@hecer/yoke 1.6.0 → 1.6.2
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.
- package/.claude-plugin/plugin.json +13 -13
- package/.codex-plugin/plugin.json +7 -7
- package/CHANGELOG.md +304 -288
- package/README.md +874 -874
- package/TODOS.md +5 -5
- package/agents/docs.toml +6 -6
- package/agents/implementer.toml +6 -6
- package/agents/reviewer.toml +6 -6
- package/agents/security.toml +6 -6
- package/bench/README.md +86 -86
- package/bench/RESULTS.md +35 -35
- package/bench/output-compaction.mjs +65 -65
- package/bench/result-schema.mjs +12 -12
- package/bench/results/claude-2026-07-27T18-03-26.json +50 -50
- package/bench/results/codex-unavailable-1785175418318.json +15 -15
- package/bench/results/gemini-2026-07-27T18-03-44.json +46 -46
- package/bench/run-matrix.mjs +26 -26
- package/bench/run.mjs +106 -106
- package/canon/AGENTS.md +30 -30
- package/canon/context/DECISIONS.md +4 -4
- package/canon/context/GLOSSARY.md +11 -11
- package/canon/context/KNOWLEDGE.md +4 -4
- package/canon/context/PROJECT.md +15 -15
- package/canon/loop/loop-spec.md +65 -65
- package/canon/loop/prd.schema.md +43 -43
- package/canon/manifest.yaml +59 -59
- package/canon/policy/gates.md +7 -7
- package/canon/policy/roles.md +9 -9
- package/canon/skills/ATTRIBUTION.md +99 -99
- package/canon/skills/authoring-prd/SKILL.md +58 -58
- package/canon/skills/brainstorming/SKILL.md +164 -164
- package/canon/skills/codebase-design/DEEPENING.md +15 -15
- package/canon/skills/codebase-design/DESIGN-IT-TWICE.md +12 -12
- package/canon/skills/codebase-design/SKILL.md +39 -39
- package/canon/skills/dispatching-parallel-agents/SKILL.md +182 -182
- package/canon/skills/document-release/SKILL.md +302 -302
- package/canon/skills/domain-modeling/ADR-FORMAT.md +19 -19
- package/canon/skills/domain-modeling/CONTEXT-FORMAT.md +39 -39
- package/canon/skills/domain-modeling/SKILL.md +35 -35
- package/canon/skills/executing-plans/SKILL.md +70 -70
- package/canon/skills/finishing-a-development-branch/SKILL.md +200 -200
- package/canon/skills/health/SKILL.md +177 -177
- package/canon/skills/maintaining-context/SKILL.md +34 -34
- package/canon/skills/minimal-code/SKILL.md +21 -21
- package/canon/skills/no-ai-slop/SKILL.md +103 -103
- package/canon/skills/no-ai-slop/eval.md +43 -43
- package/canon/skills/plan-ceo-review/SKILL.md +541 -541
- package/canon/skills/plan-eng-review/SKILL.md +362 -362
- package/canon/skills/receiving-code-review/SKILL.md +213 -213
- package/canon/skills/requesting-code-review/SKILL.md +105 -105
- package/canon/skills/resolving-merge-conflicts/SKILL.md +18 -18
- package/canon/skills/retro/SKILL.md +397 -397
- package/canon/skills/review/SKILL.md +246 -246
- package/canon/skills/ship/SKILL.md +691 -691
- package/canon/skills/subagent-driven-development/SKILL.md +277 -277
- package/canon/skills/systematic-debugging/SKILL.md +296 -296
- package/canon/skills/tdd/SKILL.md +371 -371
- package/canon/skills/unslop-ui/SKILL.md +34 -34
- package/canon/skills/using-git-worktrees/SKILL.md +218 -218
- package/canon/skills/verification-before-completion/SKILL.md +139 -139
- package/canon/skills/visual-verification/SKILL.md +54 -54
- package/canon/skills/workflow/SKILL.md +22 -22
- package/canon/skills/writing-for-agents/SKILL-MECHANICS.md +27 -27
- package/canon/skills/writing-for-agents/SKILL.md +42 -42
- package/canon/skills/writing-plans/SKILL.md +152 -152
- package/canon/skills/writing-skills/SKILL.md +655 -655
- package/canon/skills/yoke-retrofit/SKILL.md +26 -26
- package/canon/skills/yoke-workflow/SKILL.md +20 -20
- package/canon/tools/codex-rtk-hook.mjs +35 -35
- package/canon/tools/graphify.md +3 -3
- package/canon/tools/playwright-mcp.md +3 -3
- package/canon/tools/rtk.md +7 -7
- package/canon/tools/serena.md +6 -6
- package/dist/agents/process.js +5 -0
- package/dist/agents/providers.js +1 -1
- package/dist/loop/cleanup.js +3 -0
- package/dist/loop/reporter.js +4 -1
- package/dist/loop/watchdog.js +3 -1
- package/dist/prd/command.js +17 -17
- package/dist/retrofit/planners/claude.js +14 -14
- package/dist/retrofit/preserve.js +2 -2
- package/docs/MIGRATING-TO-1.0.md +33 -33
- package/docs/MIGRATING-TO-1.1.md +27 -27
- package/docs/MIGRATING-TO-1.4.md +70 -70
- package/docs/PUBLISHING.md +114 -91
- package/docs/superpowers/plans/2026-06-28-baustein-e-context-layer.md +981 -981
- package/docs/superpowers/plans/2026-06-29-baustein-f-routing.md +258 -258
- package/docs/superpowers/plans/2026-06-29-baustein-g-loop-observability.md +1006 -1006
- package/docs/superpowers/plans/2026-06-29-baustein-h-loop-robustness.md +374 -374
- package/docs/superpowers/plans/2026-06-30-baustein-i-visual-design-verification.md +450 -450
- package/docs/superpowers/plans/2026-07-02-baustein-k-zero-to-100-bootstrap.md +1024 -1024
- package/docs/superpowers/plans/2026-07-02-baustein-m-flow-smoke-proofs.md +574 -574
- package/docs/superpowers/plans/2026-08-13-gauntlet-quality-loop.md +537 -537
- package/docs/superpowers/plans/2026-08-16-artifact-backed-output-compaction.md +329 -329
- package/docs/superpowers/specs/2026-06-28-baustein-e-context-layer-design.md +146 -146
- package/docs/superpowers/specs/2026-06-29-baustein-f-routing-design.md +106 -106
- package/docs/superpowers/specs/2026-06-29-baustein-g-loop-observability-design.md +186 -186
- package/docs/superpowers/specs/2026-06-29-baustein-h-loop-robustness-design.md +113 -113
- package/docs/superpowers/specs/2026-06-30-baustein-i-visual-design-verification-design.md +98 -98
- package/docs/superpowers/specs/2026-07-02-baustein-k-zero-to-100-bootstrap-design.md +200 -200
- package/docs/superpowers/specs/2026-07-02-baustein-m-flow-smoke-proofs-design.md +155 -155
- package/docs/superpowers/specs/2026-08-13-gauntlet-quality-loop-design.md +422 -422
- package/docs/superpowers/specs/2026-08-16-artifact-backed-output-compaction-design.md +166 -166
- package/gemini-extension.json +6 -6
- package/hooks/hooks.json +19 -19
- package/package.json +87 -87
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: yoke-retrofit
|
|
3
|
-
description: Use when asked to "retrofit", "yoke this project", or set up the Yoke harness in a project — runs the shared setup wizard and configures the same behavior for Claude, Codex, and Gemini.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Yoke Retrofit
|
|
7
|
-
|
|
8
|
-
Set up or update Yoke through the shared `yoke setup` contract.
|
|
9
|
-
|
|
10
|
-
1. Inspect the project and identify the current host (`claude`, `codex`, or `gemini`).
|
|
11
|
-
2. Ask these setup questions one at a time and give a direct recommendation:
|
|
12
|
-
- target agents (recommend the current host; use `all` for deliberately cross-agent projects),
|
|
13
|
-
- code-graph tool,
|
|
14
|
-
- autonomous loop on/off,
|
|
15
|
-
- default runner (recommend the current host),
|
|
16
|
-
- decision mode: `auto` or `critical`.
|
|
17
|
-
3. Recommend the code graph based on this project:
|
|
18
|
-
- **Serena** is LSP-accurate and best for large typed codebases or systematic symbol refactors where a missed reference is costly. It needs a language server per language.
|
|
19
|
-
- **graphify** is fast and multimodal, and is best for exploration, migration, onboarding, or mixed code and document repositories. Its graph is an index and can become stale.
|
|
20
|
-
4. Apply the answers without a second round of prompts:
|
|
21
|
-
`yoke setup . --yes --host=<host> --agent=<agents> --code-graph=<choice> --runner=<runner> --decision-policy=<auto|critical> --loop|--no-loop`.
|
|
22
|
-
A human who runs `yoke setup .` directly receives the same five terminal questions.
|
|
23
|
-
5. Show the generated report and backup paths. Existing files are backed up under `.yoke/backup/`; settings are merged where supported.
|
|
24
|
-
6. If an old generated `CLAUDE.md` or `GEMINI.md` contained project-specific instructions, restore them inside its `<!-- yoke:preserve:start -->` / `<!-- yoke:preserve:end -->` block. Preserve blocks survive every later retrofit.
|
|
25
|
-
|
|
26
|
-
The generated harness includes the provider-neutral `yoke-workflow` skill. It owns the planning questions, approved-plan handoff, autonomous stories, and critical-decision resume flow.
|
|
1
|
+
---
|
|
2
|
+
name: yoke-retrofit
|
|
3
|
+
description: Use when asked to "retrofit", "yoke this project", or set up the Yoke harness in a project — runs the shared setup wizard and configures the same behavior for Claude, Codex, and Gemini.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Yoke Retrofit
|
|
7
|
+
|
|
8
|
+
Set up or update Yoke through the shared `yoke setup` contract.
|
|
9
|
+
|
|
10
|
+
1. Inspect the project and identify the current host (`claude`, `codex`, or `gemini`).
|
|
11
|
+
2. Ask these setup questions one at a time and give a direct recommendation:
|
|
12
|
+
- target agents (recommend the current host; use `all` for deliberately cross-agent projects),
|
|
13
|
+
- code-graph tool,
|
|
14
|
+
- autonomous loop on/off,
|
|
15
|
+
- default runner (recommend the current host),
|
|
16
|
+
- decision mode: `auto` or `critical`.
|
|
17
|
+
3. Recommend the code graph based on this project:
|
|
18
|
+
- **Serena** is LSP-accurate and best for large typed codebases or systematic symbol refactors where a missed reference is costly. It needs a language server per language.
|
|
19
|
+
- **graphify** is fast and multimodal, and is best for exploration, migration, onboarding, or mixed code and document repositories. Its graph is an index and can become stale.
|
|
20
|
+
4. Apply the answers without a second round of prompts:
|
|
21
|
+
`yoke setup . --yes --host=<host> --agent=<agents> --code-graph=<choice> --runner=<runner> --decision-policy=<auto|critical> --loop|--no-loop`.
|
|
22
|
+
A human who runs `yoke setup .` directly receives the same five terminal questions.
|
|
23
|
+
5. Show the generated report and backup paths. Existing files are backed up under `.yoke/backup/`; settings are merged where supported.
|
|
24
|
+
6. If an old generated `CLAUDE.md` or `GEMINI.md` contained project-specific instructions, restore them inside its `<!-- yoke:preserve:start -->` / `<!-- yoke:preserve:end -->` block. Preserve blocks survive every later retrofit.
|
|
25
|
+
|
|
26
|
+
The generated harness includes the provider-neutral `yoke-workflow` skill. It owns the planning questions, approved-plan handoff, autonomous stories, and critical-decision resume flow.
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: yoke-workflow
|
|
3
|
-
description: Use when the user asks Yoke to plan and build a feature, run stories autonomously, continue a Yoke loop, or only interrupt for major decisions.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Yoke Workflow
|
|
7
|
-
|
|
8
|
-
Provide the same interaction contract in Claude, Codex, and Gemini.
|
|
9
|
-
|
|
10
|
-
1. Read `.yoke/config.yaml`. If it is missing, offer `yoke setup . --host=<current-agent>` and run the setup flow before planning.
|
|
11
|
-
2. Plan before starting the loop. Inspect the project, then ask one focused question at a time only where the answer changes product behavior, scope, architecture, security, data ownership, external cost, or an irreversible choice. Include a recommended answer. Resolve routine implementation details yourself.
|
|
12
|
-
3. Summarize the agreed design in `.yoke/plan.md`, including goals, non-goals, constraints, and decisions. Use the `authoring-prd` skill to turn it into small stories with testable acceptance criteria. Run `yoke prd check .`.
|
|
13
|
-
4. Ask once for approval of the complete plan and story set. Do not begin implementation before that approval.
|
|
14
|
-
5. If `loop.enabled` is true, run the stories without routine follow-up questions using the configured runner. Prefer `yoke loop run . --max=5 --isolate`, report status after each batch, and continue until complete or genuinely blocked.
|
|
15
|
-
6. Respect `loop.decisionPolicy`:
|
|
16
|
-
- `auto`: choose the most suitable option from the plan, current code, and established conventions. Record the interpretation and continue.
|
|
17
|
-
- `critical`: routine ambiguity is still resolved automatically. If the loop reports a pending critical decision, run `yoke loop decision .`, present its options and recommendation to the user, ask exactly that question, then run `yoke loop answer . --choice=<id> --rationale="<answer>"`. The answer command records the decision and resumes the same story.
|
|
18
|
-
7. Never ask whether to run tests, review, commit, or continue to the next approved story. Those are part of the approved workflow.
|
|
19
|
-
|
|
20
|
-
The user's configured commit identity is authoritative. Do not add an AI co-author unless `commit.allowCoAuthors` explicitly permits it.
|
|
1
|
+
---
|
|
2
|
+
name: yoke-workflow
|
|
3
|
+
description: Use when the user asks Yoke to plan and build a feature, run stories autonomously, continue a Yoke loop, or only interrupt for major decisions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Yoke Workflow
|
|
7
|
+
|
|
8
|
+
Provide the same interaction contract in Claude, Codex, and Gemini.
|
|
9
|
+
|
|
10
|
+
1. Read `.yoke/config.yaml`. If it is missing, offer `yoke setup . --host=<current-agent>` and run the setup flow before planning.
|
|
11
|
+
2. Plan before starting the loop. Inspect the project, then ask one focused question at a time only where the answer changes product behavior, scope, architecture, security, data ownership, external cost, or an irreversible choice. Include a recommended answer. Resolve routine implementation details yourself.
|
|
12
|
+
3. Summarize the agreed design in `.yoke/plan.md`, including goals, non-goals, constraints, and decisions. Use the `authoring-prd` skill to turn it into small stories with testable acceptance criteria. Run `yoke prd check .`.
|
|
13
|
+
4. Ask once for approval of the complete plan and story set. Do not begin implementation before that approval.
|
|
14
|
+
5. If `loop.enabled` is true, run the stories without routine follow-up questions using the configured runner. Prefer `yoke loop run . --max=5 --isolate`, report status after each batch, and continue until complete or genuinely blocked.
|
|
15
|
+
6. Respect `loop.decisionPolicy`:
|
|
16
|
+
- `auto`: choose the most suitable option from the plan, current code, and established conventions. Record the interpretation and continue.
|
|
17
|
+
- `critical`: routine ambiguity is still resolved automatically. If the loop reports a pending critical decision, run `yoke loop decision .`, present its options and recommendation to the user, ask exactly that question, then run `yoke loop answer . --choice=<id> --rationale="<answer>"`. The answer command records the decision and resumes the same story.
|
|
18
|
+
7. Never ask whether to run tests, review, commit, or continue to the next approved story. Those are part of the approved workflow.
|
|
19
|
+
|
|
20
|
+
The user's configured commit identity is authoritative. Do not add an AI co-author unless `commit.allowCoAuthors` explicitly permits it.
|
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process'
|
|
2
|
-
import { resolve } from 'node:path'
|
|
3
|
-
import { pathToFileURL } from 'node:url'
|
|
4
|
-
|
|
5
|
-
function rtkCheck(command) {
|
|
6
|
-
const result = spawnSync('rtk', ['hook', 'check', command], { encoding: 'utf8', timeout: 3000 })
|
|
7
|
-
return result.status === 0 ? result.stdout.trim() : ''
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function rewriteHookInput(input, check = rtkCheck) {
|
|
11
|
-
if (input?.tool_name !== 'Bash' && input?.toolName !== 'Bash') return null
|
|
12
|
-
const toolInput = input.tool_input ?? input.toolInput
|
|
13
|
-
const command = toolInput?.command
|
|
14
|
-
if (typeof command !== 'string' || command.trim() === '') return null
|
|
15
|
-
const rewritten = check(command)
|
|
16
|
-
if (!rewritten || rewritten === command) return null
|
|
17
|
-
return {
|
|
18
|
-
hookSpecificOutput: {
|
|
19
|
-
hookEventName: 'PreToolUse',
|
|
20
|
-
updatedInput: { ...toolInput, command: rewritten },
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async function main() {
|
|
26
|
-
let raw = ''
|
|
27
|
-
for await (const chunk of process.stdin) raw += chunk
|
|
28
|
-
try {
|
|
29
|
-
const output = rewriteHookInput(JSON.parse(raw))
|
|
30
|
-
if (output) process.stdout.write(JSON.stringify(output))
|
|
31
|
-
} catch {
|
|
32
|
-
// Compression is an optimization. Malformed input must never block Codex.
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) await main()
|
|
2
|
+
import { resolve } from 'node:path'
|
|
3
|
+
import { pathToFileURL } from 'node:url'
|
|
4
|
+
|
|
5
|
+
function rtkCheck(command) {
|
|
6
|
+
const result = spawnSync('rtk', ['hook', 'check', command], { encoding: 'utf8', timeout: 3000 })
|
|
7
|
+
return result.status === 0 ? result.stdout.trim() : ''
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function rewriteHookInput(input, check = rtkCheck) {
|
|
11
|
+
if (input?.tool_name !== 'Bash' && input?.toolName !== 'Bash') return null
|
|
12
|
+
const toolInput = input.tool_input ?? input.toolInput
|
|
13
|
+
const command = toolInput?.command
|
|
14
|
+
if (typeof command !== 'string' || command.trim() === '') return null
|
|
15
|
+
const rewritten = check(command)
|
|
16
|
+
if (!rewritten || rewritten === command) return null
|
|
17
|
+
return {
|
|
18
|
+
hookSpecificOutput: {
|
|
19
|
+
hookEventName: 'PreToolUse',
|
|
20
|
+
updatedInput: { ...toolInput, command: rewritten },
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function main() {
|
|
26
|
+
let raw = ''
|
|
27
|
+
for await (const chunk of process.stdin) raw += chunk
|
|
28
|
+
try {
|
|
29
|
+
const output = rewriteHookInput(JSON.parse(raw))
|
|
30
|
+
if (output) process.stdout.write(JSON.stringify(output))
|
|
31
|
+
} catch {
|
|
32
|
+
// Compression is an optimization. Malformed input must never block Codex.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) await main()
|
package/canon/tools/graphify.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
# Tool: graphify (code-graph)
|
|
2
|
-
|
|
3
|
-
MIT, multimodal code/doc graph. Wired as an MCP server for all three agents (stdio). Prefer symbol/graph lookups over reading whole files. Caveat: heuristic edges (INFERRED/AMBIGUOUS) and a static index that can go stale — rebuild on significant changes.
|
|
1
|
+
# Tool: graphify (code-graph)
|
|
2
|
+
|
|
3
|
+
MIT, multimodal code/doc graph. Wired as an MCP server for all three agents (stdio). Prefer symbol/graph lookups over reading whole files. Caveat: heuristic edges (INFERRED/AMBIGUOUS) and a static index that can go stale — rebuild on significant changes.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
# Tool: Playwright MCP (browser / dogfooding)
|
|
2
|
-
|
|
3
|
-
Microsoft Playwright MCP, Apache-2.0. Wired as an MCP server for all three agents — the only browser tool with native MCP parity across Claude/Codex/Gemini. Used for QA, dogfooding user flows, screenshots, and deploy verification.
|
|
1
|
+
# Tool: Playwright MCP (browser / dogfooding)
|
|
2
|
+
|
|
3
|
+
Microsoft Playwright MCP, Apache-2.0. Wired as an MCP server for all three agents — the only browser tool with native MCP parity across Claude/Codex/Gemini. Used for QA, dogfooding user flows, screenshots, and deploy verification.
|
package/canon/tools/rtk.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Tool: rtk (token compression)
|
|
2
|
-
|
|
3
|
-
Per-agent wiring (generated by Baustein B):
|
|
4
|
-
|
|
5
|
-
- **Claude Code:** PreToolUse hook auto-rewrites commands (`git status` → `rtk git status`). On Windows this needs WSL; otherwise fall back to instruction mode (this file injected into CLAUDE.md telling the agent to prefix commands with `rtk`).
|
|
6
|
-
- **Codex CLI:** inject `RTK.md` / AGENTS.md instruction.
|
|
7
|
-
- **Gemini CLI:** no hook system — register rtk as an MCP tool or inject the GEMINI.md instruction.
|
|
1
|
+
# Tool: rtk (token compression)
|
|
2
|
+
|
|
3
|
+
Per-agent wiring (generated by Baustein B):
|
|
4
|
+
|
|
5
|
+
- **Claude Code:** PreToolUse hook auto-rewrites commands (`git status` → `rtk git status`). On Windows this needs WSL; otherwise fall back to instruction mode (this file injected into CLAUDE.md telling the agent to prefix commands with `rtk`).
|
|
6
|
+
- **Codex CLI:** inject `RTK.md` / AGENTS.md instruction.
|
|
7
|
+
- **Gemini CLI:** no hook system — register rtk as an MCP tool or inject the GEMINI.md instruction.
|
package/canon/tools/serena.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# Tool: Serena (code-graph, LSP-accurate)
|
|
2
|
-
|
|
3
|
-
MIT, MCP-first. The alternative to graphify, selected via `yoke retrofit --code-graph=serena`. Serena uses real language servers (LSP) for symbol-accurate, cross-file retrieval and refactoring (`find_symbol`, `find_referencing_symbols`, rename/move) — no static index that goes stale, so it will not miss a reference.
|
|
4
|
-
|
|
5
|
-
Wired as an MCP server for all three agents. Best for large, strongly-typed codebases (TypeScript, Python, Go) doing systematic refactoring, where missing a caller is costly.
|
|
6
|
-
|
|
1
|
+
# Tool: Serena (code-graph, LSP-accurate)
|
|
2
|
+
|
|
3
|
+
MIT, MCP-first. The alternative to graphify, selected via `yoke retrofit --code-graph=serena`. Serena uses real language servers (LSP) for symbol-accurate, cross-file retrieval and refactoring (`find_symbol`, `find_referencing_symbols`, rename/move) — no static index that goes stale, so it will not miss a reference.
|
|
4
|
+
|
|
5
|
+
Wired as an MCP server for all three agents. Best for large, strongly-typed codebases (TypeScript, Python, Go) doing systematic refactoring, where missing a caller is costly.
|
|
6
|
+
|
|
7
7
|
Caveat: needs one language server per language (can be fiddly on Windows for exotic languages) and requires `uv`. The launch command is a best-effort template — adjust to your install, e.g. `uvx --from git+https://github.com/oraios/serena serena-mcp-server`.
|
|
8
8
|
|
|
9
9
|
Yoke disables Serena's automatic web-dashboard launch in generated MCP configurations. The
|
package/dist/agents/process.js
CHANGED
|
@@ -81,6 +81,11 @@ export function startProviderProcess(agent, invocation, options = {}) {
|
|
|
81
81
|
telemetry: telemetry.finish(),
|
|
82
82
|
});
|
|
83
83
|
const finalize = (exitCode) => {
|
|
84
|
+
// Windows can emit close before taskkill's process-tree state is observable.
|
|
85
|
+
// Reconfirm here so successful termination does not leave a stale ownership record.
|
|
86
|
+
if (termination && pid !== undefined && !terminationConfirmed) {
|
|
87
|
+
terminationConfirmed = terminateProcessTree(pid, true);
|
|
88
|
+
}
|
|
84
89
|
const details = evidence();
|
|
85
90
|
if (recordFailure) {
|
|
86
91
|
finish({ ...details, kind: 'spawn-failed', error: recordFailure });
|
package/dist/agents/providers.js
CHANGED
|
@@ -13,7 +13,7 @@ const argsFor = (agent, permissions) => {
|
|
|
13
13
|
return ['exec', '--dangerously-bypass-approvals-and-sandbox', '--json'];
|
|
14
14
|
if (permissions === 'read-only')
|
|
15
15
|
return ['exec', '--sandbox', 'read-only', '--json'];
|
|
16
|
-
return ['exec', '--
|
|
16
|
+
return ['exec', '--sandbox', 'workspace-write', '--approve-for-me', '--json'];
|
|
17
17
|
}
|
|
18
18
|
if (permissions === 'unsafe')
|
|
19
19
|
return ['--yolo'];
|
package/dist/loop/cleanup.js
CHANGED
|
@@ -6,6 +6,7 @@ import { processIncarnation } from '../agents/process-incarnation.js';
|
|
|
6
6
|
import { acquireTakeoverLease, acquireTakeoverRecoveryLease, lockPath, takeoverLockPath, readLock, isPidAlive, releaseTakeoverLease, releaseTakeoverRecoveryLease, takeoverRecoveryPath, } from './lock.js';
|
|
7
7
|
import { killProcessForCleanup, killProcessTreeForCleanup } from './watchdog.js';
|
|
8
8
|
import { cleanupClaims } from './claims.js';
|
|
9
|
+
import { clearStatus } from './reporter.js';
|
|
9
10
|
// Reap orphaned runners PROJECT-SCOPED: kill only pids recorded in this project's
|
|
10
11
|
// .yoke/runner.pid files (main dir + each worktree). Never by process-name or
|
|
11
12
|
// command-line pattern — that takes down runners belonging to OTHER projects,
|
|
@@ -223,6 +224,8 @@ export function runLoopCleanup(targetDir, opts = {}) {
|
|
|
223
224
|
rmSync(lockFile, { force: true });
|
|
224
225
|
console.log('Removed stale loop lock.');
|
|
225
226
|
}
|
|
227
|
+
if (failed === 0)
|
|
228
|
+
clearStatus(targetDir);
|
|
226
229
|
console.log(removed === 0 && failed === 0 ? 'No destructive cleanup performed.' : `Removed ${removed} worktree(s)${failed > 0 ? `, ${failed} failed` : ''}.`);
|
|
227
230
|
return failed === 0 ? 0 : 1;
|
|
228
231
|
}
|
package/dist/loop/reporter.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync, appendFileSync, statSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync, appendFileSync, statSync, rmSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
export const LOG_CAP_BYTES = 256 * 1024;
|
|
4
4
|
// Append a line to .yoke/loop.log, keeping the file bounded: once it exceeds
|
|
@@ -77,6 +77,9 @@ export function readStatus(dir) {
|
|
|
77
77
|
return null;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
+
export function clearStatus(dir) {
|
|
81
|
+
rmSync(statusPath(dir), { force: true });
|
|
82
|
+
}
|
|
80
83
|
export function makeReporter(dir, opts = {}, now = () => new Date()) {
|
|
81
84
|
const sink = opts.log ?? ((line) => process.stdout.write(line + '\n'));
|
|
82
85
|
const emitConsole = (line) => { if (!opts.quiet)
|
package/dist/loop/watchdog.js
CHANGED
|
@@ -62,8 +62,10 @@ export function killProcessTreeForCleanup(pid, platform = process.platform, runT
|
|
|
62
62
|
}
|
|
63
63
|
}) {
|
|
64
64
|
if (platform === 'win32') {
|
|
65
|
+
// taskkill reports a non-zero status when the process disappeared between
|
|
66
|
+
// observation and cleanup; that is already the desired terminal state.
|
|
65
67
|
if (runTaskkill('taskkill', ['/PID', String(pid), '/T', '/F']) !== 0)
|
|
66
|
-
return
|
|
68
|
+
return !isProcessAlive(pid);
|
|
67
69
|
return confirmProcessStopped(pid, isProcessAlive);
|
|
68
70
|
}
|
|
69
71
|
try {
|
package/dist/prd/command.js
CHANGED
|
@@ -5,23 +5,23 @@ import { acceptanceText, criterionCommandProblem, isAcceptanceCriterion, loadPrd
|
|
|
5
5
|
import { agentInvocation, buildWatchdogInvocation, runAgent, isAgentAvailable, } from '../loop/runner.js';
|
|
6
6
|
import { resolveIdleMs } from '../loop/run-command.js';
|
|
7
7
|
import { detectHostAgent, resolveRunnerAgent } from '../agents/host.js';
|
|
8
|
-
export const PRD_TEMPLATE = `# Yoke PRD — the loop picks the lowest-priority open story each iteration.
|
|
9
|
-
# Story format (see canon/loop/prd.schema.md):
|
|
10
|
-
# - id: STORY-1
|
|
11
|
-
# title: scaffold the project with a runnable test suite
|
|
12
|
-
# priority: 1
|
|
13
|
-
# needs: [] # optional story IDs that must pass first
|
|
14
|
-
# area: foundation # optional collision domain for parallel runs
|
|
15
|
-
# agent: codex # optional claude|codex|gemini affinity
|
|
16
|
-
# acceptance:
|
|
17
|
-
# - id: suite-runs
|
|
18
|
-
# text: "the project test suite can run"
|
|
19
|
-
# verify: ["npm run test:suite-runs"]
|
|
20
|
-
# - id: scaffold-starts
|
|
21
|
-
# text: "the scaffolded application starts"
|
|
22
|
-
# verify: ["npm run test:scaffold-starts"]
|
|
23
|
-
# passes: false
|
|
24
|
-
[]
|
|
8
|
+
export const PRD_TEMPLATE = `# Yoke PRD — the loop picks the lowest-priority open story each iteration.
|
|
9
|
+
# Story format (see canon/loop/prd.schema.md):
|
|
10
|
+
# - id: STORY-1
|
|
11
|
+
# title: scaffold the project with a runnable test suite
|
|
12
|
+
# priority: 1
|
|
13
|
+
# needs: [] # optional story IDs that must pass first
|
|
14
|
+
# area: foundation # optional collision domain for parallel runs
|
|
15
|
+
# agent: codex # optional claude|codex|gemini affinity
|
|
16
|
+
# acceptance:
|
|
17
|
+
# - id: suite-runs
|
|
18
|
+
# text: "the project test suite can run"
|
|
19
|
+
# verify: ["npm run test:suite-runs"]
|
|
20
|
+
# - id: scaffold-starts
|
|
21
|
+
# text: "the scaffolded application starts"
|
|
22
|
+
# verify: ["npm run test:scaffold-starts"]
|
|
23
|
+
# passes: false
|
|
24
|
+
[]
|
|
25
25
|
`;
|
|
26
26
|
export const MAX_PLANNING_BRIEF_CHARS = 20_000;
|
|
27
27
|
export const MAX_PLANNING_BRIEF_BYTES = MAX_PLANNING_BRIEF_CHARS * 4;
|
|
@@ -6,21 +6,21 @@ import { hasWsl } from '../wsl.js';
|
|
|
6
6
|
import { detectGstack } from '../gstack.js';
|
|
7
7
|
import { PRESERVE_SCAFFOLD } from '../preserve.js';
|
|
8
8
|
import { skillPackageActions } from '../skill-actions.js';
|
|
9
|
-
const GSTACK_COMPOSE = `## Composed tools (gstack detected)
|
|
10
|
-
|
|
11
|
-
This project also has [gstack](https://github.com/garrytan/gstack) installed. For capabilities Yoke does not ship, prefer gstack's skills:
|
|
12
|
-
|
|
13
|
-
- Live-browser QA → \`/qa\`
|
|
14
|
-
- Security audit → \`/cso\`
|
|
15
|
-
- Ship / deploy → \`/ship\`, \`/land-and-deploy\`
|
|
9
|
+
const GSTACK_COMPOSE = `## Composed tools (gstack detected)
|
|
10
|
+
|
|
11
|
+
This project also has [gstack](https://github.com/garrytan/gstack) installed. For capabilities Yoke does not ship, prefer gstack's skills:
|
|
12
|
+
|
|
13
|
+
- Live-browser QA → \`/qa\`
|
|
14
|
+
- Security audit → \`/cso\`
|
|
15
|
+
- Ship / deploy → \`/ship\`, \`/land-and-deploy\`
|
|
16
16
|
`;
|
|
17
|
-
const claudeMd = (rtkNote, composeNote) => `# Project Instructions
|
|
18
|
-
|
|
19
|
-
This project uses the Yoke harness. Baseline instructions:
|
|
20
|
-
|
|
21
|
-
@AGENTS.md
|
|
22
|
-
${rtkNote ? `\n${rtkNote}\n` : ''}${composeNote ? `\n${composeNote}\n` : ''}
|
|
23
|
-
${PRESERVE_SCAFFOLD}
|
|
17
|
+
const claudeMd = (rtkNote, composeNote) => `# Project Instructions
|
|
18
|
+
|
|
19
|
+
This project uses the Yoke harness. Baseline instructions:
|
|
20
|
+
|
|
21
|
+
@AGENTS.md
|
|
22
|
+
${rtkNote ? `\n${rtkNote}\n` : ''}${composeNote ? `\n${composeNote}\n` : ''}
|
|
23
|
+
${PRESERVE_SCAFFOLD}
|
|
24
24
|
`;
|
|
25
25
|
export function planClaude(canonDir, targetDir, wslAvailable = hasWsl(), codeGraph = 'graphify', gstackDetected = detectGstack(targetDir)) {
|
|
26
26
|
const manifest = loadManifest(join(canonDir, 'manifest.yaml'));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const PRESERVE_START = '<!-- yoke:preserve:start -->';
|
|
2
2
|
export const PRESERVE_END = '<!-- yoke:preserve:end -->';
|
|
3
|
-
export const PRESERVE_SCAFFOLD = `${PRESERVE_START}
|
|
4
|
-
<!-- Project-specific instructions go here. Yoke keeps this block across retrofits. -->
|
|
3
|
+
export const PRESERVE_SCAFFOLD = `${PRESERVE_START}
|
|
4
|
+
<!-- Project-specific instructions go here. Yoke keeps this block across retrofits. -->
|
|
5
5
|
${PRESERVE_END}`;
|
|
6
6
|
/**
|
|
7
7
|
* Extract the inner content of every balanced preserve-marker pair, in order.
|
package/docs/MIGRATING-TO-1.0.md
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
# Migrating to Yoke 1.0
|
|
2
|
-
|
|
3
|
-
Yoke 1.0 changes unsafe implicit behavior into explicit policy.
|
|
4
|
-
|
|
5
|
-
## Runner permissions
|
|
6
|
-
|
|
7
|
-
The default is `runner.permissions: safe`. Automation that intentionally requires a full
|
|
8
|
-
sandbox bypass must pass `--unsafe` or configure `runner.permissions: unsafe`. Use
|
|
9
|
-
`read-only` for planning and probing.
|
|
10
|
-
|
|
11
|
-
## Reviews
|
|
12
|
-
|
|
13
|
-
Reviewers write `.yoke/review-verdict.json`; Yoke validates and consumes it. The reviewer must
|
|
14
|
-
differ from the implementer unless `--allow-self-review` is explicit. CI can add `--json`.
|
|
15
|
-
|
|
16
|
-
## Commit ownership
|
|
17
|
-
|
|
18
|
-
Yoke resolves identity before implementation. Configure it when Git has no identity:
|
|
19
|
-
|
|
20
|
-
```yaml
|
|
21
|
-
commit:
|
|
22
|
-
authorName: HECer
|
|
23
|
-
authorEmail: hec_er@web.de
|
|
24
|
-
allowCoAuthors: false
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## PRDs, audit, and cleanup
|
|
28
|
-
|
|
29
|
-
Existing PRDs remain valid. Optional `needs`, `area`, and `agent` fields add dependencies,
|
|
30
|
-
collision domains, and affinity. Enable the story audit gate with `audit.enabled: true` and
|
|
31
|
-
version suppressions with `suppressionsVersion: 1`.
|
|
32
|
-
|
|
33
|
-
`yoke loop cleanup` now reports retained worktrees. Add `--remove-worktrees` for deletion.
|
|
1
|
+
# Migrating to Yoke 1.0
|
|
2
|
+
|
|
3
|
+
Yoke 1.0 changes unsafe implicit behavior into explicit policy.
|
|
4
|
+
|
|
5
|
+
## Runner permissions
|
|
6
|
+
|
|
7
|
+
The default is `runner.permissions: safe`. Automation that intentionally requires a full
|
|
8
|
+
sandbox bypass must pass `--unsafe` or configure `runner.permissions: unsafe`. Use
|
|
9
|
+
`read-only` for planning and probing.
|
|
10
|
+
|
|
11
|
+
## Reviews
|
|
12
|
+
|
|
13
|
+
Reviewers write `.yoke/review-verdict.json`; Yoke validates and consumes it. The reviewer must
|
|
14
|
+
differ from the implementer unless `--allow-self-review` is explicit. CI can add `--json`.
|
|
15
|
+
|
|
16
|
+
## Commit ownership
|
|
17
|
+
|
|
18
|
+
Yoke resolves identity before implementation. Configure it when Git has no identity:
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
commit:
|
|
22
|
+
authorName: HECer
|
|
23
|
+
authorEmail: hec_er@web.de
|
|
24
|
+
allowCoAuthors: false
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## PRDs, audit, and cleanup
|
|
28
|
+
|
|
29
|
+
Existing PRDs remain valid. Optional `needs`, `area`, and `agent` fields add dependencies,
|
|
30
|
+
collision domains, and affinity. Enable the story audit gate with `audit.enabled: true` and
|
|
31
|
+
version suppressions with `suppressionsVersion: 1`.
|
|
32
|
+
|
|
33
|
+
`yoke loop cleanup` now reports retained worktrees. Add `--remove-worktrees` for deletion.
|
package/docs/MIGRATING-TO-1.1.md
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
# Migrating to Yoke 1.1
|
|
2
|
-
|
|
3
|
-
Yoke 1.1 makes Claude, Codex, and Gemini share the same setup, planning, runner-selection, and decision behavior.
|
|
4
|
-
|
|
5
|
-
Run the setup wizard once in an existing project:
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npx @hecer/yoke@1.1.0 setup .
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
It preserves existing Yoke configuration and asks for target agents, code graph, loop state, default runner, and decision mode. A non-interactive agent can apply explicit choices with `--yes`.
|
|
12
|
-
|
|
13
|
-
The new config fields are optional and backward-compatible:
|
|
14
|
-
|
|
15
|
-
```yaml
|
|
16
|
-
runner:
|
|
17
|
-
agent: codex
|
|
18
|
-
permissions: safe
|
|
19
|
-
loop:
|
|
20
|
-
enabled: true
|
|
21
|
-
timeoutMinutes: 30
|
|
22
|
-
decisionPolicy: critical # auto | critical
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
`loop.onAmbiguity: resolve|abort` and `--on-ambiguity=` still work. Prefer `decisionPolicy` for new projects: `auto` resolves routine choices without asking; `critical` pauses only for high-impact decisions and continues after `yoke loop answer`. Resume restores the original isolation, review, runner, permissions, timeout, and policy flags instead of silently weakening the run. If the restart cannot begin, `yoke loop resume` retries from the request-bound state stored under Git's private state directory.
|
|
26
|
-
|
|
27
|
-
Restart an already-open Codex task after retrofit if it does not discover the newly generated `.agents/skills/yoke-workflow/SKILL.md`.
|
|
1
|
+
# Migrating to Yoke 1.1
|
|
2
|
+
|
|
3
|
+
Yoke 1.1 makes Claude, Codex, and Gemini share the same setup, planning, runner-selection, and decision behavior.
|
|
4
|
+
|
|
5
|
+
Run the setup wizard once in an existing project:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @hecer/yoke@1.1.0 setup .
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
It preserves existing Yoke configuration and asks for target agents, code graph, loop state, default runner, and decision mode. A non-interactive agent can apply explicit choices with `--yes`.
|
|
12
|
+
|
|
13
|
+
The new config fields are optional and backward-compatible:
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
runner:
|
|
17
|
+
agent: codex
|
|
18
|
+
permissions: safe
|
|
19
|
+
loop:
|
|
20
|
+
enabled: true
|
|
21
|
+
timeoutMinutes: 30
|
|
22
|
+
decisionPolicy: critical # auto | critical
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`loop.onAmbiguity: resolve|abort` and `--on-ambiguity=` still work. Prefer `decisionPolicy` for new projects: `auto` resolves routine choices without asking; `critical` pauses only for high-impact decisions and continues after `yoke loop answer`. Resume restores the original isolation, review, runner, permissions, timeout, and policy flags instead of silently weakening the run. If the restart cannot begin, `yoke loop resume` retries from the request-bound state stored under Git's private state directory.
|
|
26
|
+
|
|
27
|
+
Restart an already-open Codex task after retrofit if it does not discover the newly generated `.agents/skills/yoke-workflow/SKILL.md`.
|