Files
waggle-os/docs/superpowers/specs/2026-06-30-goal-ancestry-design.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

102 lines
5.5 KiB
Markdown

# Goal-Ancestry Context Chain — Design
**Date:** 2026-06-30 · **Author:** Claude Opus 4.8 (1M) · **Owner:** Marko (founder)
**Arc:** AI-OS external-agent recon · STEAL NOW item **#6** from
`docs/analysis/external-agent-launching-and-memory-comparison-2026-06-29.md`
**Effort:** S · **Branch:** `feat/goal-ancestry-context`
---
## 1. Goal & Non-Goals
**Goal.** Give every agent run a durable sense of **why it exists** — a short "ancestry"
breadcrumb (the purpose above the current turn) injected into the system prompt, complementing
(not duplicating) hive-mind recall and the live AwarenessLayer task state. Paperclip supplies a
mission→project→goal→task chain each run; this is Waggle's honest equivalent.
**Non-goals (YAGNI):**
- No new persistence / data model. No workspace "charter/mission" field (reserved for later).
- No UI. No feature flag (purely additive — renders nothing when there's no "why").
- The `Orchestrator` does **not** reach into the DB for ancestry — it renders what it's handed.
- The live current task stays in the existing self-awareness "Active Tasks" section (no dup).
## 2. Honest Mapping (founder-approved 2026-06-30)
Waggle has no mission→project→goal→task hierarchy. The durable "why" sources are:
| Level | Waggle source | Included? |
|---|---|---|
| `mission` | *(no workspace-charter field exists yet)* | reserved — omitted today |
| `project` | active **workspace** name (+ template) — the durable container | **yes** |
| `goal` | **`AgentDef.goal`** / persona goal — the agent's declared purpose | **yes** |
| `task` | already rendered by the self-awareness "Active Tasks" section | omitted (no dup) |
All four levels exist in the type for future-proofing; only `project` + `goal` are populated now.
## 3. Architecture — pure renderer + caller populates
**Unit A — `GoalAncestry` type (`packages/shared/src/types.ts`).**
```ts
/** Durable "why" injected into the agent system prompt (AI-OS #6). All optional. */
export interface GoalAncestry {
mission?: string; // reserved — no workspace charter field yet
project?: string; // workspace name (+ template)
goal?: string; // agent's declared goal / persona purpose
task?: string; // omitted today (lives in the awareness section)
}
```
**Unit B — Orchestrator renders it (`packages/agent/src/orchestrator.ts`).**
- `OrchestratorConfig.goalAncestry?: GoalAncestry`; stored as `private goalAncestry: GoalAncestry | null`.
- A pure helper `renderGoalAncestry(a: GoalAncestry | null): string` returns a `# Why You're Here`
block listing only the present levels as `Label: value` lines, or `''` when nothing is present.
- `buildSystemPrompt()` adds a **cached** section (keyed on `JSON.stringify(goalAncestry) || 'empty'`,
same pattern as the identity section) inserted **after identity, before self-awareness** — purpose
frames capability/awareness. The empty result is filtered out by the existing `.filter(Boolean)`.
Render format (only present levels):
```
# Why You're Here
Project: Acme Redesign (engineering)
Goal: Ship the launcher live-output pane and keep tests green
```
**Unit C — Caller populates (`packages/server/src/local/index.ts`, the per-session orchestrator).**
- Build a `GoalAncestry` from available context at construction: `project` ← active workspace
name (+ template if present), `goal` ← the resolved persona/agent goal for the session.
- `mission`/`task` left undefined. When neither `project` nor `goal` is known (e.g. bare personal
chat), pass `undefined` → section renders nothing → byte-identical to today.
## 4. Data Flow
```
session construct (local/index.ts) ── workspace + persona/agent ──▶ GoalAncestry { project, goal }
└▶ new Orchestrator({ ..., goalAncestry })
└▶ buildSystemPrompt() ── cachedSection('goal_ancestry') ──▶ "# Why You're Here\nProject: …\nGoal: …"
(empty ancestry ⇒ '' ⇒ filtered out ⇒ prompt unchanged)
```
## 5. Error Handling / Edge Cases
- All levels optional; missing → omitted line. All-empty → no section (no heading, no blank).
- Long values: truncate each level to a sane cap (≤200 chars) so a verbose goal can't bloat every turn.
- The renderer is total (never throws); a malformed ancestry object just yields the lines it can.
## 6. Testing (TDD)
- `renderGoalAncestry`: full ancestry → heading + one line per present level, in mission→project→goal→task order;
partial (only `goal`) → just that line; empty/`null``''`; over-long value → truncated.
- `buildSystemPrompt`: with ancestry → section present and ordered after identity / before self-awareness;
without → section absent (prompt unchanged); cache hit on unchanged ancestry (no recompute).
- Caller wiring: a session with workspace + persona goal yields a populated `goalAncestry`; bare session yields none.
**Gates:** `tsc --noEmit` 0 (shared/agent/server); new units RED→GREEN; existing orchestrator suite green.
## 7. File Change List
| File | Change |
|---|---|
| `packages/shared/src/types.ts` | add `GoalAncestry` interface |
| `packages/agent/src/orchestrator.ts` | `OrchestratorConfig.goalAncestry`, field, `renderGoalAncestry`, cached section in `buildSystemPrompt` |
| `packages/server/src/local/index.ts` | populate `goalAncestry` for the per-session orchestrator |
| tests (2) | `orchestrator` goal-ancestry unit tests + (light) caller-wiring assertion |
## 8. Open Questions
- **None blocking.** Mapping founder-approved. `mission` + a workspace-charter field is a separate future item.