@ouro.bot/cli 0.1.0-alpha.6 → 0.1.0-alpha.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/AdoptionSpecialist.ouro/agent.json +70 -9
  2. package/AdoptionSpecialist.ouro/psyche/SOUL.md +5 -2
  3. package/AdoptionSpecialist.ouro/psyche/identities/monty.md +2 -2
  4. package/README.md +147 -205
  5. package/assets/ouroboros.png +0 -0
  6. package/changelog.json +325 -0
  7. package/dist/heart/active-work.js +178 -0
  8. package/dist/heart/bridges/manager.js +358 -0
  9. package/dist/heart/bridges/state-machine.js +135 -0
  10. package/dist/heart/bridges/store.js +123 -0
  11. package/dist/heart/config.js +57 -23
  12. package/dist/heart/core.js +236 -90
  13. package/dist/heart/cross-chat-delivery.js +146 -0
  14. package/dist/heart/daemon/agent-discovery.js +81 -0
  15. package/dist/heart/daemon/auth-flow.js +351 -0
  16. package/dist/heart/daemon/daemon-cli.js +1173 -227
  17. package/dist/heart/daemon/daemon-entry.js +55 -6
  18. package/dist/heart/daemon/daemon-runtime-sync.js +212 -0
  19. package/dist/heart/daemon/daemon.js +189 -10
  20. package/dist/heart/daemon/hatch-animation.js +10 -3
  21. package/dist/heart/daemon/hatch-flow.js +4 -82
  22. package/dist/heart/daemon/hooks/bundle-meta.js +92 -0
  23. package/dist/heart/daemon/launchd.js +159 -0
  24. package/dist/heart/daemon/log-tailer.js +4 -3
  25. package/dist/heart/daemon/message-router.js +17 -8
  26. package/dist/heart/daemon/ouro-bot-entry.js +0 -0
  27. package/dist/heart/daemon/ouro-bot-global-installer.js +128 -0
  28. package/dist/heart/daemon/ouro-entry.js +0 -0
  29. package/dist/heart/daemon/ouro-path-installer.js +178 -0
  30. package/dist/heart/daemon/ouro-uti.js +11 -2
  31. package/dist/heart/daemon/process-manager.js +14 -1
  32. package/dist/heart/daemon/run-hooks.js +37 -0
  33. package/dist/heart/daemon/runtime-logging.js +58 -15
  34. package/dist/heart/daemon/runtime-metadata.js +219 -0
  35. package/dist/heart/daemon/runtime-mode.js +67 -0
  36. package/dist/heart/daemon/sense-manager.js +307 -0
  37. package/dist/heart/daemon/socket-client.js +202 -0
  38. package/dist/heart/daemon/specialist-orchestrator.js +53 -84
  39. package/dist/heart/daemon/specialist-prompt.js +64 -5
  40. package/dist/heart/daemon/specialist-tools.js +213 -58
  41. package/dist/heart/daemon/staged-restart.js +114 -0
  42. package/dist/heart/daemon/subagent-installer.js +48 -7
  43. package/dist/heart/daemon/thoughts.js +379 -0
  44. package/dist/heart/daemon/update-checker.js +111 -0
  45. package/dist/heart/daemon/update-hooks.js +138 -0
  46. package/dist/heart/daemon/wrapper-publish-guard.js +86 -0
  47. package/dist/heart/delegation.js +62 -0
  48. package/dist/heart/identity.js +122 -19
  49. package/dist/heart/kicks.js +1 -19
  50. package/dist/heart/model-capabilities.js +40 -0
  51. package/dist/heart/progress-story.js +42 -0
  52. package/dist/heart/providers/anthropic.js +74 -9
  53. package/dist/heart/providers/azure.js +86 -7
  54. package/dist/heart/providers/minimax.js +4 -0
  55. package/dist/heart/providers/openai-codex.js +12 -3
  56. package/dist/heart/safe-workspace.js +228 -0
  57. package/dist/heart/sense-truth.js +61 -0
  58. package/dist/heart/session-activity.js +169 -0
  59. package/dist/heart/session-recall.js +116 -0
  60. package/dist/heart/streaming.js +100 -22
  61. package/dist/heart/target-resolution.js +123 -0
  62. package/dist/heart/turn-coordinator.js +28 -0
  63. package/dist/mind/associative-recall.js +14 -2
  64. package/dist/mind/bundle-manifest.js +70 -0
  65. package/dist/mind/context.js +27 -11
  66. package/dist/mind/first-impressions.js +16 -2
  67. package/dist/mind/friends/channel.js +35 -0
  68. package/dist/mind/friends/group-context.js +144 -0
  69. package/dist/mind/friends/store-file.js +19 -0
  70. package/dist/mind/friends/trust-explanation.js +74 -0
  71. package/dist/mind/friends/types.js +8 -0
  72. package/dist/mind/memory.js +27 -26
  73. package/dist/mind/pending.js +72 -9
  74. package/dist/mind/phrases.js +1 -0
  75. package/dist/mind/prompt.js +299 -77
  76. package/dist/mind/token-estimate.js +8 -12
  77. package/dist/nerves/cli-logging.js +15 -2
  78. package/dist/nerves/coverage/run-artifacts.js +1 -1
  79. package/dist/repertoire/ado-client.js +4 -2
  80. package/dist/repertoire/coding/feedback.js +134 -0
  81. package/dist/repertoire/coding/index.js +4 -1
  82. package/dist/repertoire/coding/manager.js +62 -4
  83. package/dist/repertoire/coding/spawner.js +3 -3
  84. package/dist/repertoire/coding/tools.js +41 -2
  85. package/dist/repertoire/data/ado-endpoints.json +188 -0
  86. package/dist/repertoire/tasks/board.js +12 -0
  87. package/dist/repertoire/tasks/index.js +23 -9
  88. package/dist/repertoire/tasks/transitions.js +1 -2
  89. package/dist/repertoire/tools-base.js +629 -251
  90. package/dist/repertoire/tools-bluebubbles.js +93 -0
  91. package/dist/repertoire/tools-teams.js +58 -25
  92. package/dist/repertoire/tools.js +92 -48
  93. package/dist/senses/bluebubbles-client.js +210 -5
  94. package/dist/senses/bluebubbles-entry.js +2 -0
  95. package/dist/senses/bluebubbles-inbound-log.js +109 -0
  96. package/dist/senses/bluebubbles-media.js +339 -0
  97. package/dist/senses/bluebubbles-model.js +12 -4
  98. package/dist/senses/bluebubbles-mutation-log.js +45 -5
  99. package/dist/senses/bluebubbles-runtime-state.js +109 -0
  100. package/dist/senses/bluebubbles-session-cleanup.js +72 -0
  101. package/dist/senses/bluebubbles.js +890 -45
  102. package/dist/senses/cli-layout.js +87 -0
  103. package/dist/senses/cli.js +345 -144
  104. package/dist/senses/continuity.js +94 -0
  105. package/dist/senses/debug-activity.js +148 -0
  106. package/dist/senses/inner-dialog-worker.js +47 -18
  107. package/dist/senses/inner-dialog.js +330 -84
  108. package/dist/senses/pipeline.js +278 -0
  109. package/dist/senses/teams.js +570 -129
  110. package/dist/senses/trust-gate.js +112 -2
  111. package/package.json +14 -3
  112. package/subagents/README.md +46 -33
  113. package/subagents/work-doer.md +28 -24
  114. package/subagents/work-merger.md +24 -30
  115. package/subagents/work-planner.md +44 -27
  116. package/dist/heart/daemon/specialist-session.js +0 -142
  117. package/dist/inner-worker-entry.js +0 -4
@@ -39,6 +39,9 @@ const fs = __importStar(require("fs"));
39
39
  const path = __importStar(require("path"));
40
40
  const identity_1 = require("../heart/identity");
41
41
  const runtime_1 = require("../nerves/runtime");
42
+ const types_1 = require("../mind/friends/types");
43
+ const pending_1 = require("../mind/pending");
44
+ // Canned reply; eventually agents should compose their own first-contact message
42
45
  exports.STRANGER_AUTO_REPLY = "I'm sorry, I'm not allowed to talk to strangers";
43
46
  function buildExternalKey(provider, externalId, tenantId) {
44
47
  return `${provider}:${tenantId ?? ""}:${externalId}`;
@@ -77,16 +80,107 @@ function appendPrimaryNotification(bundleRoot, provider, externalId, tenantId, n
77
80
  fs.mkdirSync(inboxDir, { recursive: true });
78
81
  fs.appendFileSync(notificationsPath, `${JSON.stringify(payload)}\n`, "utf8");
79
82
  }
83
+ function writeInnerPendingNotice(bundleRoot, noticeContent, nowIso) {
84
+ const innerPendingDir = path.join(bundleRoot, "state", "pending", pending_1.INNER_DIALOG_PENDING.friendId, pending_1.INNER_DIALOG_PENDING.channel, pending_1.INNER_DIALOG_PENDING.key);
85
+ const fileName = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}.json`;
86
+ const filePath = path.join(innerPendingDir, fileName);
87
+ const payload = {
88
+ from: "instinct",
89
+ content: noticeContent,
90
+ timestamp: Date.now(),
91
+ at: nowIso,
92
+ };
93
+ fs.mkdirSync(innerPendingDir, { recursive: true });
94
+ fs.writeFileSync(filePath, JSON.stringify(payload), "utf-8");
95
+ }
80
96
  function enforceTrustGate(input) {
97
+ const { senseType } = input;
98
+ // Local (CLI) and internal (inner dialog) — always allow
99
+ if (senseType === "local" || senseType === "internal") {
100
+ return { allowed: true };
101
+ }
102
+ // Closed senses (Teams) — org already gates access, allow all trust levels
103
+ if (senseType === "closed") {
104
+ return { allowed: true };
105
+ }
106
+ // Open senses (BlueBubbles/iMessage) — enforce trust rules
81
107
  const trustLevel = input.friend.trustLevel ?? "friend";
82
- if (trustLevel !== "stranger") {
108
+ // Family and friend — always allow on open
109
+ if ((0, types_1.isTrustedLevel)(trustLevel)) {
83
110
  return { allowed: true };
84
111
  }
85
112
  const bundleRoot = input.bundleRoot ?? (0, identity_1.getAgentRoot)();
86
- const repliesPath = path.join(bundleRoot, "stranger-replies.json");
87
113
  const nowIso = (input.now ?? (() => new Date()))().toISOString();
114
+ // Acquaintance rules
115
+ if (trustLevel === "acquaintance") {
116
+ return handleAcquaintance(input, bundleRoot, nowIso);
117
+ }
118
+ // Stranger rules (trustLevel === "stranger")
119
+ return handleStranger(input, bundleRoot, nowIso);
120
+ }
121
+ function handleAcquaintance(input, bundleRoot, nowIso) {
122
+ const { isGroupChat, groupHasFamilyMember, hasExistingGroupWithFamily } = input;
123
+ // Group chat with family member present — allow
124
+ if (isGroupChat && groupHasFamilyMember) {
125
+ return { allowed: true };
126
+ }
127
+ let result;
128
+ let noticeDetail;
129
+ if (isGroupChat) {
130
+ // Group chat without family member — reject silently
131
+ result = { allowed: false, reason: "acquaintance_group_no_family" };
132
+ noticeDetail = `acquaintance "${input.friend.name}" messaged in a group chat without a family member present`;
133
+ }
134
+ else if (hasExistingGroupWithFamily) {
135
+ // 1:1 but shares a group with family — redirect
136
+ result = {
137
+ allowed: false,
138
+ reason: "acquaintance_1on1_has_group",
139
+ autoReply: "Hey! Reach me in our group chat instead.",
140
+ };
141
+ noticeDetail = `acquaintance "${input.friend.name}" DMed me directly — redirected to our group chat`;
142
+ }
143
+ else {
144
+ // 1:1, no shared group with family — redirect to any group
145
+ result = {
146
+ allowed: false,
147
+ reason: "acquaintance_1on1_no_group",
148
+ autoReply: "Hey! Reach me in a group chat instead.",
149
+ };
150
+ noticeDetail = `acquaintance "${input.friend.name}" DMed me directly — asked to reach me in a group chat`;
151
+ }
152
+ (0, runtime_1.emitNervesEvent)({
153
+ level: "warn",
154
+ component: "senses",
155
+ event: "senses.trust_gate",
156
+ message: "acquaintance message blocked",
157
+ meta: {
158
+ channel: input.channel,
159
+ provider: input.provider,
160
+ reason: result.reason,
161
+ },
162
+ });
163
+ try {
164
+ writeInnerPendingNotice(bundleRoot, noticeDetail, nowIso);
165
+ }
166
+ catch (error) {
167
+ (0, runtime_1.emitNervesEvent)({
168
+ level: "error",
169
+ component: "senses",
170
+ event: "senses.trust_gate_error",
171
+ message: "failed to write inner pending notice",
172
+ meta: {
173
+ reason: error instanceof Error ? error.message : String(error),
174
+ },
175
+ });
176
+ }
177
+ return result;
178
+ }
179
+ function handleStranger(input, bundleRoot, nowIso) {
180
+ const repliesPath = path.join(bundleRoot, "stranger-replies.json");
88
181
  const externalKey = buildExternalKey(input.provider, input.externalId, input.tenantId);
89
182
  const state = loadRepliesState(repliesPath);
183
+ // Subsequent contact — silent drop
90
184
  if (state[externalKey]) {
91
185
  (0, runtime_1.emitNervesEvent)({
92
186
  level: "warn",
@@ -103,6 +197,7 @@ function enforceTrustGate(input) {
103
197
  reason: "stranger_silent_drop",
104
198
  };
105
199
  }
200
+ // First contact — auto-reply, persist state, notify agent
106
201
  state[externalKey] = nowIso;
107
202
  try {
108
203
  persistRepliesState(repliesPath, state);
@@ -132,6 +227,21 @@ function enforceTrustGate(input) {
132
227
  },
133
228
  });
134
229
  }
230
+ const noticeDetail = `stranger "${input.friend.name}" tried to reach me via ${input.channel}. Auto-replied once.`;
231
+ try {
232
+ writeInnerPendingNotice(bundleRoot, noticeDetail, nowIso);
233
+ }
234
+ catch (error) {
235
+ (0, runtime_1.emitNervesEvent)({
236
+ level: "error",
237
+ component: "senses",
238
+ event: "senses.trust_gate_error",
239
+ message: "failed to write inner pending notice",
240
+ meta: {
241
+ reason: error instanceof Error ? error.message : String(error),
242
+ },
243
+ });
244
+ }
135
245
  (0, runtime_1.emitNervesEvent)({
136
246
  level: "warn",
137
247
  component: "senses",
package/package.json CHANGED
@@ -1,15 +1,18 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.60",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
+ "cli": "dist/heart/daemon/ouro-bot-entry.js",
6
7
  "ouro": "dist/heart/daemon/ouro-entry.js",
7
8
  "ouro.bot": "dist/heart/daemon/ouro-bot-entry.js"
8
9
  },
9
10
  "files": [
10
11
  "dist/",
11
12
  "AdoptionSpecialist.ouro/",
12
- "subagents/"
13
+ "subagents/",
14
+ "assets/",
15
+ "changelog.json"
13
16
  ],
14
17
  "exports": {
15
18
  ".": "./dist/heart/daemon/daemon-cli.js",
@@ -30,11 +33,19 @@
30
33
  },
31
34
  "dependencies": {
32
35
  "@anthropic-ai/sdk": "^0.78.0",
36
+ "@azure/identity": "^4.13.0",
33
37
  "@microsoft/teams.apps": "^2.0.5",
34
38
  "@microsoft/teams.dev": "^2.0.5",
35
- "openai": "^6.27.0"
39
+ "fast-glob": "^3.3.3",
40
+ "openai": "^6.27.0",
41
+ "semver": "^7.7.4"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/ouroborosbot/ouroboros"
36
46
  },
37
47
  "devDependencies": {
48
+ "@types/semver": "^7.7.1",
38
49
  "@vitest/coverage-v8": "^4.0.18",
39
50
  "eslint": "^10.0.2",
40
51
  "typescript": "^5.7.0",
@@ -1,52 +1,68 @@
1
- # Sub-agents
1
+ # Workflow Helpers
2
2
 
3
- These are source-of-truth workflow definitions (`work-planner`, `work-doer`, `work-merger`) for planning, execution, and merge. They can be consumed either as Claude sub-agents (`.md` files with YAML frontmatter) or as Codex-style skills (`SKILL.md`).
3
+ These files are the source-of-truth workflow helpers for:
4
4
 
5
- ## Installation
5
+ - `work-planner`
6
+ - `work-doer`
7
+ - `work-merger`
6
8
 
7
- ### Claude Code (sub-agents)
9
+ They are written to stay generic enough for different agent shells, while following this repo’s local rules through `AGENTS.md`.
8
10
 
9
- Copy or symlink these files into Claude's sub-agent directory:
11
+ ## What They Do
12
+
13
+ - `work-planner.md`
14
+ Creates and refines planning docs, then converts approved plans into doing docs.
15
+ - `work-doer.md`
16
+ Executes approved doing docs unit by unit with strict validation discipline.
17
+ - `work-merger.md`
18
+ Syncs with `main`, resolves conflicts, creates the PR, handles CI, and merges.
19
+
20
+ ## Important Repo-Specific Truth
21
+
22
+ These helpers do not hardcode task-doc paths. They are expected to read project instructions to discover them.
23
+
24
+ In this repo, that means:
25
+
26
+ - task docs live in `~/AgentBundles/<agent>.ouro/tasks/one-shots/`
27
+ - not inside the repo
28
+
29
+ ## Installing For Claude Code
10
30
 
11
31
  ```bash
12
- # Claude Code
32
+ mkdir -p ~/.claude/agents
13
33
  cp subagents/*.md ~/.claude/agents/
14
- # or
15
- ln -s "$(pwd)"/subagents/*.md ~/.claude/agents/
16
34
  ```
17
35
 
18
- ### Codex / skill-based harnesses
19
-
20
- For tools that support skills but not Claude sub-agents, install these as skills:
36
+ ## Installing For Codex-Style Skills
21
37
 
22
38
  ```bash
23
- mkdir -p ~/.codex/skills/work-planner ~/.codex/skills/work-doer ~/.codex/skills/work-merger
39
+ mkdir -p ~/.agents/skills/work-planner ~/.agents/skills/work-doer ~/.agents/skills/work-merger
24
40
 
25
41
  # Hard-link to keep one source of truth
26
- ln -f "$(pwd)/subagents/work-planner.md" ~/.codex/skills/work-planner/SKILL.md
27
- ln -f "$(pwd)/subagents/work-doer.md" ~/.codex/skills/work-doer/SKILL.md
28
- ln -f "$(pwd)/subagents/work-merger.md" ~/.codex/skills/work-merger/SKILL.md
42
+ ln -f "$(pwd)/subagents/work-planner.md" ~/.agents/skills/work-planner/SKILL.md
43
+ ln -f "$(pwd)/subagents/work-doer.md" ~/.agents/skills/work-doer/SKILL.md
44
+ ln -f "$(pwd)/subagents/work-merger.md" ~/.agents/skills/work-merger/SKILL.md
29
45
  ```
30
46
 
31
- **Important:** Hard-links break when editors save by replacing the file (new inode). After editing any `subagents/*.md` file, re-run the `ln -f` command for that file to restore the link. You can verify with `stat -f '%i'` — both files should share the same inode.
47
+ **Important:** For Codex/OpenAI skill installs, use the generic `~/.agents/skills` root and use hard links (`ln`, not `ln -s`). Installing the same skill into both `~/.agents/skills` and `~/.codex/skills` can produce duplicate entries in Codex. Symlinked `SKILL.md` files may load but are not advertised reliably by Codex surfaces. Hard-links break when editors save by replacing the file (new inode). After editing any `subagents/*.md` file, re-run the `ln -f` command for that file to restore the link. You can verify with `stat -f '%i'` — both files should share the same inode.
32
48
 
33
49
  Optional UI metadata:
34
50
 
35
51
  ```bash
36
- mkdir -p ~/.codex/skills/work-planner/agents ~/.codex/skills/work-doer/agents ~/.codex/skills/work-merger/agents
37
- cat > ~/.codex/skills/work-planner/agents/openai.yaml << 'EOF'
52
+ mkdir -p ~/.agents/skills/work-planner/agents ~/.agents/skills/work-doer/agents ~/.agents/skills/work-merger/agents
53
+ cat > ~/.agents/skills/work-planner/agents/openai.yaml << 'EOF'
38
54
  interface:
39
55
  display_name: "Work Planner"
40
56
  short_description: "Create and gate planning/doing task docs"
41
57
  default_prompt: "Use $work-planner to create or update a planning doc, then stop at NEEDS_REVIEW."
42
58
  EOF
43
- cat > ~/.codex/skills/work-doer/agents/openai.yaml << 'EOF'
59
+ cat > ~/.agents/skills/work-doer/agents/openai.yaml << 'EOF'
44
60
  interface:
45
61
  display_name: "Work Doer"
46
62
  short_description: "Execute approved doing docs with strict TDD"
47
63
  default_prompt: "Use $work-doer to execute an approved doing doc unit by unit."
48
64
  EOF
49
- cat > ~/.codex/skills/work-merger/agents/openai.yaml << 'EOF'
65
+ cat > ~/.agents/skills/work-merger/agents/openai.yaml << 'EOF'
50
66
  interface:
51
67
  display_name: "Work Merger"
52
68
  short_description: "Merge feature branch into main via PR after work-doer completes"
@@ -54,20 +70,17 @@ interface:
54
70
  EOF
55
71
  ```
56
72
 
57
- Restart the harness after install so new skills are discovered.
73
+ ## Keeping Local Skill Copies Fresh
74
+
75
+ After editing any `subagents/*.md` file, resync your local installed copies.
58
76
 
59
- ## Available sub-agents
77
+ The repo workflow usually checks this with diffs like:
60
78
 
61
- | File | Purpose |
62
- |------|---------|
63
- | `work-planner.md` | Interactive task planner. Generates planning docs through conversation, then converts to doing docs after human approval. |
64
- | `work-doer.md` | Task executor. Reads a doing doc and works through each unit sequentially with strict TDD. |
65
- | `work-merger.md` | Sync-and-merge agent. Merges feature branch into main via PR after work-doer completes. Handles conflicts, CI failures, and race conditions. |
79
+ ```bash
80
+ diff -q ~/.agents/skills/work-planner/SKILL.md subagents/work-planner.md
81
+ diff -q ~/.agents/skills/work-doer/SKILL.md subagents/work-doer.md
82
+ ```
66
83
 
67
- ## Workflow
84
+ ## Restart Behavior
68
85
 
69
- 1. Human describes a task
70
- 2. Agent invokes **work-planner** to create a planning doc → human approves → planner converts to doing doc
71
- 3. Agent invokes **work-doer** to execute the doing doc unit by unit
72
- 4. Each unit is committed independently with progress tracked in the doing doc
73
- 5. Agent invokes **work-merger** to merge the feature branch into main via PR (fetch, merge, resolve conflicts, CI gate, merge PR, cleanup)
86
+ Some tools only discover new skills on startup. If a shell/app does not see updates immediately, restart that shell/app after syncing.
@@ -8,17 +8,19 @@ You are a task executor. Read a doing.md file and execute all units sequentially
8
8
 
9
9
  ## On Startup
10
10
 
11
- 1. **Find doing doc**: Look for `YYYY-MM-DD-HHMM-doing-*.md` in repo root
12
- 2. If multiple found, ask which one
13
- 3. If none found, ask user for location
14
- 4. **Check execution_mode**: Read the doing doc's `Execution Mode` field
15
- 5. **Verify artifacts directory exists**: `{task-name}/` next to `{task-name}.md`
11
+ 1. **Find task-doc directory**: Read project instructions (for example `AGENTS.md`) to determine where planning/doing docs live for this repo
12
+ 2. **Confirm worktree**: Run from the dedicated task worktree required by the project. If the current checkout is shared, ambiguous, or not on the task branch, switch/create the correct worktree first when project instructions allow it. Only STOP to ask the user when they explicitly want to control naming/layout or automatic creation fails.
13
+ 3. **Find doing doc**: Look for `YYYY-MM-DD-HHMM-doing-*.md` in that project-defined task-doc directory
14
+ 4. If multiple found, ask which one
15
+ 5. If none found, ask user for location
16
+ 6. **Check execution_mode**: Read the doing doc's `Execution Mode` field
17
+ 7. **Verify artifacts directory exists**: `{task-name}/` next to `{task-name}.md`
16
18
  - If missing, create it: `mkdir {task-name}`
17
- 6. **Detect resume vs fresh start:**
19
+ 8. **Detect resume vs fresh start:**
18
20
  - Count completed units (✅) vs total units
19
21
  - Check git status for uncommitted changes
20
22
 
21
- 7. **Announce status clearly:**
23
+ 8. **Announce status clearly:**
22
24
 
23
25
  **If fresh start (0 units complete):**
24
26
  ```
@@ -214,20 +216,22 @@ When all units are `✅`:
214
216
  ## Rules
215
217
 
216
218
  1. **File naming**: Expect `YYYY-MM-DD-HHMM-doing-{name}.md` format
217
- 2. **Artifacts directory**: Use `{task-name}/` for all outputs, logs, data
218
- 3. **Execution mode**: Honor `pending | spawn | direct` from doing doc
219
- 4. **TDD strictly enforced** tests before implementation, always
220
- 5. **100% coverage** no exceptions, no exclude attributes
221
- 6. **Atomic commits** — one logical unit per commit, push after each
222
- 7. **Timestamps from git** — `git log -1 --format="%Y-%m-%d %H:%M"`
223
- 8. **Push after each unit phase complete**
224
- 9. **Update doing.md after each unit** — status and progress log
225
- 10. **Spawn sub-agents for fixes** don't ask, just do it
226
- 11. **Update docs immediately** — when decisions made, commit right away
227
- 12. **Stop on actual blocker** — unclear requirements or need user input
228
- 13. **/compact proactively** — preserve context between units
229
- 14. **No warnings** — treat warnings as errors
230
- 15. **Run full test suite** — before marking unit complete, not just new tests
231
- 16. **Always compile** — run the project's build command after every implementation/refactor unit. Tests passing is necessary but not sufficient.
232
- 17. **Checklist hygiene is mandatory** — keep doing/planning `Completion Criteria` checklists synchronized with verified completion evidence.
233
- 18. **Verify APIs before importing** — before writing `import { Foo } from './bar'`, use `grep` or `read_file` to confirm `Foo` is actually exported from that module. Never assume an export exists always check the source first. This prevents wasted cycles on "module has no exported member" errors.
219
+ 2. **Location**: Read and update doing docs in the project-defined task-doc directory, which may live outside the repo
220
+ 3. **Artifacts directory**: Use `{task-name}/` for all outputs, logs, data
221
+ 4. **Execution mode**: Honor `pending | spawn | direct` from doing doc
222
+ 5. **Respect the approved structure**: A `READY_FOR_EXECUTION` doing doc should already be ambiguity-clean. Do not rewrite unit structure unless the user changes scope or the doing doc is actually blocked/inaccurate.
223
+ 6. **TDD strictly enforced** — tests before implementation, always
224
+ 7. **100% coverage** — no exceptions, no exclude attributes
225
+ 8. **Atomic commits** one logical unit per commit, push after each
226
+ 9. **Timestamps from git** — `git log -1 --format="%Y-%m-%d %H:%M"`
227
+ 10. **Push after each unit phase complete**
228
+ 11. **Update doing.md after each unit** — status and progress log
229
+ 12. **Spawn sub-agents for fixes** — don't ask, just do it
230
+ 13. **Update docs immediately** — when decisions made, commit right away
231
+ 14. **Stop on actual blocker** — unclear requirements or need user input
232
+ 15. **/compact proactively** — preserve context between units
233
+ 16. **No warnings** — treat warnings as errors
234
+ 17. **Run full test suite** — before marking unit complete, not just new tests
235
+ 18. **Always compile** — run the project's build command after every implementation/refactor unit. Tests passing is necessary but not sufficient.
236
+ 19. **Checklist hygiene is mandatory** — keep doing/planning `Completion Criteria` checklists synchronized with verified completion evidence.
237
+ 19. **Verify APIs before importing** — before writing `import { Foo } from './bar'`, use `grep` or `read_file` to confirm `Foo` is actually exported from that module. Never assume an export exists — always check the source first. This prevents wasted cycles on "module has no exported member" errors.
@@ -19,12 +19,16 @@ The branch follows the `<agent>/<slug>` convention (e.g., `ouroboros/context-ker
19
19
 
20
20
  Do not hardcode agent names. Derive `<agent>` from the branch at runtime.
21
21
 
22
+ ### 1a. Determine the project-defined task-doc directory
23
+
24
+ Read project instructions (for example `AGENTS.md`) to determine where this repo keeps planning/doing docs. Set `TASK_DIR` to that project-defined location. Do not assume task docs live in the repo.
25
+
22
26
  ### 2. Find own doing doc
23
27
 
24
- The caller provides the doing doc path (e.g., `ouroboros/tasks/2026-03-03-1032-doing-sync-and-merge.md`). If not provided, find the most recent doing doc:
28
+ The caller provides the doing doc path. If not provided, read project instructions (for example `AGENTS.md`) to find the project-defined task-doc directory, then find the most recent doing doc there:
25
29
 
26
30
  ```bash
27
- ls -t ${AGENT}/tasks/*-doing-*.md | head -1
31
+ ls -t "${TASK_DIR}"/*-doing-*.md | head -1
28
32
  ```
29
33
 
30
34
  Read this doing doc to understand what was just implemented. You will need it for conflict resolution context.
@@ -134,35 +138,28 @@ You already have the path from On Startup. Read the doing doc to understand:
134
138
  - The objective, completion criteria, and unit descriptions
135
139
  - What files were changed and why
136
140
 
137
- ### Step 2: Discover other agents' doing docs (git-informed)
138
-
139
- Find exactly which doing docs landed on main since this branch diverged. Do NOT scan by filename timestamps or guess -- use git history:
140
-
141
- ```bash
142
- git log origin/main --not HEAD --name-only --diff-filter=A -- '*/tasks/*-doing-*.md'
143
- ```
141
+ ### Step 2: Gather incoming-main intent (git-informed)
144
142
 
145
- This returns the paths of doing docs that were **added to main** after this branch's merge base. These are the docs from the other agent's completed work that caused the conflicts.
146
-
147
- If no doing docs are found with `--diff-filter=A` (added), also check for modifications:
143
+ Do not assume task docs live in this repo. Instead, use git history and diffs to understand what landed on `main` since this branch diverged:
148
144
 
149
145
  ```bash
150
- git log origin/main --not HEAD --name-only --diff-filter=M -- '*/tasks/*-doing-*.md'
146
+ git log origin/main --not HEAD --oneline
147
+ git diff --name-only HEAD...origin/main
151
148
  ```
152
149
 
153
- **Why git-informed discovery matters:**
154
- - Timestamp-sorted filename scans can miss relevant docs or include irrelevant ones
155
- - Git history tells you exactly what landed on main since you branched
156
- - This is deterministic and correct regardless of doc naming or timing
150
+ If a clearly relevant local task doc exists outside the repo (for example in another local bundle/worktree task directory), you may read it for extra context. Treat that as optional context, not a required precondition.
157
151
 
158
- ### Step 3: Read discovered doing docs
152
+ **Why this is the primary source of truth:**
153
+ - Task docs may live outside the repo entirely
154
+ - Git history tells you exactly what changed on `main` since you branched
155
+ - This keeps work-merger generic instead of assuming one repo's task-doc layout
159
156
 
160
- For each doing doc found in Step 2, read it to understand:
161
- - What the other agent implemented
162
- - Their objective and completion criteria
163
- - Which files they changed and why
157
+ ### Step 3: Combine own task intent with incoming-main changes
164
158
 
165
- This gives you both intents: what your branch did, and what landed on main.
159
+ Use:
160
+ - your own doing doc as the source of truth for this branch's intent
161
+ - incoming git commits/diffs as the source of truth for what landed on `main`
162
+ - any optional local task docs only when they materially clarify a conflict
166
163
 
167
164
  ### Step 4: Resolve conflicts
168
165
 
@@ -182,7 +179,7 @@ With both intents understood, resolve each conflict:
182
179
  If the merge was syntactically clean but tests fail (Case B):
183
180
 
184
181
  1. Read the test failure output to identify which tests broke
185
- 2. Cross-reference with both doing docs to understand the conflict
182
+ 2. Cross-reference with your doing doc plus the incoming git changes to understand the conflict
186
183
  3. Fix the code to satisfy both agents' intents
187
184
  4. Re-run tests: `npm test`
188
185
  5. Repeat until tests pass
@@ -204,7 +201,7 @@ git commit -m "fix: resolve semantic conflicts after merging main"
204
201
  npm test
205
202
  ```
206
203
 
207
- All tests must pass before proceeding to PR Workflow. If tests still fail after resolution, re-examine the doing docs and try again. If genuinely stuck after multiple attempts, escalate to the user (see **Escalation**).
204
+ All tests must pass before proceeding to PR Workflow. If tests still fail after resolution, re-examine your doing doc, the incoming git changes, and any optional supporting task docs, then try again. If genuinely stuck after multiple attempts, escalate to the user (see **Escalation**).
208
205
 
209
206
  ---
210
207
 
@@ -227,20 +224,17 @@ git push --force-with-lease origin ${BRANCH}
227
224
 
228
225
  ### Step 2: Create the pull request
229
226
 
230
- Before creating the PR, build a comprehensive description of **all** changes on this branch relative to main — not just the most recent task. Use git to understand the full scope:
227
+ Before creating the PR, build a comprehensive description of **all** changes on this branch relative to main — not just the most recent task. Use your doing doc plus git to understand the full scope:
231
228
 
232
229
  ```bash
233
230
  # All commits on this branch not on main
234
231
  git log origin/main..HEAD --oneline
235
232
 
236
- # All doing docs on this branch (completed tasks)
237
- git log origin/main..HEAD --name-only --diff-filter=A -- '*/tasks/*-doing-*.md'
238
-
239
233
  # Summary of all files changed
240
234
  git diff origin/main --stat
241
235
  ```
242
236
 
243
- Read each doing doc found above. The PR body should summarize every completed task on the branch, grouped logically. Include:
237
+ Read the doing doc you are executing, plus any other explicitly provided task docs for this branch. The PR body should summarize every completed task on the branch, grouped logically when needed. Include:
244
238
  - A section per task (or group of related tasks) with a brief summary of what was implemented
245
239
  - A final "Files changed" summary (e.g., "164 files changed — new context kernel, codebase restructure, sync-and-merge system")
246
240
 
@@ -8,8 +8,17 @@ You are a task planner for coding work. Help the user define scope, then convert
8
8
 
9
9
  ## On Startup
10
10
 
11
+ **Determine task doc directory:**
12
+ 1. Read project instructions (for example `AGENTS.md`) to find the canonical task-doc location for the current repo
13
+ 2. Derive `AGENT` from the current git branch when the project uses agent-scoped task docs
14
+ 3. Confirm the task is running from a dedicated task worktree when the project requires parallel agent work; if the checkout is shared or ambiguous, create/switch to the dedicated worktree yourself when project instructions allow it, and only STOP to ask the caller when they explicitly want to control naming/layout or automatic creation fails
15
+ 4. Set `TASK_DIR` to the project-defined planning/doing directory
16
+ 5. If the project-defined parent location exists but `TASK_DIR` does not, create it
17
+ 6. If the project does not define a task-doc location, STOP and ask the user or caller where planning/doing docs should live
18
+ 7. Do not assume task docs live in the repo root; many projects keep them externally
19
+
11
20
  **Check for existing planning docs:**
12
- 1. Look for `YYYY-MM-DD-HHMM-planning-*.md` files in repo root
21
+ 1. Look for `YYYY-MM-DD-HHMM-planning-*.md` files in `TASK_DIR`
13
22
  2. If found, ask: `"found planning-{name}.md from [date]. resume or start new?"`
14
23
  3. If resuming: run Template Compliance Check (see below), then continue
15
24
  4. If new: proceed with Phase 1
@@ -100,7 +109,7 @@ fix and continue? (y/n)
100
109
 
101
110
  1. User describes the task
102
111
  2. Generate timestamp: `date '+%Y-%m-%d-%H%M'`
103
- 3. Create `YYYY-MM-DD-HHMM-planning-{short-desc}.md` using PLANNING TEMPLATE — **follow template exactly, no extra sections**
112
+ 3. Create `TASK_DIR/YYYY-MM-DD-HHMM-planning-{short-desc}.md` using PLANNING TEMPLATE — **follow template exactly, no extra sections**
104
113
  4. Commit immediately: `git commit -m "docs(planning): create planning-{short-desc}.md"`
105
114
  5. Ask clarifying questions about scope, completion criteria, unknowns
106
115
  6. Refine based on answers — **commit after each significant change**
@@ -150,13 +159,13 @@ User answers questions → agent updates doc → agent sets status to `NEEDS_REV
150
159
 
151
160
  **Only proceed after user says "approved" or equivalent.**
152
161
 
153
- **CRITICAL: Planning doc is KEPT. Conversion creates a NEW doing doc alongside it.**
162
+ **CRITICAL: Planning doc is KEPT. Conversion creates a NEW doing doc alongside it in `TASK_DIR`.**
154
163
 
155
- Run these passes — announce each. **ALL 4 PASSES ARE MANDATORY. You must run every pass, even if you think nothing changed. Each pass MUST have its own commit (use "no changes needed" in the commit message if the pass found nothing to fix). Do NOT skip or combine passes.**
164
+ Run these passes — announce each. **ALL 5 PASSES ARE MANDATORY. You must run every pass, even if you think nothing changed. Each pass MUST have its own commit (use "no changes needed" in the commit message if the pass found nothing to fix). Do NOT skip or combine passes.**
156
165
 
157
166
  **Pass 1 — First Draft:**
158
167
  - Create `YYYY-MM-DD-HHMM-doing-{short-desc}.md` (same timestamp and short-desc as planning)
159
- - Create adjacent artifacts directory: `YYYY-MM-DD-HHMM-doing-{short-desc}/` for any files, outputs, or working data
168
+ - Create adjacent artifacts directory in `TASK_DIR`: `YYYY-MM-DD-HHMM-doing-{short-desc}/` for any files, outputs, or working data
160
169
  - Use DOING TEMPLATE — **follow exactly**, including emoji status on every unit header (`### ⬜ Unit X:`)
161
170
  - Fill from planning doc
162
171
  - Decide execution_mode: `pending` (needs approval), `spawn` (spawn sub-agent per unit), or `direct` (run directly)
@@ -173,7 +182,14 @@ Run these passes — announce each. **ALL 4 PASSES ARE MANDATORY. You must run e
173
182
  - Update units if reality differs from what was assumed during planning
174
183
  - Commit: `git commit -m "docs(doing): validation pass"` (or `"docs(doing): validation pass - no changes needed"` if nothing to fix)
175
184
 
176
- **Pass 4 — Quality:**
185
+ **Pass 4 — Ambiguity:**
186
+ - Remove doer-facing ambiguity before execution starts
187
+ - Tighten units so a `READY_FOR_EXECUTION` doing doc does not require structural rewrites by `work-doer`
188
+ - Resolve fuzzy phrases like "appropriate files", "as needed", or "wherever the bug is" into concrete targets unless the project instructions explicitly require that flexibility
189
+ - If uncertainty remains, keep it in the planning doc's `Open Questions`, set status to `NEEDS_REVIEW`, and STOP instead of shipping an ambiguous doing doc
190
+ - Commit: `git commit -m "docs(doing): ambiguity pass"` (or `"docs(doing): ambiguity pass - no changes needed"` if nothing to fix)
191
+
192
+ **Pass 5 — Quality:**
177
193
  - All units have acceptance criteria?
178
194
  - No TBD items?
179
195
  - Completion criteria testable?
@@ -347,27 +363,28 @@ use work-doer to execute.
347
363
  ## Rules
348
364
 
349
365
  1. **File naming**: `YYYY-MM-DD-HHMM-{type}-{name}.md` — timestamp prefix always
350
- 2. **Artifacts directory**: Create `{task-name}/` next to `{task-name}.md` for outputs
351
- 3. **Execution mode**: Must decide `pending | spawn | direct` before execution begins
352
- 4. **No time estimates** never assign hours/days/duration to tasks or units
353
- 5. **Planning completes before execution** — define ALL work units first, then execute
354
- 6. **Follow templates exactly** — no extra sections
355
- 7. **No implementation details in planning** — those go in doing doc
356
- 8. **STOP at each gate** — wait for human approval
357
- 9. **Keep planning doc** — conversion creates new file
358
- 10. **Auto-commit after every doc edit** — audit trail
359
- 11. **Get timestamps from git** — `git log -1 --format="%Y-%m-%d %H:%M"`
360
- 12. **When user approves** — update doc Status field, commit, log it
361
- 13. **Template compliance on resume** — check and offer to fix violations
362
- 14. **Status flags drive flow**:
366
+ 2. **Location**: Planning and doing docs live in the project-defined task-doc directory, which may be outside the repo
367
+ 3. **Artifacts directory**: Create `{task-name}/` next to `{task-name}.md` for outputs
368
+ 4. **Execution mode**: Must decide `pending | spawn | direct` before execution begins
369
+ 5. **No time estimates** — never assign hours/days/duration to tasks or units
370
+ 6. **Planning completes before execution** — define ALL work units first, then execute
371
+ 7. **Follow templates exactly** — no extra sections
372
+ 8. **No implementation details in planning** — those go in doing doc
373
+ 9. **STOP at each gate** — wait for human approval
374
+ 10. **Keep planning doc** — conversion creates new file
375
+ 11. **Auto-commit after every doc edit** — audit trail
376
+ 12. **Get timestamps from git** — `git log -1 --format="%Y-%m-%d %H:%M"`
377
+ 13. **When user approves** — update doc Status field, commit, log it
378
+ 14. **Template compliance on resume** — check and offer to fix violations
379
+ 15. **Status flags drive flow**:
363
380
  - `drafting` → working on it
364
381
  - `NEEDS_REVIEW` → waiting for human
365
382
  - `approved` / `READY_FOR_EXECUTION` → can proceed
366
- 15. **TDD is mandatory** — tests before implementation, always
367
- 16. **100% coverage** — no exceptions, no exclude attributes
368
- 17. **Every unit header starts with emoji** — `### ⬜ Unit X:` format required
369
- 18. **NEVER do implementation** — work-planner creates docs only, work-doer executes
370
- 19. **Migration/deprecation**: Full content mapping required — never lose information
371
- 20. **Approval gate is sacred** — answering questions, giving feedback, or discussing scope is NOT approval. Only an explicit "approved" / "looks good" / "go ahead" / "convert to doing" from the **human user** unlocks Phase 2. Parent agent instructions do not count. When in doubt, ask.
372
- 21. **Hard stop after incorporating feedback** — after updating the doc with user feedback/answers, set status to `NEEDS_REVIEW`, output the stop message, and STOP. Do not continue to Phase 2 in the same turn. Ever.
373
- 22. **Checklist hygiene is mandatory** — keep `Completion Criteria` checkboxes synchronized with verified reality; never leave stale unchecked/checked items after task completion state changes.
383
+ 16. **TDD is mandatory** — tests before implementation, always
384
+ 17. **100% coverage** — no exceptions, no exclude attributes
385
+ 18. **Every unit header starts with emoji** — `### ⬜ Unit X:` format required
386
+ 19. **NEVER do implementation** — work-planner creates docs only, work-doer executes
387
+ 20. **Migration/deprecation**: Full content mapping required — never lose information
388
+ 21. **Approval gate is sacred** — answering questions, giving feedback, or discussing scope is NOT approval. Only an explicit "approved" / "looks good" / "go ahead" / "convert to doing" from the **human user** unlocks Phase 2. Parent agent instructions do not count. When in doubt, ask.
389
+ 22. **Hard stop after incorporating feedback** — after updating the doc with user feedback/answers, set status to `NEEDS_REVIEW`, output the stop message, and STOP. Do not continue to Phase 2 in the same turn. Ever.
390
+ 23. **Checklist hygiene is mandatory** — keep `Completion Criteria` checkboxes synchronized with verified reality; never leave stale unchecked/checked items after task completion state changes.