Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions platform/agents/council/council.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,9 +505,21 @@ def parallel_bounded(thunks: list[Callable[[], T]], cap: int) -> list[T]:
return list(ex.map(lambda t: t(), thunks))


def localize_verify(cmd: str, repo_root: str, cwd: str) -> str:
"""Point a verify command at the worktree it runs in. The consolidator is
told to write repo-relative commands, but a stray absolute repo-root path
(e.g. `cd /workspace/services/foo`) would otherwise check the host tree, not
the worker's worktree. Rewrite the repo root to the worktree so such a
command still verifies the right files. Pure (covered by --self-test)."""
if repo_root and repo_root != cwd and repo_root in cmd:
return cmd.replace(repo_root, cwd)
return cmd


def run_verify(cmd: str, cwd: Path) -> tuple[Optional[int], str]:
if not cmd.strip():
return None, "(no verify command)"
cmd = localize_verify(cmd, str(REPO_ROOT), str(cwd))
try:
proc = subprocess.run(["bash", "-lc", cmd], cwd=str(cwd),
capture_output=True, text=True, env=child_env(),
Expand Down Expand Up @@ -1237,6 +1249,14 @@ def check(name: str, cond: bool) -> None:
check("_split_dest_url canonical ssh remote",
_split_dest_url("o", "n") == "git@github.com:o/n.git")

# localize_verify (verify runs in the worktree, not the host repo root)
check("localize_verify rewrites repo root to the worktree",
localize_verify("cd /workspace/services/foo && npm test",
"/workspace", "/tmp/wt/T1")
== "cd /tmp/wt/T1/services/foo && npm test")
check("localize_verify leaves relative commands untouched",
localize_verify("npm test", "/workspace", "/tmp/wt/T1") == "npm test")

print(f"\n{'PASS' if not failures else 'FAIL: ' + ', '.join(failures)}")
return 1 if failures else 0

Expand Down
12 changes: 12 additions & 0 deletions platform/agents/council/prompts/consolidator.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,30 @@ each. Do not merely pick one and discard the other; the best ideas are often
split across both.

# Task brief

{{brief}}

# Plan A (final)

{{plan_a}}

# Plan B (final)

{{plan_b}}

# Critique history (rounds 1-2, both directions)

{{history}}

# Repository

Ground every task in the real codebase at {{repo_root}}. Do not invent paths.

# Your job

Produce (1) a clear consolidated plan in Markdown, and (2) a task DAG for
parallel execution. Each task must:

- be independently executable by a cheap worker agent given only its own fields,
- touch a NON-OVERLAPPING set of files from every task it does not depend on
(overlapping files across parallel tasks cause merge conflicts — partition the
Expand All @@ -32,6 +39,10 @@ parallel execution. Each task must:
no markdown, no parenthetical asides. Chain steps with `&&`. Right:
`python3 foo.py --version && python3 -m pytest -q`. Wrong:
`run the script (expect "ok") and check it passes`.
The command runs from the ROOT of the worker's isolated worktree (a fresh
checkout of this repo), so use REPO-RELATIVE paths only — never an absolute
path and never `cd /abs/...`. Right: `cd services/foo && npm test`. Wrong:
`cd /workspace/services/foo && npm test`.
- be tagged with a difficulty and a worker model (haiku for trivial/moderate,
sonnet for hard).

Expand All @@ -42,6 +53,7 @@ should be a single task with a clear ordering, not forced into false parallelism
{{baseline}}

# Output

Return ONLY a JSON object — no prose, no code fences — matching this schema:

{{schema}}
56 changes: 28 additions & 28 deletions platform/agents/kit/manifest.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
version: 1
generated: partial
notes:
- "This manifest pins the current repo and installer agent surfaces. Repo skills, hooks, hook settings, and the installer entrypoint are rendered from agent-kit templates; installer heredoc bodies, including hooks, skills, settings, and allowlists, are rendered from partial templates."
- "Repo skill bodies are intentionally agent-specific today; parity means every shared skill has both Claude and Codex targets unless an explicit unsupported reason is present."
- 'This manifest pins the current repo and installer agent surfaces. Repo skills, hooks, hook settings, and the installer entrypoint are rendered from agent-kit templates; installer heredoc bodies, including hooks, skills, settings, and allowlists, are rendered from partial templates.'
- 'Repo skill bodies are intentionally agent-specific today; parity means every shared skill has both Claude and Codex targets unless an explicit unsupported reason is present.'

renderer:
script_path: platform/agents/kit/render-agent-kit.py
Expand Down Expand Up @@ -77,8 +77,8 @@ skills:
sha256: d9c050e9c9dc1714129e545559f8f42ead5f0b6bc4cb28f4af74b3610542e596
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/skills/agent-session-bootstrap/SKILL.md"
codex_target_path: "${CODEX_HOME}/skills/agent-session-bootstrap/SKILL.md"
target_path: '${CLAUDE_HOME}/skills/agent-session-bootstrap/SKILL.md'
codex_target_path: '${CODEX_HOME}/skills/agent-session-bootstrap/SKILL.md'
- name: council
supported_agents: [codex, claude]
targets:
Expand All @@ -90,8 +90,8 @@ skills:
sha256: 0453a7fe2373cc46cf6e17122788ef7a99a5d8c7f2e0387ff7962265c088500a
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/skills/council/SKILL.md"
codex_target_path: "${CODEX_HOME}/skills/council/SKILL.md"
target_path: '${CLAUDE_HOME}/skills/council/SKILL.md'
codex_target_path: '${CODEX_HOME}/skills/council/SKILL.md'
- name: fleet-change
supported_agents: [codex, claude]
targets:
Expand All @@ -112,8 +112,8 @@ skills:
sha256: 99f677b9e491be60b35dc72d6abbf87a064ce1f6db83b492af990a467f63881c
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/skills/kb-first/SKILL.md"
codex_target_path: "${CODEX_HOME}/skills/kb-first/SKILL.md"
target_path: '${CLAUDE_HOME}/skills/kb-first/SKILL.md'
codex_target_path: '${CODEX_HOME}/skills/kb-first/SKILL.md'
- name: open-pr
supported_agents: [codex, claude]
targets:
Expand Down Expand Up @@ -143,25 +143,25 @@ skills:
sha256: 6823d195dbfb99e2bab3bdeed760445d1d0db78600a46405ae605c12fca4467e
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/skills/token-economy/SKILL.md"
codex_target_path: "${CODEX_HOME}/skills/token-economy/SKILL.md"
target_path: '${CLAUDE_HOME}/skills/token-economy/SKILL.md'
codex_target_path: '${CODEX_HOME}/skills/token-economy/SKILL.md'
- name: topics
supported_agents: [codex, claude]
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/skills/topics/SKILL.md"
codex_target_path: "${CODEX_HOME}/skills/topics/SKILL.md"
target_path: '${CLAUDE_HOME}/skills/topics/SKILL.md'
codex_target_path: '${CODEX_HOME}/skills/topics/SKILL.md'
- name: audit
supported_agents: [codex, claude]
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/skills/audit/SKILL.md"
codex_target_path: "${CODEX_HOME}/skills/audit/SKILL.md"
target_path: '${CLAUDE_HOME}/skills/audit/SKILL.md'
codex_target_path: '${CODEX_HOME}/skills/audit/SKILL.md'

hooks:
- name: kb-user-prompt-recall
event: UserPromptSubmit
purpose: "Inject bounded knowledge.recall snippets before the agent sees the prompt."
purpose: 'Inject bounded knowledge.recall snippets before the agent sees the prompt.'
supported_agents: [claude, codex]
mcp_tools: [knowledge.recall]
targets:
Expand All @@ -175,11 +175,11 @@ hooks:
sha256: 50d4579b3e774675326cc76113afebcfe5251c46ea11059cf0a567557e1a6911
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/hooks/user-prompt-submit-recall.sh"
codex_target_path: "${CODEX_HOME}/hooks/kb-user-prompt-recall.sh"
target_path: '${CLAUDE_HOME}/hooks/user-prompt-submit-recall.sh'
codex_target_path: '${CODEX_HOME}/hooks/kb-user-prompt-recall.sh'
- name: kb-stop-digest
event: Stop
purpose: "Digest the transcript into capped lesson candidates and capture survivors."
purpose: 'Digest the transcript into capped lesson candidates and capture survivors.'
supported_agents: [claude, codex]
mcp_tools: [knowledge.digest_transcript, knowledge.recall, knowledge.capture_lesson]
targets:
Expand All @@ -193,12 +193,12 @@ hooks:
sha256: 193522faf697ca08bc18b0b00d670195efe54d88be4dfca95324dce6910b6e01
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/hooks/stop-session-digest.sh"
codex_target_path: "${CODEX_HOME}/hooks/kb-stop-digest.sh"
target_path: '${CLAUDE_HOME}/hooks/stop-session-digest.sh'
codex_target_path: '${CODEX_HOME}/hooks/kb-stop-digest.sh'
- name: pre-tool-use-edit-recall
event: PreToolUse
matcher: "Edit|Write|MultiEdit|apply_patch"
purpose: "Recall file/module lessons before edits."
matcher: 'Edit|Write|MultiEdit|apply_patch'
purpose: 'Recall file/module lessons before edits.'
supported_agents: [claude, codex]
targets:
- agent: claude
Expand All @@ -212,12 +212,12 @@ hooks:
mcp_tools: [knowledge.recall]
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/hooks/pre-tool-use-edit-recall.sh"
codex_target_path: "${CODEX_HOME}/hooks/pre-tool-use-edit-recall.sh"
target_path: '${CLAUDE_HOME}/hooks/pre-tool-use-edit-recall.sh'
codex_target_path: '${CODEX_HOME}/hooks/pre-tool-use-edit-recall.sh'
- name: pre-tool-use-git-commit-capture
event: PreToolUse
matcher: Bash
purpose: "Capture non-WIP git commit messages as candidate decisions."
purpose: 'Capture non-WIP git commit messages as candidate decisions.'
supported_agents: [claude, codex]
targets:
- agent: claude
Expand All @@ -231,8 +231,8 @@ hooks:
mcp_tools: [knowledge.capture_decision]
installer:
source_path: services/knowledge-api/src/main/resources/installer/install.sh
target_path: "${CLAUDE_HOME}/hooks/pre-tool-use-git-commit-capture.sh"
codex_target_path: "${CODEX_HOME}/hooks/pre-tool-use-git-commit-capture.sh"
target_path: '${CLAUDE_HOME}/hooks/pre-tool-use-git-commit-capture.sh'
codex_target_path: '${CODEX_HOME}/hooks/pre-tool-use-git-commit-capture.sh'

settings:
- agent: claude
Expand All @@ -244,5 +244,5 @@ settings:

installer:
path: services/knowledge-api/src/main/resources/installer/install.sh
sha256: a3356d48c5b98b4f21632717b785c14cf08c7ee11106274a0bef40992d72bf77
sha256: 68d38c29f3e755f6dae9f916379867893f4ad0d4307f71f2cadf33e6662ccd0a
supported_agents: [codex, claude]
32 changes: 32 additions & 0 deletions services/knowledge-api/src/main/resources/installer/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1082,9 +1082,21 @@ def parallel_bounded(thunks: list[Callable[[], T]], cap: int) -> list[T]:
return list(ex.map(lambda t: t(), thunks))


def localize_verify(cmd: str, repo_root: str, cwd: str) -> str:
"""Point a verify command at the worktree it runs in. The consolidator is
told to write repo-relative commands, but a stray absolute repo-root path
(e.g. `cd /workspace/services/foo`) would otherwise check the host tree, not
the worker's worktree. Rewrite the repo root to the worktree so such a
command still verifies the right files. Pure (covered by --self-test)."""
if repo_root and repo_root != cwd and repo_root in cmd:
return cmd.replace(repo_root, cwd)
return cmd


def run_verify(cmd: str, cwd: Path) -> tuple[Optional[int], str]:
if not cmd.strip():
return None, "(no verify command)"
cmd = localize_verify(cmd, str(REPO_ROOT), str(cwd))
try:
proc = subprocess.run(["bash", "-lc", cmd], cwd=str(cwd),
capture_output=True, text=True, env=child_env(),
Expand Down Expand Up @@ -1814,6 +1826,14 @@ def cmd_self_test(_args: argparse.Namespace) -> int:
check("_split_dest_url canonical ssh remote",
_split_dest_url("o", "n") == "git@github.com:o/n.git")

# localize_verify (verify runs in the worktree, not the host repo root)
check("localize_verify rewrites repo root to the worktree",
localize_verify("cd /workspace/services/foo && npm test",
"/workspace", "/tmp/wt/T1")
== "cd /tmp/wt/T1/services/foo && npm test")
check("localize_verify leaves relative commands untouched",
localize_verify("npm test", "/workspace", "/tmp/wt/T1") == "npm test")

print(f"\n{'PASS' if not failures else 'FAIL: ' + ', '.join(failures)}")
return 1 if failures else 0

Expand Down Expand Up @@ -1970,23 +1990,30 @@ each. Do not merely pick one and discard the other; the best ideas are often
split across both.

# Task brief

{{brief}}

# Plan A (final)

{{plan_a}}

# Plan B (final)

{{plan_b}}

# Critique history (rounds 1-2, both directions)

{{history}}

# Repository

Ground every task in the real codebase at {{repo_root}}. Do not invent paths.

# Your job

Produce (1) a clear consolidated plan in Markdown, and (2) a task DAG for
parallel execution. Each task must:

- be independently executable by a cheap worker agent given only its own fields,
- touch a NON-OVERLAPPING set of files from every task it does not depend on
(overlapping files across parallel tasks cause merge conflicts — partition the
Expand All @@ -1997,6 +2024,10 @@ parallel execution. Each task must:
no markdown, no parenthetical asides. Chain steps with `&&`. Right:
`python3 foo.py --version && python3 -m pytest -q`. Wrong:
`run the script (expect "ok") and check it passes`.
The command runs from the ROOT of the worker's isolated worktree (a fresh
checkout of this repo), so use REPO-RELATIVE paths only — never an absolute
path and never `cd /abs/...`. Right: `cd services/foo && npm test`. Wrong:
`cd /workspace/services/foo && npm test`.
- be tagged with a difficulty and a worker model (haiku for trivial/moderate,
sonnet for hard).

Expand All @@ -2007,6 +2038,7 @@ should be a single task with a clear ordering, not forced into false parallelism
{{baseline}}

# Output

Return ONLY a JSON object — no prose, no code fences — matching this schema:

{{schema}}
Expand Down