@mrciphersmith/keryx 0.2.97 → 0.2.99
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/dist/cli.js +4583 -2702
- package/dist/core.js +40 -2
- package/package.json +1 -1
- package/src/gdskills/bundled/rules/core/api-contracts.mdc +1 -0
- package/src/gdskills/bundled/rules/core/cli-interface-design.mdc +237 -0
- package/src/gdskills/bundled/rules/core/code-style-patterns.mdc +1 -0
- package/src/gdskills/bundled/rules/core/database-patterns.mdc +1 -0
- package/src/gdskills/bundled/rules/core/definition-of-done.mdc +116 -0
- package/src/gdskills/bundled/rules/core/documentation-management.mdc +33 -38
- package/src/gdskills/bundled/rules/core/error-handling.mdc +1 -11
- package/src/gdskills/bundled/rules/core/execution-metrics.md +1 -2
- package/src/gdskills/bundled/rules/core/frontend-assistant.mdc +1 -0
- package/src/gdskills/bundled/rules/core/git-concurrency.mdc +101 -0
- package/src/gdskills/bundled/rules/core/implementation-plans.mdc +23 -11
- package/src/gdskills/bundled/rules/core/mobx-store-template.mdc +1 -0
- package/src/gdskills/bundled/rules/core/nestjs-dto.mdc +1 -0
- package/src/gdskills/bundled/rules/core/playwright-testing.mdc +1 -0
- package/src/gdskills/bundled/rules/core/requirements-management.mdc +15 -11
- package/src/gdskills/bundled/rules/core/rule-management-workflow.mdc +29 -14
- package/src/gdskills/bundled/rules/core/shared-definitions.mdc +1 -1
- package/src/gdskills/bundled/rules/core/skill-lifecycle.mdc +9 -5
- package/src/gdskills/bundled/rules/core/skills-storage-workflow.mdc +156 -23
- package/src/gdskills/bundled/rules/core/storybook-guidelines.mdc +1 -0
- package/src/gdskills/bundled/rules/core/subagent-status-protocol.md +9 -2
- package/src/gdskills/bundled/skills/core/reviewer-skill-creator/SKILL.md +42 -5
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.md +67 -74
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.md +24 -8
- package/src/gdskills/bundled/skills/orchestration/context-collector/orchestrator-prompt.md +2 -2
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.detail.md +12 -22
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.md +44 -31
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/analysis-request.md +2 -2
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/analysis-request.template.md +1 -1
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/input-contract.schema.json +4 -4
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/orchestrator-prompt.md +2 -2
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.md +20 -6
- package/src/gdskills/bundled/skills/orchestration/flow-orchestrator/SKILL.md +67 -9
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.md +6 -6
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/orchestrator-prompt.md +1 -1
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.md +45 -5
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.md +88 -32
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.md +52 -41
- package/src/gdskills/bundled/skills/orchestration/task-implementer/output-contract.schema.json +32 -1
- package/src/gdskills/bundled/skills/planning/autodoc-analyst/SKILL.md +16 -0
- package/src/gdskills/bundled/skills/planning/autodoc-architect/SKILL.md +16 -0
- package/src/gdskills/bundled/skills/planning/autodoc-assembler/SKILL.md +16 -0
- package/src/gdskills/bundled/skills/planning/autodoc-orchestrator/SKILL.md +17 -0
- package/src/gdskills/bundled/skills/planning/autodoc-scanner/SKILL.md +16 -0
- package/src/gdskills/bundled/skills/planning/autodoc-writer/SKILL.md +16 -0
- package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.md +29 -4
- package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.codex.md +17 -0
- package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.cursor.md +17 -0
- package/src/gdskills/bundled/skills/planning/consistency-checker/SKILL.md +17 -0
- package/src/gdskills/bundled/skills/planning/docpack-orchestrator/SKILL.md +32 -2
- package/src/gdskills/bundled/skills/planning/docpack-review/SKILL.md +14 -2
- package/src/gdskills/bundled/skills/planning/interview/SKILL.md +30 -8
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.md +33 -7
- package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.codex.md +16 -0
- package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.cursor.md +16 -0
- package/src/gdskills/bundled/skills/planning/patterns-researcher/SKILL.md +16 -0
- package/src/gdskills/bundled/skills/planning/planner/SKILL.codex.md +17 -0
- package/src/gdskills/bundled/skills/planning/planner/SKILL.cursor.md +17 -0
- package/src/gdskills/bundled/skills/planning/planner/SKILL.md +17 -0
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.md +27 -10
- package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.codex.md +16 -0
- package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.cursor.md +16 -0
- package/src/gdskills/bundled/skills/planning/problem-definer/SKILL.md +16 -0
- package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.codex.md +16 -0
- package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.cursor.md +16 -0
- package/src/gdskills/bundled/skills/planning/project-discovery/SKILL.md +16 -0
- package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.codex.md +4 -0
- package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.cursor.md +4 -0
- package/src/gdskills/bundled/skills/planning/spec-writer/SKILL.md +4 -0
- package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.codex.md +4 -0
- package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.cursor.md +4 -0
- package/src/gdskills/bundled/skills/planning/stack-advisor/SKILL.md +4 -0
- package/src/gdskills/bundled/skills/platform/agent-entrypoint-distiller/SKILL.md +31 -4
- package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.md +27 -3
- package/src/gdskills/bundled/skills/platform/hookify/SKILL.md +29 -4
- package/src/gdskills/bundled/skills/quality/api-truth/SKILL.md +226 -0
- package/src/gdskills/bundled/skills/quality/changelog/SKILL.md +25 -5
- package/src/gdskills/bundled/skills/quality/commit/SKILL.md +26 -5
- package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.md +25 -4
- package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.md +26 -5
- package/src/gdskills/bundled/skills/quality/deploy/SKILL.md +27 -4
- package/src/gdskills/bundled/skills/quality/deprecation-path/SKILL.md +268 -0
- package/src/gdskills/bundled/skills/quality/fresh-eyes/SKILL.md +190 -0
- package/src/gdskills/bundled/skills/quality/metaproject-security/SKILL.md +24 -3
- package/src/gdskills/bundled/skills/quality/perf-check/SKILL.md +30 -9
- package/src/gdskills/bundled/skills/quality/pr/SKILL.md +25 -5
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.md +27 -4
- package/src/gdskills/bundled/skills/quality/push/SKILL.md +25 -4
- package/src/gdskills/bundled/skills/quality/root-cause/SKILL.md +204 -0
- package/src/gdskills/bundled/skills/quality/security-audit/SKILL.md +25 -4
- package/src/gdskills/bundled/skills/quality/test-gen/SKILL.md +31 -5
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.md +32 -11
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.md +42 -7
- package/src/gdskills/bundled/skills/review/code-learned-review/SKILL.md +43 -3
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.md +46 -4
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.md +46 -6
- package/src/gdskills/bundled/skills/review/review-architecture/SKILL.md +5 -5
- package/src/gdskills/bundled/skills/review/review-backend/SKILL.md +5 -6
- package/src/gdskills/bundled/skills/review/review-clean-code/SKILL.md +6 -6
- package/src/gdskills/bundled/skills/review/review-core-boundaries/SKILL.md +37 -3
- package/src/gdskills/bundled/skills/review/review-flow-graph/SKILL.md +38 -4
- package/src/gdskills/bundled/skills/review/review-frontend/SKILL.md +4 -6
- package/src/gdskills/bundled/skills/review/review-frontend-conventions/SKILL.md +37 -3
- package/src/gdskills/bundled/skills/review/review-highload/SKILL.md +5 -7
- package/src/gdskills/bundled/skills/review/review-layout/SKILL.md +24 -3
- package/src/gdskills/bundled/skills/review/review-logic/SKILL.md +5 -5
- package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +49 -64
- package/src/gdskills/bundled/skills/review/review-orchestrator/input-contract.schema.json +1 -2
- package/src/gdskills/bundled/skills/review/review-orchestrator/review-context.schema.json +1 -5
- package/src/gdskills/bundled/skills/review/review-orchestrator/reviewer-input.schema.json +53 -9
- package/src/gdskills/bundled/skills/review/review-performance/SKILL.md +11 -11
- package/src/gdskills/bundled/skills/review/review-pr-feedback/SKILL.md +9 -8
- package/src/gdskills/bundled/skills/review/review-regression/SKILL.md +33 -2
- package/src/gdskills/bundled/skills/review/review-security-code/SKILL.md +6 -4
- package/src/gdskills/bundled/skills/review/review-style/SKILL.md +5 -5
- package/src/gdskills/bundled/skills/review/review-testing-practices/SKILL.md +41 -3
- package/src/gdskills/bundled/skills/review/review-verifier/SKILL.md +2 -2
- package/src/gdskills/bundled/rules/core/review-agent-profile.mdc +0 -49
- package/src/gdskills/bundled/rules/core/review-strict-profile.mdc +0 -48
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.codex.md +0 -353
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.cursor.md +0 -353
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.opencode.md +0 -353
- package/src/gdskills/bundled/skills/orchestration/code-verifier/SKILL.zed.md +0 -353
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.codex.md +0 -655
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.cursor.md +0 -655
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.opencode.md +0 -655
- package/src/gdskills/bundled/skills/orchestration/context-collector/SKILL.zed.md +0 -655
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.codex.md +0 -434
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.cursor.md +0 -434
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.opencode.md +0 -434
- package/src/gdskills/bundled/skills/orchestration/feature-analyzer/SKILL.zed.md +0 -434
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.codex.md +0 -163
- package/src/gdskills/bundled/skills/orchestration/feature-dev/SKILL.cursor.md +0 -163
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.codex.md +0 -373
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.cursor.md +0 -373
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.opencode.md +0 -373
- package/src/gdskills/bundled/skills/orchestration/issue-analyzer/SKILL.zed.md +0 -373
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.codex.md +0 -374
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.cursor.md +0 -374
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.opencode.md +0 -374
- package/src/gdskills/bundled/skills/orchestration/job-documenter/SKILL.zed.md +0 -374
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.codex.md +0 -2190
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.cursor.md +0 -2190
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.opencode.md +0 -2190
- package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.zed.md +0 -2190
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.codex.md +0 -659
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.cursor.md +0 -659
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.opencode.md +0 -659
- package/src/gdskills/bundled/skills/orchestration/task-implementer/SKILL.zed.md +0 -659
- package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.codex.md +0 -90
- package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.cursor.md +0 -90
- package/src/gdskills/bundled/skills/planning/interview/SKILL.codex.md +0 -187
- package/src/gdskills/bundled/skills/planning/interview/SKILL.cursor.md +0 -187
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.codex.md +0 -105
- package/src/gdskills/bundled/skills/planning/interviewer/SKILL.cursor.md +0 -105
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.codex.md +0 -193
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.cursor.md +0 -193
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.opencode.md +0 -193
- package/src/gdskills/bundled/skills/planning/prd-creator/SKILL.zed.md +0 -193
- package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.codex.md +0 -87
- package/src/gdskills/bundled/skills/platform/claude-md-management/SKILL.cursor.md +0 -87
- package/src/gdskills/bundled/skills/platform/hookify/SKILL.codex.md +0 -100
- package/src/gdskills/bundled/skills/platform/hookify/SKILL.cursor.md +0 -100
- package/src/gdskills/bundled/skills/quality/changelog/SKILL.codex.md +0 -84
- package/src/gdskills/bundled/skills/quality/changelog/SKILL.cursor.md +0 -84
- package/src/gdskills/bundled/skills/quality/commit/SKILL.codex.md +0 -66
- package/src/gdskills/bundled/skills/quality/commit/SKILL.cursor.md +0 -66
- package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.codex.md +0 -66
- package/src/gdskills/bundled/skills/quality/db-migrate/SKILL.cursor.md +0 -66
- package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.codex.md +0 -81
- package/src/gdskills/bundled/skills/quality/dependency-update/SKILL.cursor.md +0 -81
- package/src/gdskills/bundled/skills/quality/deploy/SKILL.codex.md +0 -70
- package/src/gdskills/bundled/skills/quality/deploy/SKILL.cursor.md +0 -70
- package/src/gdskills/bundled/skills/quality/perf-check/SKILL.codex.md +0 -83
- package/src/gdskills/bundled/skills/quality/perf-check/SKILL.cursor.md +0 -83
- package/src/gdskills/bundled/skills/quality/pr/SKILL.codex.md +0 -75
- package/src/gdskills/bundled/skills/quality/pr/SKILL.cursor.md +0 -75
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.codex.md +0 -378
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.cursor.md +0 -378
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.opencode.md +0 -378
- package/src/gdskills/bundled/skills/quality/pr-issue-documenter/SKILL.zed.md +0 -378
- package/src/gdskills/bundled/skills/quality/push/SKILL.codex.md +0 -52
- package/src/gdskills/bundled/skills/quality/push/SKILL.cursor.md +0 -52
- package/src/gdskills/bundled/skills/quality/security-audit/SKILL.codex.md +0 -108
- package/src/gdskills/bundled/skills/quality/security-audit/SKILL.cursor.md +0 -108
- package/src/gdskills/bundled/skills/quality/test-gen/SKILL.codex.md +0 -75
- package/src/gdskills/bundled/skills/quality/test-gen/SKILL.cursor.md +0 -75
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.codex.md +0 -339
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.cursor.md +0 -339
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.opencode.md +0 -339
- package/src/gdskills/bundled/skills/quality/tests-creator/SKILL.zed.md +0 -339
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.codex.md +0 -203
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.cursor.md +0 -203
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.opencode.md +0 -203
- package/src/gdskills/bundled/skills/review/code-ai-review/SKILL.zed.md +0 -203
- package/src/gdskills/bundled/skills/review/code-learned-review/SKILL.codex.md +0 -243
- package/src/gdskills/bundled/skills/review/code-learned-review/SKILL.cursor.md +0 -243
- package/src/gdskills/bundled/skills/review/code-learned-review/SKILL.opencode.md +0 -243
- package/src/gdskills/bundled/skills/review/code-learned-review/SKILL.zed.md +0 -243
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.codex.md +0 -259
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.cursor.md +0 -259
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.opencode.md +0 -259
- package/src/gdskills/bundled/skills/review/code-mobx-store-review/SKILL.zed.md +0 -259
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.codex.md +0 -168
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.cursor.md +0 -168
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.opencode.md +0 -168
- package/src/gdskills/bundled/skills/review/code-style-review/SKILL.zed.md +0 -168
|
@@ -1,2190 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: job-orchestrator
|
|
3
|
-
description: "Use when a GitHub issue or complex intent needs to be analyzed, planned, and implemented end-to-end with sub-agents."
|
|
4
|
-
triggers:
|
|
5
|
-
- "Implement issue"
|
|
6
|
-
- "Issue to PR"
|
|
7
|
-
- "Orchestrate"
|
|
8
|
-
- "Run pipeline"
|
|
9
|
-
- "Analyze and implement"
|
|
10
|
-
- "Full implementation"
|
|
11
|
-
- "Full review"
|
|
12
|
-
- "Полное ревью"
|
|
13
|
-
- "Review my code"
|
|
14
|
-
- "Analyze branch"
|
|
15
|
-
- "Review via orchestrator"
|
|
16
|
-
- "Orchestrated review"
|
|
17
|
-
- "Auto-implement"
|
|
18
|
-
- "Auto-implement issue"
|
|
19
|
-
- "Orchestrate issue"
|
|
20
|
-
- "Run issue pipeline"
|
|
21
|
-
- "Full issue implementation"
|
|
22
|
-
metadata:
|
|
23
|
-
author: "MrCipherSmith"
|
|
24
|
-
version: "3.2.0"
|
|
25
|
-
category: "orchestration"
|
|
26
|
-
compatible_harnesses: "cursor,codex,zed,opencode,claude"
|
|
27
|
-
license: "MIT"
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
<SUBAGENT-STOP>
|
|
31
|
-
If you were dispatched as a subagent to execute a specific task, skip this skill entirely.
|
|
32
|
-
This skill is for orchestrators and interactive session-level routing only.
|
|
33
|
-
Proceed directly with your assigned task.
|
|
34
|
-
</SUBAGENT-STOP>
|
|
35
|
-
|
|
36
|
-
# Job Orchestrator
|
|
37
|
-
|
|
38
|
-
## Purpose
|
|
39
|
-
|
|
40
|
-
Dynamic orchestrator that builds execution plans based on user intent. Unlike a fixed pipeline, the orchestrator adapts its workflow to what the user actually needs — from "just analyze this issue" to "implement, review, and create a PR". It dispatches sub-agents (`issue-analyzer`, `context-collector`, `tests-creator`, `task-implementer`, `code-verifier`, `review-orchestrator`) and persists every step, document and retry through `keryx job`, which writes `.metaproject/jobs/<job-name>/`.
|
|
41
|
-
|
|
42
|
-
**The package is the state.** `keryx job` is the only writer of `state.json`; it validates every write against the registered contract `job-orchestrator-state` and refuses one that does not conform. Never hand-write `state.json`, and never hold a step's outcome only in this session — a step recorded nowhere is a step that did not happen as far as the next session is concerned.
|
|
43
|
-
|
|
44
|
-
**Execution metrics (opt-in):** when a USER runs this orchestrator directly (not as a dispatched subagent), at the start ask "Collect execution statistics for this run? (yes/no)" per `.metaproject/rules/core/execution-metrics.md`. If yes, append the `## Execution Metrics` section at the end and save it under the job dir (`jobs/<job>/metrics/`). Never ask or emit it when dispatched as a subagent.
|
|
45
|
-
|
|
46
|
-
**Key design principle** (from Anthropic's "Building Effective Agents"):
|
|
47
|
-
> "The key difference from parallelization is its flexibility — subtasks aren't pre-defined, but determined by the orchestrator based on the specific input."
|
|
48
|
-
|
|
49
|
-
**Input:** User request (issue URL, analysis request, implementation request, etc.)
|
|
50
|
-
**Output:** Executed plan + persistent job documentation in `.metaproject/jobs/<job-name>/` + optional PR
|
|
51
|
-
|
|
52
|
-
## When to Use
|
|
53
|
-
|
|
54
|
-
- Implementing a complete GitHub issue from start to finish
|
|
55
|
-
- Analyzing an issue and proposing a solution before implementing
|
|
56
|
-
- Running any multi-step orchestrated workflow
|
|
57
|
-
- Running a comprehensive code review with persistent documentation
|
|
58
|
-
- When the AGENTS.md routing rule (Step 1.5) determines the user wants orchestrated execution and the user confirms
|
|
59
|
-
- User says "implement issue #N", "analyze issue #N", provides an issue URL, or asks for orchestrated work
|
|
60
|
-
- User says "full review", "полное ревью", or any request that implies orchestration
|
|
61
|
-
|
|
62
|
-
## Architecture: 4 Dynamic Phases
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
Phase 0: CONTEXT COLLECTION → Gather info, determine intent
|
|
66
|
-
Phase 1: PLAN BUILDING → Build dynamic plan, init job docs
|
|
67
|
-
Phase 2: EXECUTION → Execute plan steps, document each result
|
|
68
|
-
Phase 3: COMPLETION → Final report, optional PR, tell user where docs are
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## Phase 0: CONTEXT COLLECTION
|
|
74
|
-
|
|
75
|
-
### 0.0 State Resumption Check
|
|
76
|
-
|
|
77
|
-
Before asking any questions, list existing job packages:
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
keryx job list --json
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Every entry carries `phase`, `stepsDone`/`stepsTotal` and `nextStep`. A job whose
|
|
84
|
-
`phase` is not `COMPLETION` is unfinished.
|
|
85
|
-
|
|
86
|
-
1. If an unfinished job exists, ASK the user:
|
|
87
|
-
"Found unfinished job '<job-name>' (<stepsDone>/<stepsTotal> steps, next: <nextStep>).
|
|
88
|
-
Resume it or start a new orchestrated job?"
|
|
89
|
-
2. If resume → read the package and jump directly to the step it names:
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
keryx job status <job-name> --json
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
`next_step` is the first step that is neither `completed` nor `skipped` — computed
|
|
96
|
-
from the file, not recalled. `retries` gives the recorded attempt count per step, so
|
|
97
|
-
a resumed session continues from the real number instead of restarting at zero, and
|
|
98
|
-
`documents` lists what has already been produced.
|
|
99
|
-
3. If new → proceed to 0.1.
|
|
100
|
-
|
|
101
|
-
There is no `paused` status and nothing writes one. A job is unfinished exactly when a
|
|
102
|
-
step is still open, and `keryx job status` is what reports that.
|
|
103
|
-
|
|
104
|
-
### 0.1 Determine User Intent
|
|
105
|
-
|
|
106
|
-
Parse the user's request to identify the intent:
|
|
107
|
-
|
|
108
|
-
| User Says | Intent | Plan Type |
|
|
109
|
-
|-----------|--------|-----------|
|
|
110
|
-
| "Implement issue #N" / "Issue to PR" | `implement` | Full: analyze → branch → implement → verify → review → fix → PR |
|
|
111
|
-
| "Analyze issue #N" / "Study issue" | `analyze` | Analysis only: analyze → report. Then ask if user wants to implement. |
|
|
112
|
-
| "Review my code" / "Review branch" | `review` | Review only: review → report |
|
|
113
|
-
| "Analyze and implement" | `implement` | Same as implement |
|
|
114
|
-
| Custom request | `custom` | Run `interviewer` skill first, then build plan from output |
|
|
115
|
-
|
|
116
|
-
**Ambiguity detection:** If the request uses vague words ("improve", "fix", "refactor") with no issue number or specific file — trigger the **Interactive Approach Selection** below.
|
|
117
|
-
|
|
118
|
-
### 0.1.1 Interactive Approach Selection (for ambiguous requests)
|
|
119
|
-
|
|
120
|
-
When intent cannot be determined confidently, present options to the user:
|
|
121
|
-
|
|
122
|
-
```
|
|
123
|
-
I see several ways to approach this. Which fits best?
|
|
124
|
-
|
|
125
|
-
A) 🔍 Analysis only — decompose into tasks, show plan, stop
|
|
126
|
-
B) 🛠 Full implementation — analyze → implement → review → PR
|
|
127
|
-
C) 📋 Analysis + brainstorm — explore approaches before committing
|
|
128
|
-
D) 🔧 Review only — review current branch changes
|
|
129
|
-
E) 📝 Custom — describe what you need, I'll build the plan
|
|
130
|
-
|
|
131
|
-
> pick a letter or describe your own approach
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
**Mapping:**
|
|
135
|
-
- A → `analyze` intent
|
|
136
|
-
- B → `implement` intent
|
|
137
|
-
- C → `analyze` intent + trigger `brainstorm` after analysis
|
|
138
|
-
- D → `review` intent
|
|
139
|
-
- E → `custom` intent → proceed to 0.1.5 (interviewer gate)
|
|
140
|
-
|
|
141
|
-
**Skip this step** when intent is clear (explicit issue number, "implement issue #N", "review my code").
|
|
142
|
-
|
|
143
|
-
### 0.1.5 Interviewer Gate (for `custom` and ambiguous requests)
|
|
144
|
-
|
|
145
|
-
For `custom` intent OR any ambiguous request, invoke the `interviewer` skill **before** collecting standard context. This replaces the generic "What do you need?" question with a structured critical interview.
|
|
146
|
-
|
|
147
|
-
**Invoke:**
|
|
148
|
-
```
|
|
149
|
-
Load skill: skills/gdskills/planning/interviewer/SKILL.md
|
|
150
|
-
|
|
151
|
-
INPUT:
|
|
152
|
-
topic: <user's original request>
|
|
153
|
-
goal: "job-orchestrator — build execution plan"
|
|
154
|
-
context:
|
|
155
|
-
codebase_summary: <git log --oneline -10 if available>
|
|
156
|
-
existing_analysis: <any issue content already known>
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
**Map output:**
|
|
160
|
-
- `derived_context` → `INTENT_STATE.task_description`
|
|
161
|
-
- answers with `confidence: "certain"` → `INTENT_STATE.constraints`
|
|
162
|
-
- `blockers` → surface to user (if non-empty, do NOT proceed)
|
|
163
|
-
|
|
164
|
-
**Gate rule:**
|
|
165
|
-
- `ready_to_proceed: false` → STOP. Tell user what blockers remain.
|
|
166
|
-
- `ready_to_proceed: true` → continue to 0.2 with enriched context.
|
|
167
|
-
|
|
168
|
-
**Skip** for `implement`/`analyze` with an issue number — requirements are in the issue.
|
|
169
|
-
|
|
170
|
-
### 0.2 Collect Required Context
|
|
171
|
-
|
|
172
|
-
The orchestrator MUST collect all required context before proceeding:
|
|
173
|
-
|
|
174
|
-
**Always ask (mandatory):**
|
|
175
|
-
|
|
176
|
-
1. **What to do** — for `implement`/`analyze`: from issue. For `custom`: from interviewer output (0.1.5).
|
|
177
|
-
|
|
178
|
-
2. **Project directory** — NEVER assume. Always ask explicitly:
|
|
179
|
-
```
|
|
180
|
-
Which project directory should I use?
|
|
181
|
-
○ Type the full absolute path to your project
|
|
182
|
-
(No default — always ask, never assume.)
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
3. **Base branch** — auto-detect from repo:
|
|
186
|
-
```bash
|
|
187
|
-
# Detect default branch
|
|
188
|
-
git -C <project_dir> symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'
|
|
189
|
-
# Fallback: check for main, master, develop
|
|
190
|
-
```
|
|
191
|
-
Present detected branch and ask to confirm. No hardcoded default — and
|
|
192
|
-
`input-contract.schema.json` declares none either, so the contract cannot
|
|
193
|
-
reintroduce one behind the question.
|
|
194
|
-
|
|
195
|
-
**Intent-specific questions:**
|
|
196
|
-
|
|
197
|
-
| Intent | Additional Questions |
|
|
198
|
-
|--------|---------------------|
|
|
199
|
-
| `implement` | Create PR? (default: yes). Skip if user already stated. |
|
|
200
|
-
| `analyze` | None — always produced. After: ask if user wants to implement. |
|
|
201
|
-
| `review` | Which branch to review? (default: current branch) |
|
|
202
|
-
| `custom` | None — covered by interviewer in 0.1.5 |
|
|
203
|
-
|
|
204
|
-
4. **Job name** — auto-generate based on context, ask user to confirm:
|
|
205
|
-
```
|
|
206
|
-
Job documentation folder:
|
|
207
|
-
○ issue-4141--pipeline-validation (auto-generated, Recommended)
|
|
208
|
-
○ Type your own name
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
**Naming patterns:**
|
|
212
|
-
- Issue implementation: `issue-<N>--<slug>`
|
|
213
|
-
- Issue analysis: `analysis--issue-<N>`
|
|
214
|
-
- Code review: `review--<slug>`
|
|
215
|
-
- Custom: `task--<slug>`
|
|
216
|
-
|
|
217
|
-
### 0.3 Interview for Implement Intent
|
|
218
|
-
|
|
219
|
-
For `implement` intent, dispatch `interview` skill after collecting context to clarify implementation-specific ambiguities (complements 0.1.5 which handles `custom` intent):
|
|
220
|
-
|
|
221
|
-
```
|
|
222
|
-
Dispatch interview skill with:
|
|
223
|
-
{
|
|
224
|
-
"goal": <issue title>,
|
|
225
|
-
"context": <collected context + issue body>,
|
|
226
|
-
"domain": "implement",
|
|
227
|
-
"caller": "job-orchestrator",
|
|
228
|
-
"known_facts": [project_dir, base_branch, issue details],
|
|
229
|
-
"max_questions": null
|
|
230
|
-
}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
**When to run:** `implement` intent only (if `run_interview: true`, default).
|
|
234
|
-
**Skip for:** `analyze` (analysis reveals details), `review` (scoped by diff), `custom` (covered by 0.1.5).
|
|
235
|
-
|
|
236
|
-
**Output → Phase 1:** `INTERVIEW_RESULT` feeds into plan building — informs task decomposition and architecture.
|
|
237
|
-
|
|
238
|
-
**Brainstorm trigger:** If during interview the user answers "not sure" or the interview identifies an unresolved architectural question (high-impact decision with no clear answer), auto-trigger:
|
|
239
|
-
```
|
|
240
|
-
Dispatch brainstorm --quick with:
|
|
241
|
-
topic: <the specific architectural question>
|
|
242
|
-
context: <project stack + interview answers so far>
|
|
243
|
-
```
|
|
244
|
-
Present brainstorm result as enriched answer options, then continue interview.
|
|
245
|
-
|
|
246
|
-
**Skip if:** user says "just do it" / "skip questions", or `run_interview: false`.
|
|
247
|
-
|
|
248
|
-
### 0.3.1 Dependency Check
|
|
249
|
-
|
|
250
|
-
If the issue or interview reveals the task is primarily about updating dependencies:
|
|
251
|
-
```
|
|
252
|
-
IF issue title/body contains "update", "upgrade", "bump", "dependency", "CVE":
|
|
253
|
-
Suggest: "This looks like a dependency update task. Use /dependency-update instead?"
|
|
254
|
-
IF user confirms → delegate to dependency-update skill, skip orchestrator pipeline
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### 0.4 Summarize and Confirm
|
|
258
|
-
|
|
259
|
-
Before proceeding, present a summary:
|
|
260
|
-
|
|
261
|
-
```
|
|
262
|
-
Ready to proceed:
|
|
263
|
-
Intent: implement
|
|
264
|
-
Issue: #4141 — Pipeline validation improvements
|
|
265
|
-
Project: /Users/.../<PROJECT>
|
|
266
|
-
Base: <detected base branch>
|
|
267
|
-
Create PR: yes
|
|
268
|
-
Job name: issue-4141--pipeline-validation
|
|
269
|
-
|
|
270
|
-
Proceed? (yes / adjust)
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
This is the **operator** gate and it is not governed by `skip_confirmation`. That
|
|
274
|
-
setting is `{"const": true}` in `input-contract.schema.json` and means exactly one
|
|
275
|
-
thing: dispatched sub-agents run without asking the operator to approve each
|
|
276
|
-
dispatch. It has never covered this question, and the two are named apart here so
|
|
277
|
-
the contract and the prose stop reading as a contradiction. The gate that *can* be
|
|
278
|
-
turned off is `plan_approval` in 1.3.
|
|
279
|
-
|
|
280
|
-
`job_name` must match `^[a-z0-9-]+$` — the pattern `state.schema.json` declares and
|
|
281
|
-
`keryx job init` enforces before it builds a path from the value. `issue-4141--pipeline-validation`
|
|
282
|
-
conforms; anything with a slash, a space or an uppercase letter is refused.
|
|
283
|
-
|
|
284
|
-
---
|
|
285
|
-
|
|
286
|
-
## Phase 1: PLAN BUILDING
|
|
287
|
-
|
|
288
|
-
### 1.1 Build Execution Plan
|
|
289
|
-
|
|
290
|
-
Based on intent, construct an ordered list of steps:
|
|
291
|
-
|
|
292
|
-
**For `implement` intent:**
|
|
293
|
-
```
|
|
294
|
-
PLAN:
|
|
295
|
-
1. { id: "analyze", type: "analyze", agent: "issue-analyzer", depends: [] }
|
|
296
|
-
2. { id: "context", type: "context", agent: "context-collector", depends: ["analyze"] }
|
|
297
|
-
3. { id: "prepare", type: "prepare", agent: "orchestrator", depends: ["context"] }
|
|
298
|
-
4. { id: "tests-creator", type: "tests", agent: "tests-creator", depends: ["prepare"] }
|
|
299
|
-
5. { id: "implement", type: "implement", agent: "task-implementer", depends: ["tests-creator"] }
|
|
300
|
-
6. { id: "sanity-check", type: "check", agent: "orchestrator", depends: ["implement"] }
|
|
301
|
-
7. { id: "verify", type: "verify", agent: "code-verifier", depends: ["sanity-check"] }
|
|
302
|
-
8. { id: "review", type: "review", agent: "review-orchestrator", depends: ["verify"] }
|
|
303
|
-
9. { id: "security", type: "security", agent: "security-audit", depends: ["implement"], conditional: true }
|
|
304
|
-
10. { id: "fix", type: "fix", agent: "task-implementer", depends: ["review"], conditional: true }
|
|
305
|
-
11. { id: "verify-post-fix", type: "verify", agent: "code-verifier", depends: ["fix"], conditional: true }
|
|
306
|
-
12. { id: "perf-check", type: "perf", agent: "perf-check", depends: ["verify"], conditional: true }
|
|
307
|
-
13. { id: "report", type: "report", agent: "orchestrator", depends: ["verify"] }
|
|
308
|
-
14. { id: "pr", type: "pr", agent: "orchestrator", depends: ["report"], conditional: true }
|
|
309
|
-
15. { id: "deploy", type: "deploy", agent: "deploy", depends: ["pr"], conditional: true }
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
This is the plan `keryx job init --intent implement` writes, step for step. The `agent`
|
|
313
|
-
field is the **label recorded in the plan**, not a dispatch target: the `review` step is
|
|
314
|
-
executed by `review-orchestrator` (2.6), and `orchestrator` means this skill does the
|
|
315
|
-
step itself. Read the recorded plan back at any time with `keryx job status <job-name>`.
|
|
316
|
-
|
|
317
|
-
**Conditional step triggers** — one row per step, no step listed twice:
|
|
318
|
-
|
|
319
|
-
| Step | Runs when |
|
|
320
|
-
|------|-----------|
|
|
321
|
-
| `sanity-check` | always — verifies ≥1 commit was made |
|
|
322
|
-
| `tests-creator` | always — mandatory TDD step before every task-implementer wave |
|
|
323
|
-
| `verify` | always — `code-verifier` is the mandatory quality gate after implementation |
|
|
324
|
-
| `security` | diff touches `auth/`, `api/`, migrations, schema files, or `.env` |
|
|
325
|
-
| `fix` | review or verify produced a `blocker` or `major` finding |
|
|
326
|
-
| `verify-post-fix` | after `fix` ran — confirms the fix resolved the findings |
|
|
327
|
-
| `perf-check` | diff contains `*.tsx`, `*.jsx`, `*.css`, `dist/` or `build/` files |
|
|
328
|
-
| `pr` | `create_pr: true` |
|
|
329
|
-
| `deploy` | user answers "yes" to the post-PR staging deploy prompt |
|
|
330
|
-
|
|
331
|
-
Severities are the canonical four — `blocker`, `major`, `minor`, `info` — from
|
|
332
|
-
`review-finding.schema.json`. They are the only vocabulary this skill uses, so the
|
|
333
|
-
`fix` trigger and the counts in the report are read off the same field.
|
|
334
|
-
|
|
335
|
-
Note: `security` runs in parallel with `review` (both depend on `implement` results, no overlap).
|
|
336
|
-
|
|
337
|
-
**A conditional step is not exempt from the record.** Every step in the plan is
|
|
338
|
-
written into the package by `keryx job init`, and `keryx job complete` refuses while
|
|
339
|
-
any step is neither `completed` nor `skipped`. A condition that did not fire is
|
|
340
|
-
closed explicitly:
|
|
341
|
-
|
|
342
|
-
```bash
|
|
343
|
-
keryx job step <job-name> perf-check --status skipped --reason "no frontend files in diff"
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
**For `analyze` intent:**
|
|
347
|
-
```
|
|
348
|
-
PLAN:
|
|
349
|
-
1. { id: "analyze", type: "analyze", agent: "issue-analyzer", depends: [] }
|
|
350
|
-
2. { id: "context", type: "context", agent: "context-collector", depends: ["analyze"] }
|
|
351
|
-
3. { id: "report", type: "report", agent: "orchestrator", depends: ["context"] }
|
|
352
|
-
4. { id: "proposal", type: "proposal", agent: "orchestrator", depends: ["report"] }
|
|
353
|
-
```
|
|
354
|
-
Step 4 (`proposal`) asks the user: "Want me to implement this? If yes, I'll extend the plan."
|
|
355
|
-
|
|
356
|
-
**For `review` intent:**
|
|
357
|
-
```
|
|
358
|
-
PLAN:
|
|
359
|
-
1. { id: "context", type: "context", agent: "context-collector", depends: [] }
|
|
360
|
-
2. { id: "review", type: "review", agent: "reviewers", depends: ["context"] }
|
|
361
|
-
3. { id: "report", type: "report", agent: "orchestrator", depends: ["review"] }
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
**For `custom` intent:**
|
|
365
|
-
Build plan dynamically. Each step must have: id, type, agent, dependencies.
|
|
366
|
-
|
|
367
|
-
### 1.2 Create the Job Package
|
|
368
|
-
|
|
369
|
-
Create the package with the CLI. This is one command, run by the orchestrator — not
|
|
370
|
-
a sub-agent dispatch:
|
|
371
|
-
|
|
372
|
-
```bash
|
|
373
|
-
keryx job init --name <job-name> --intent implement|analyze|review|custom --project <project_dir>
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
It creates `.metaproject/jobs/<job-name>/` containing:
|
|
377
|
-
|
|
378
|
-
- `state.json` — validated against the registered contract `job-orchestrator-state`
|
|
379
|
-
on **every** write. A state that does not conform is refused, not written.
|
|
380
|
-
- `journal.md` — append-only, one line per recorded event, written by `keryx job`.
|
|
381
|
-
- the plan for the chosen intent, every step `pending`, with `plan.current_step`
|
|
382
|
-
already pointing at the first one.
|
|
383
|
-
|
|
384
|
-
`--intent` defaults to `implement`. `--project` defaults to the current directory;
|
|
385
|
-
pass the path collected in 0.2 explicitly rather than relying on the default.
|
|
386
|
-
|
|
387
|
-
**Refusals to expect, and what each means:**
|
|
388
|
-
|
|
389
|
-
| Message | Cause |
|
|
390
|
-
|---------|-------|
|
|
391
|
-
| `Job package already exists: .metaproject/jobs/<name>` | The package is there. Run `keryx job status <name>` and resume it (0.0) instead of re-initialising. |
|
|
392
|
-
| `Invalid --name "<name>"` | The name is not `^[a-z0-9-]+$`. |
|
|
393
|
-
| `Invalid --intent "<value>"` | Not one of `implement`, `analyze`, `review`, `custom`. |
|
|
394
|
-
|
|
395
|
-
Confirm the result before proceeding:
|
|
396
|
-
|
|
397
|
-
```bash
|
|
398
|
-
keryx job status <job-name>
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
It prints the phase, the step list with statuses, and `next:` — the step execution
|
|
402
|
-
starts from.
|
|
403
|
-
|
|
404
|
-
### 1.3 Display Plan + Agent Approval
|
|
405
|
-
|
|
406
|
-
Display the plan the package actually holds — do not retype it from memory:
|
|
407
|
-
|
|
408
|
-
```bash
|
|
409
|
-
keryx job status <job-name>
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
There is **one** plan. Every step listed in 1.1 is in it, including the conditional
|
|
413
|
-
ones; a conditional step is one whose trigger may not fire, not one that is absent
|
|
414
|
-
until somebody adds it. For the `implement` intent that is fifteen steps:
|
|
415
|
-
|
|
416
|
-
```
|
|
417
|
-
Execution plan — 15 steps (◦ = conditional):
|
|
418
|
-
|
|
419
|
-
Step 1 analyze issue-analyzer → issue #<N>
|
|
420
|
-
Step 2 context context-collector → project context + test framework
|
|
421
|
-
Step 3 prepare orchestrator → feature branch worktree
|
|
422
|
-
Step 4 tests-creator tests-creator × <tasks> → RED test stubs per task (MANDATORY)
|
|
423
|
-
Step 5 implement task-implementer × <tasks> → <N> tasks make tests GREEN (wave-parallel)
|
|
424
|
-
Step 6 sanity-check orchestrator → verify commits exist
|
|
425
|
-
Step 7 verify code-verifier → lint + type-check + tests + imports (MANDATORY)
|
|
426
|
-
Step 8 review review-orchestrator → managed review round
|
|
427
|
-
Step 9 ◦ security security-audit → auth/API/DB/env files touched
|
|
428
|
-
Step 10◦ fix task-implementer → blocker or major findings
|
|
429
|
-
Step 11◦ verify-post-fix code-verifier → after fix
|
|
430
|
-
Step 12◦ perf-check perf-check → frontend/bundle files changed
|
|
431
|
-
Step 13 report orchestrator → final summary
|
|
432
|
-
Step 14◦ pr orchestrator + gh CLI → create_pr=true
|
|
433
|
-
Step 15◦ deploy deploy → user asked for a staging deploy
|
|
434
|
-
|
|
435
|
-
Proceed? (yes / adjust: "skip fix", "remove pr", etc.)
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
**If user adjusts:** record the decision in the package rather than holding it in
|
|
439
|
-
this session:
|
|
440
|
-
|
|
441
|
-
```bash
|
|
442
|
-
# "skip fix" — close it now, with the reason on the record
|
|
443
|
-
keryx job step <job-name> fix --status skipped --reason "operator asked to skip at plan approval"
|
|
444
|
-
# "remove pr"
|
|
445
|
-
keryx job step <job-name> pr --status skipped --reason "create_pr: false"
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
Then re-display with `keryx job status <job-name>` and ask again. A step the operator
|
|
449
|
-
removed is `skipped` with a reason, never silently dropped — that is the difference
|
|
450
|
-
between a plan somebody changed and a plan that quietly shrank.
|
|
451
|
-
|
|
452
|
-
**If `plan_approval: false`** (automation setting) → skip this display and proceed directly.
|
|
453
|
-
|
|
454
|
-
---
|
|
455
|
-
|
|
456
|
-
## Phase 2: EXECUTION
|
|
457
|
-
|
|
458
|
-
Execute each step in plan order, documenting results after each step.
|
|
459
|
-
|
|
460
|
-
### 2.1 General Execution Loop
|
|
461
|
-
|
|
462
|
-
Every step in the loop is bracketed by two `keryx job` calls. The package, not this
|
|
463
|
-
session, is what says a step ran.
|
|
464
|
-
|
|
465
|
-
```
|
|
466
|
-
FOR step in PLAN:
|
|
467
|
-
IF step.conditional AND condition_not_met:
|
|
468
|
-
keryx job step <job-name> <step-id> --status skipped --reason "<why the trigger did not fire>"
|
|
469
|
-
CONTINUE
|
|
470
|
-
|
|
471
|
-
2.1.1 Open the step:
|
|
472
|
-
keryx job step <job-name> <step-id> --status in-progress
|
|
473
|
-
Re-entering a step that was already opened increments `metrics.steps[].retries`
|
|
474
|
-
— that counter is the attempt budget, and it survives a session restart.
|
|
475
|
-
|
|
476
|
-
2.1.2 Execute step (see step-specific instructions below)
|
|
477
|
-
If the sub-agent returns a malformed result or fails to follow formatting rules, run an explicit retry:
|
|
478
|
-
"The previous output was malformed. Fix these errors: [errors] and try again." (Max 2 retries before counting as critical failure).
|
|
479
|
-
Re-open the step before each retry so the retry is counted.
|
|
480
|
-
|
|
481
|
-
2.1.3 Collect result
|
|
482
|
-
|
|
483
|
-
2.1.4 Write the document to disk, then record it in the package:
|
|
484
|
-
keryx job document <job-name> --type analysis|implementation-report|review|verification-report --file <path>
|
|
485
|
-
The file must already exist — `job document` refuses a `--file` it cannot
|
|
486
|
-
find with "Write the document first, then record it." It copies the file
|
|
487
|
-
into the package and adds it to `documentation.documents_created`.
|
|
488
|
-
Re-recording the same type replaces the file and leaves one entry.
|
|
489
|
-
|
|
490
|
-
2.1.5 Confirm what the package now holds:
|
|
491
|
-
keryx job status <job-name>
|
|
492
|
-
The step list, the retry counts and the recorded documents come from
|
|
493
|
-
`state.json`. This is the job index; there is no README to update.
|
|
494
|
-
|
|
495
|
-
2.1.6 Close the step:
|
|
496
|
-
keryx job step <job-name> <step-id> --status completed
|
|
497
|
-
|
|
498
|
-
IF step failed critically:
|
|
499
|
-
keryx job step <job-name> <step-id> --status failed --reason "<what failed>"
|
|
500
|
-
Ask user: "Step '<name>' failed. Continue with remaining steps or abort?"
|
|
501
|
-
IF abort: skip to Phase 3 (COMPLETION)
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
**`failed` is not terminal.** `keryx job complete` refuses while any step is `failed`
|
|
505
|
-
or still open, and names them. A job that genuinely ends with a step unfinished is
|
|
506
|
-
closed by deciding what happened to that step — `--status skipped --reason "<why>"` —
|
|
507
|
-
which leaves the decision on the record instead of leaving the package half-written.
|
|
508
|
-
|
|
509
|
-
Only four document types exist: `analysis`, `implementation-report`, `review`,
|
|
510
|
-
`verification-report`. Anything else is refused with the valid list.
|
|
511
|
-
|
|
512
|
-
### 2.2 Step: ANALYZE
|
|
513
|
-
|
|
514
|
-
Dispatch `issue-analyzer` as a sub-agent.
|
|
515
|
-
|
|
516
|
-
**Prepare prompt:** Read `skills/gdskills/orchestration/issue-analyzer/orchestrator-prompt.md`
|
|
517
|
-
and fill in:
|
|
518
|
-
- Issue URL or repo+number
|
|
519
|
-
- Codebase paths with roles
|
|
520
|
-
- Automation settings (skip_confirmation: true, search_depth: focused)
|
|
521
|
-
|
|
522
|
-
That file ships with the skill. If the read fails, the path is wrong or the skill is
|
|
523
|
-
not installed — stop and say so. Do not proceed on an improvised prompt: a missed
|
|
524
|
-
template is exactly the failure that hid behind the old "(if it exists)" hedge.
|
|
525
|
-
|
|
526
|
-
**Launch:**
|
|
527
|
-
```
|
|
528
|
-
Task({
|
|
529
|
-
description: "Issue analysis: #<N>",
|
|
530
|
-
subagent_type: "general-purpose",
|
|
531
|
-
prompt: <constructed prompt>
|
|
532
|
-
})
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
**Parse result:** Extract JSON analysis object:
|
|
536
|
-
```
|
|
537
|
-
ANALYSIS_RESULT:
|
|
538
|
-
issue_type: from issue.type
|
|
539
|
-
total_tasks: from issue.total_tasks (= tasks.length)
|
|
540
|
-
tasks: [{task_id, task_name, task_type, complexity, dependencies,
|
|
541
|
-
description, target_files, acceptance_criteria, context,
|
|
542
|
-
existing_tests, existing_stories, module_patterns}]
|
|
543
|
-
dependency_order: from dependency_order array (already topologically sorted)
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
**Validate:** At least 1 task, no circular dependencies, all dependency references valid. Dependency_order array must contain all task_ids exactly once.
|
|
547
|
-
|
|
548
|
-
**Document:** write the analysis, then record it:
|
|
549
|
-
|
|
550
|
-
```bash
|
|
551
|
-
keryx job document <job-name> --type analysis --file <path/to/analysis.md>
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
It lands in the package as `analysis.md` (the source extension is preserved, so a
|
|
555
|
-
`.json` analysis lands as `analysis.json`) and appears in `documents` on the next
|
|
556
|
-
`keryx job status`.
|
|
557
|
-
|
|
558
|
-
**For `analyze` intent:** After documenting, present analysis to user. Ask:
|
|
559
|
-
```
|
|
560
|
-
Analysis complete. Found <N> tasks.
|
|
561
|
-
Want me to implement this? I'll create a feature branch and run the full pipeline.
|
|
562
|
-
○ Yes, implement
|
|
563
|
-
○ No, analysis is enough
|
|
564
|
-
```
|
|
565
|
-
If "Yes" → follow Plan Extension below: create an `implement` package and continue there. Do not rewrite this package's plan.
|
|
566
|
-
If "No" → skip to Phase 3 (COMPLETION).
|
|
567
|
-
|
|
568
|
-
### 2.3 Step: CONTEXT
|
|
569
|
-
|
|
570
|
-
Dispatch `context-collector` to build the unified context document.
|
|
571
|
-
|
|
572
|
-
**Prepare prompt:** Use the template from `skills/gdskills/orchestration/context-collector/SKILL.md`:
|
|
573
|
-
|
|
574
|
-
```
|
|
575
|
-
Task({
|
|
576
|
-
description: "Collect context: <job-name>",
|
|
577
|
-
subagent_type: "general-purpose",
|
|
578
|
-
prompt: |
|
|
579
|
-
You are the context-collector agent. Your task is to research and build
|
|
580
|
-
a context document for the current job.
|
|
581
|
-
|
|
582
|
-
Load the skill from: skills/gdskills/orchestration/context-collector/SKILL.md
|
|
583
|
-
|
|
584
|
-
ACTION: collect
|
|
585
|
-
JOB_NAME: <job-name>
|
|
586
|
-
JOBS_ROOT: <JOBS_ROOT>
|
|
587
|
-
PROJECT_DIR: <project_dir>
|
|
588
|
-
|
|
589
|
-
DATA:
|
|
590
|
-
TASK_DESCRIPTION: <from issue or user request>
|
|
591
|
-
FOCUS_AREAS: <derived from analysis — affected areas, libraries>
|
|
592
|
-
ANALYSIS_RESULT: <output from issue-analyzer, if available>
|
|
593
|
-
KNOWN_LIBRARIES: <from package.json scan during analysis>
|
|
594
|
-
|
|
595
|
-
Execute all phases and return a CONTEXT_RESULT block.
|
|
596
|
-
})
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
**Parse result:**
|
|
600
|
-
```
|
|
601
|
-
CONTEXT_RESULT:
|
|
602
|
-
status: success | error
|
|
603
|
-
version: <document version>
|
|
604
|
-
summary: <what context was collected>
|
|
605
|
-
```
|
|
606
|
-
|
|
607
|
-
**Validate:** status must be `success`. If `error` → log warning, continue (context is helpful but not blocking).
|
|
608
|
-
|
|
609
|
-
**After context is collected:** the orchestrator holds the context path and puts it
|
|
610
|
-
into every subsequent dispatch prompt:
|
|
611
|
-
|
|
612
|
-
```
|
|
613
|
-
CONTEXT_LOCATION: <JOBS_ROOT>/<job-name>/context_v<N>.md
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
**Context versioning:** never overwrite an existing context file — write snapshots as
|
|
617
|
-
`context_v1.md`, `context_v2.md`, and so on. Version 1 comes from the first collect in
|
|
618
|
-
2.3; each update writes the next number.
|
|
619
|
-
|
|
620
|
-
The current version is the highest-numbered file in the package, which is a fact on
|
|
621
|
-
disk that any session can read:
|
|
622
|
-
|
|
623
|
-
```bash
|
|
624
|
-
ls .metaproject/jobs/<job-name>/context_v*.md
|
|
625
|
-
```
|
|
626
|
-
|
|
627
|
-
`state.json` does not carry a context pointer and nothing writes one — do not tell a
|
|
628
|
-
sub-agent to look for one. The orchestrator passes the path (Constructing Subagent
|
|
629
|
-
Context, below); subagents receive, they do not retrieve.
|
|
630
|
-
|
|
631
|
-
**Triggering context updates during execution:**
|
|
632
|
-
|
|
633
|
-
If during later steps (implement, review) a sub-agent reports missing context or a new library is discovered:
|
|
634
|
-
|
|
635
|
-
```
|
|
636
|
-
Task({
|
|
637
|
-
description: "Update context: <job-name>",
|
|
638
|
-
subagent_type: "general-purpose",
|
|
639
|
-
prompt: |
|
|
640
|
-
You are the context-collector agent. Update the existing context.
|
|
641
|
-
|
|
642
|
-
Load the skill from: skills/gdskills/orchestration/context-collector/SKILL.md
|
|
643
|
-
|
|
644
|
-
ACTION: update
|
|
645
|
-
JOB_NAME: <job-name>
|
|
646
|
-
JOBS_ROOT: <JOBS_ROOT>
|
|
647
|
-
PROJECT_DIR: <project_dir>
|
|
648
|
-
CONTEXT_VERSION: <current version + 1> ← write to context_v<N+1>.md
|
|
649
|
-
|
|
650
|
-
DATA:
|
|
651
|
-
TASK_DESCRIPTION: <original task description>
|
|
652
|
-
UPDATE_REASON: <why context needs updating>
|
|
653
|
-
FOCUS_AREAS: <new areas to research>
|
|
654
|
-
|
|
655
|
-
Execute update flow and return a CONTEXT_RESULT block.
|
|
656
|
-
})
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
### 2.4 Step: PREPARE
|
|
660
|
-
|
|
661
|
-
Create git worktree for feature branch.
|
|
662
|
-
|
|
663
|
-
> **CRITICAL**: Feature branches MUST be created via `git worktree add`.
|
|
664
|
-
> **NEVER** use `git checkout -b` or `git switch -c` — this switches the main working directory.
|
|
665
|
-
> The worktree is a **sibling directory** to the project directory.
|
|
666
|
-
|
|
667
|
-
**Determine branch name:**
|
|
668
|
-
```
|
|
669
|
-
Format: feature/<custom-slug>
|
|
670
|
-
Slug: descriptive, lowercase, alphanumeric+hyphens, from issue title/feature
|
|
671
|
-
Examples: feature/pipeline-validation, feature/mirror-step-source-column
|
|
672
|
-
```
|
|
673
|
-
|
|
674
|
-
**Create worktree:**
|
|
675
|
-
```bash
|
|
676
|
-
# Fetch latest base branch
|
|
677
|
-
git -C <project_dir> fetch origin <base_branch>
|
|
678
|
-
|
|
679
|
-
# Create worktree as SIBLING directory
|
|
680
|
-
git -C <project_dir> worktree add ../<branch-slug> -b feature/<branch-slug> origin/<base_branch>
|
|
681
|
-
|
|
682
|
-
# Example:
|
|
683
|
-
# Project dir: /Users/user/projects/<PROJECT>
|
|
684
|
-
# git -C ... worktree add ../pipeline-validation -b feature/pipeline-validation origin/develop-2
|
|
685
|
-
# Result worktree: /Users/user/projects/pipeline-validation
|
|
686
|
-
# Result branch: feature/pipeline-validation
|
|
687
|
-
|
|
688
|
-
# Auto-detect package manager and install dependencies
|
|
689
|
-
if [ -f <worktree_path>/bun.lock ] || [ -f <worktree_path>/bun.lockb ]; then
|
|
690
|
-
PM="bun"; RUNNER="bun run"; bun install --cwd <worktree_path>
|
|
691
|
-
elif [ -f <worktree_path>/pnpm-lock.yaml ]; then
|
|
692
|
-
PM="pnpm"; RUNNER="pnpm run"; pnpm install --prefix <worktree_path>
|
|
693
|
-
elif [ -f <worktree_path>/yarn.lock ]; then
|
|
694
|
-
PM="yarn"; RUNNER="yarn"; yarn --cwd <worktree_path>
|
|
695
|
-
elif [ -f <worktree_path>/package-lock.json ]; then
|
|
696
|
-
PM="npm"; RUNNER="npm run"; npm install --prefix <worktree_path>
|
|
697
|
-
elif [ -f <worktree_path>/requirements.txt ]; then
|
|
698
|
-
PM="python"; RUNNER=""; pip install -r <worktree_path>/requirements.txt
|
|
699
|
-
elif [ -f <worktree_path>/go.mod ]; then
|
|
700
|
-
PM="go"; RUNNER=""; (cd <worktree_path> && go mod download)
|
|
701
|
-
fi
|
|
702
|
-
```
|
|
703
|
-
|
|
704
|
-
> **IMPORTANT**: After creating the worktree, ALL subsequent operations (implementation, review, lint, test, git) MUST run in the **worktree directory**, NOT in the original project directory.
|
|
705
|
-
|
|
706
|
-
**Record state:**
|
|
707
|
-
```
|
|
708
|
-
BRANCH_STATE:
|
|
709
|
-
name: feature/<branch-slug>
|
|
710
|
-
base: <base_branch>
|
|
711
|
-
worktree_path: <absolute path to worktree>
|
|
712
|
-
project_dir: <original project directory — DO NOT modify>
|
|
713
|
-
created_from_commit: <commit hash>
|
|
714
|
-
package_manager: <PM>
|
|
715
|
-
run_command: <RUNNER>
|
|
716
|
-
```
|
|
717
|
-
|
|
718
|
-
> **Carry `package_manager` and `run_command` into every subsequent dispatch prompt** — all subsequent steps use these instead of hardcoded `npm`. They are not persisted; the orchestrator holds them for the run and states them explicitly in each dispatch.
|
|
719
|
-
|
|
720
|
-
**Record:** close the step and put the branch on the record:
|
|
721
|
-
|
|
722
|
-
```bash
|
|
723
|
-
keryx job step <job-name> prepare --status completed --reason "feature/<branch-slug> at <worktree_path>"
|
|
724
|
-
```
|
|
725
|
-
|
|
726
|
-
`--reason` is appended to the package's `journal.md` with a timestamp, which is where
|
|
727
|
-
"what branch did this job use" is answerable after the session ends.
|
|
728
|
-
|
|
729
|
-
### 2.5 Step: TESTS-CREATOR + IMPLEMENT
|
|
730
|
-
|
|
731
|
-
tests-creator runs before task-implementer for every task, with no exceptions.
|
|
732
|
-
|
|
733
|
-
There is no `wave-executor` agent. Each wave is two dispatches the orchestrator makes
|
|
734
|
-
itself — `tests-creator`, then `task-implementer` — and both are real, installed
|
|
735
|
-
skills. Nothing is delegated to an intermediary that does not exist.
|
|
736
|
-
|
|
737
|
-
**CONTEXT BUDGET RULE: instruct every dispatched agent to write its full result to a
|
|
738
|
-
file and return only a compact summary line.** The orchestrator's context grows with
|
|
739
|
-
what agents *return*, not with what they do; a returned result file path costs a line,
|
|
740
|
-
an inlined verification log costs thousands. After 3–4 waves of inlined results the
|
|
741
|
-
session freezes on context reload, which is the failure this rule exists to avoid.
|
|
742
|
-
|
|
743
|
-
---
|
|
744
|
-
|
|
745
|
-
#### Wave ordering
|
|
746
|
-
|
|
747
|
-
Waves come from `dependency_order` in `ANALYSIS_RESULT`, which `issue-analyzer` already
|
|
748
|
-
returned topologically sorted and which 2.2 validated. Wave 1 is every task with no
|
|
749
|
-
unsatisfied dependency; wave N+1 is every task whose dependencies are all in waves 1..N.
|
|
750
|
-
Do not re-derive an ordering the analysis already produced.
|
|
751
|
-
|
|
752
|
-
#### Execution pattern
|
|
753
|
-
|
|
754
|
-
```
|
|
755
|
-
FOR wave_index, wave_tasks in enumerate(WAVES):
|
|
756
|
-
|
|
757
|
-
keryx job step <job-name> tests-creator --status in-progress # wave 1 only
|
|
758
|
-
# Step A — tests-creator (MANDATORY, run first)
|
|
759
|
-
Dispatch one tests-creator per task in this wave, in a SINGLE turn (parallel).
|
|
760
|
-
Wait for ALL of them. Collect TEST_SPECS[task_id] from each response.
|
|
761
|
-
keryx job step <job-name> tests-creator --status completed # last wave only
|
|
762
|
-
|
|
763
|
-
# Parallel safety check, before Step B:
|
|
764
|
-
# if two tasks in this wave share a target_file, dispatch them sequentially.
|
|
765
|
-
|
|
766
|
-
keryx job step <job-name> implement --status in-progress # wave 1 only
|
|
767
|
-
# Step B — task-implementer (after all test stubs are committed)
|
|
768
|
-
Dispatch one task-implementer per task in this wave, in a SINGLE turn (parallel),
|
|
769
|
-
each carrying test_case_specs: TEST_SPECS[task_id].
|
|
770
|
-
Wait for ALL of them.
|
|
771
|
-
|
|
772
|
-
Read each result's STATUS line:
|
|
773
|
-
all DONE → continue to next wave
|
|
774
|
-
any DONE_WITH_CONCERNS → record the concerns, continue
|
|
775
|
-
any BLOCKED → STOP, read the result file, resolve or ask the user
|
|
776
|
-
```
|
|
777
|
-
|
|
778
|
-
#### tests-creator dispatch (Step A)
|
|
779
|
-
|
|
780
|
-
```
|
|
781
|
-
Task({
|
|
782
|
-
description: "Wave <N> tests: <task_id>",
|
|
783
|
-
subagent_type: "general-purpose",
|
|
784
|
-
prompt: |
|
|
785
|
-
Load skill: skills/gdskills/quality/tests-creator/SKILL.md
|
|
786
|
-
|
|
787
|
-
## Task
|
|
788
|
-
<the single task object>
|
|
789
|
-
|
|
790
|
-
## Workspace
|
|
791
|
-
- worktree_path: <absolute path>
|
|
792
|
-
- branch: <branch name>
|
|
793
|
-
- package_manager: <pm>
|
|
794
|
-
- run_command: <runner>
|
|
795
|
-
- context_path: <JOBS_ROOT>/<job-name>/context_v<N>.md
|
|
796
|
-
|
|
797
|
-
## Required response
|
|
798
|
-
Begin with STATUS: <STATUS>. Return the test_case_specs for this task and
|
|
799
|
-
nothing else inline; write anything longer to
|
|
800
|
-
<JOBS_ROOT>/<job-name>/results/<task_id>-tests.json and return the path.
|
|
801
|
-
})
|
|
802
|
-
```
|
|
803
|
-
|
|
804
|
-
#### task-implementer dispatch (Step B)
|
|
805
|
-
|
|
806
|
-
```
|
|
807
|
-
Task({
|
|
808
|
-
description: "Wave <N> implement: <task_id>",
|
|
809
|
-
subagent_type: "general-purpose",
|
|
810
|
-
prompt: |
|
|
811
|
-
Load skill: skills/gdskills/orchestration/task-implementer/SKILL.md
|
|
812
|
-
|
|
813
|
-
## Task
|
|
814
|
-
<the single task object, WITH test_case_specs: TEST_SPECS[task_id]>
|
|
815
|
-
|
|
816
|
-
## Workspace
|
|
817
|
-
- worktree_path: <absolute path>
|
|
818
|
-
- branch: <branch name>
|
|
819
|
-
- package_manager: <pm>
|
|
820
|
-
- run_command: <runner>
|
|
821
|
-
- issue_number: <N>
|
|
822
|
-
- job_name: <job-name>
|
|
823
|
-
- context_path: <JOBS_ROOT>/<job-name>/context_v<N>.md
|
|
824
|
-
|
|
825
|
-
## Required response format (compact — no inline JSON)
|
|
826
|
-
STATUS: DONE
|
|
827
|
-
Task: <task_id>
|
|
828
|
-
Commits: [abc1234 feat(x): ...]
|
|
829
|
-
Tests: <N passed, M failed>
|
|
830
|
-
Result file: <JOBS_ROOT>/<job-name>/results/<task_id>.json
|
|
831
|
-
|
|
832
|
-
Write full detail to the result file. Do NOT inline it.
|
|
833
|
-
})
|
|
834
|
-
```
|
|
835
|
-
|
|
836
|
-
**Each wave runs in ONE worktree.** The worktree created in 2.4 is the whole job's
|
|
837
|
-
workspace — waves are ordered, not isolated from each other, and a later wave sees
|
|
838
|
-
what an earlier one committed. That is what makes the dependency order mean anything.
|
|
839
|
-
|
|
840
|
-
**After all waves, document:** write the implementation report, then record it:
|
|
841
|
-
|
|
842
|
-
```bash
|
|
843
|
-
keryx job document <job-name> --type implementation-report --file <path/to/implementation-report.md>
|
|
844
|
-
keryx job step <job-name> implement --status completed
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
The report summarises every wave: commits, files, test totals, and each task's final
|
|
848
|
-
STATUS.
|
|
849
|
-
|
|
850
|
-
### 2.5.1 Post-Implementation Checkpoint
|
|
851
|
-
|
|
852
|
-
After all waves complete, check if tests were created. If not, offer `test-gen`:
|
|
853
|
-
|
|
854
|
-
```
|
|
855
|
-
# Derive all modified files from the per-task result files
|
|
856
|
-
ALL_FILES = collect from <JOBS_ROOT>/<job-name>/results/*.json
|
|
857
|
-
|
|
858
|
-
IF no test files in ALL_FILES:
|
|
859
|
-
Auto-trigger test-gen for new/modified source files
|
|
860
|
-
(skip test files, config files, types-only files)
|
|
861
|
-
```
|
|
862
|
-
|
|
863
|
-
Then present the implementation summary to user:
|
|
864
|
-
|
|
865
|
-
```
|
|
866
|
-
Implementation complete:
|
|
867
|
-
- <N>/<M> tasks ✅
|
|
868
|
-
- <X> files modified, <Y> files created
|
|
869
|
-
- Tests: <created by implementer | auto-generated by test-gen | none>
|
|
870
|
-
|
|
871
|
-
What's next?
|
|
872
|
-
A) 🔍 Review → fix → PR (standard pipeline)
|
|
873
|
-
B) 👀 Show me the diff first — I'll review manually
|
|
874
|
-
C) 🚀 Skip review, go straight to PR
|
|
875
|
-
D) ⏹ Stop here — I'll continue manually
|
|
876
|
-
```
|
|
877
|
-
|
|
878
|
-
**Mapping:**
|
|
879
|
-
- A → continue to the REVIEW step (2.6)
|
|
880
|
-
- B → run `git diff <merge_base>..HEAD --stat` and `git diff <merge_base>..HEAD`, then re-ask
|
|
881
|
-
- C → skip REVIEW and FIX, go to VERIFY (2.8) → PR. Record both:
|
|
882
|
-
`keryx job step <job-name> review --status skipped --reason "operator chose to skip review"`
|
|
883
|
-
- D → close the open steps with a reason and go to Phase 3:
|
|
884
|
-
`keryx job step <job-name> <step-id> --status skipped --reason "operator stopped here to continue manually"`
|
|
885
|
-
|
|
886
|
-
**Wait for the answer.** There is no default and no timer: this skill runs as a model
|
|
887
|
-
in a turn-based session, and nothing here can observe wall-clock time passing while a
|
|
888
|
-
user does not reply. A "default after N seconds" could never fire, so it is not
|
|
889
|
-
offered.
|
|
890
|
-
|
|
891
|
-
### 2.5.2 Step: IMPLEMENT SANITY CHECK
|
|
892
|
-
|
|
893
|
-
Lightweight verification after all waves complete, **before** launching review.
|
|
894
|
-
This catches the case where a task-implementer reports `STATUS: DONE` but made no
|
|
895
|
-
actual git changes.
|
|
896
|
-
|
|
897
|
-
```bash
|
|
898
|
-
# Run in worktree directory
|
|
899
|
-
git diff --stat <merge_base>..HEAD
|
|
900
|
-
git log <merge_base>..HEAD --oneline
|
|
901
|
-
```
|
|
902
|
-
|
|
903
|
-
**Gate conditions:**
|
|
904
|
-
|
|
905
|
-
| Check | Pass | Fail action |
|
|
906
|
-
|-------|------|-------------|
|
|
907
|
-
| At least 1 commit exists | ≥1 commit | `retryable` — re-dispatch the task-implementers for that wave with: "No commits were made. Implement the changes and commit them." |
|
|
908
|
-
| At least 1 file modified | ≥1 file changed | Same as above |
|
|
909
|
-
| Claimed files actually modified | All files named in the result files appear in the diff | Log discrepancy as a concern, continue |
|
|
910
|
-
|
|
911
|
-
Re-open the step before re-dispatching, so the attempt is counted:
|
|
912
|
-
|
|
913
|
-
```bash
|
|
914
|
-
keryx job step <job-name> implement --status in-progress
|
|
915
|
-
```
|
|
916
|
-
|
|
917
|
-
`metrics.steps[].retries` for `implement` goes up by one. Read it back with
|
|
918
|
-
`keryx job status <job-name> --json` — the count is on disk, so it is still right
|
|
919
|
-
after a session restart.
|
|
920
|
-
|
|
921
|
-
**If the retry also produces no commits** → classify as `terminal` and stop:
|
|
922
|
-
|
|
923
|
-
```bash
|
|
924
|
-
keryx job step <job-name> sanity-check --status failed --reason "task-implementer reported DONE twice with no git changes"
|
|
925
|
-
```
|
|
926
|
-
|
|
927
|
-
```
|
|
928
|
-
"task-implementer returned STATUS: DONE twice but made no git changes.
|
|
929
|
-
Please implement manually and re-run from the review step."
|
|
930
|
-
```
|
|
931
|
-
|
|
932
|
-
**Record the outcome** in the journal, where it survives the session:
|
|
933
|
-
|
|
934
|
-
```bash
|
|
935
|
-
keryx job step <job-name> sanity-check --status completed \
|
|
936
|
-
--reason "<N> commits, <M> files changed, +<A>/-<R> lines"
|
|
937
|
-
```
|
|
938
|
-
|
|
939
|
-
There is no `sanity_check` field in `state.json` and nothing writes one — the
|
|
940
|
-
journal line is the record.
|
|
941
|
-
|
|
942
|
-
---
|
|
943
|
-
|
|
944
|
-
### 2.6 Step: REVIEW
|
|
945
|
-
|
|
946
|
-
`review-orchestrator` is the review path. It is not one strategy among several: it is
|
|
947
|
-
the only entry point that produces a **managed review record**, and every round this
|
|
948
|
-
skill runs is a round that must be citable afterwards. The legacy alternatives —
|
|
949
|
-
launching `code-ai-review` / `code-learned-review` / `code-style-review` by hand, or the
|
|
950
|
-
never-bundled `code-review` 4-agent skill — are gone. They emitted prose into a chat
|
|
951
|
-
transcript and nothing else, which is precisely the failure the managed pipeline
|
|
952
|
-
replaced.
|
|
953
|
-
|
|
954
|
-
A pull request driven by this orchestrator has to pass the completion gate shipped in
|
|
955
|
-
0.2.71. Its five conditions are what 2.6 and 2.7 are built to satisfy:
|
|
956
|
-
|
|
957
|
-
| Gate condition | Satisfied by |
|
|
958
|
-
|---|---|
|
|
959
|
-
| every fix round has a managed record | `keryx review start` before, `keryx review ingest` after (2.6.1, 2.7) |
|
|
960
|
-
| every finding has a terminal disposition | `keryx review complete --finding … --disposition … --evidence …` (2.7) |
|
|
961
|
-
| scope B is recorded when a scope-B reviewer ran | `keryx review blast-radius --json` → `review ingest --blast-radius` (2.6.1) |
|
|
962
|
-
| no inbound PR comment is unanswered | `keryx review comments collect` every round, `… reply --final` once (2.6.2) |
|
|
963
|
-
| verification stats exist | `review-verifier` dispatched, passed as `--verifications` (2.6.1) |
|
|
964
|
-
|
|
965
|
-
#### 2.6.0 Review Scope Selection
|
|
966
|
-
|
|
967
|
-
Ask which reviewer set to use. The flags are `review-orchestrator`'s, and they select
|
|
968
|
-
reviewers — there is no "quick vs thorough" mode:
|
|
969
|
-
|
|
970
|
-
```
|
|
971
|
-
Which reviewers should run on this branch?
|
|
972
|
-
|
|
973
|
-
A) Auto-detect from the diff (recommended) — review-orchestrator picks from changed files
|
|
974
|
-
B) Named domains — e.g. --backend --security, --frontend --testing-practices
|
|
975
|
-
C) Everything — --all
|
|
976
|
-
D) Skip review entirely
|
|
977
|
-
|
|
978
|
-
> pick a letter
|
|
979
|
-
```
|
|
980
|
-
|
|
981
|
-
Then ask which optional convention reviewers to include when local convention docs or matching
|
|
982
|
-
paths are present:
|
|
983
|
-
|
|
984
|
-
```
|
|
985
|
-
Which project-convention reviewers should I include?
|
|
986
|
-
|
|
987
|
-
A) Include all detected convention reviewers (recommended)
|
|
988
|
-
B) Choose individually
|
|
989
|
-
C) Skip convention reviewers
|
|
990
|
-
|
|
991
|
-
Detected reviewers:
|
|
992
|
-
- review-frontend-conventions: frontend files / stories / local frontend guide
|
|
993
|
-
- review-testing-practices: tests, stories, MSW, or e2e files
|
|
994
|
-
- review-core-boundaries: shared core/infrastructure files
|
|
995
|
-
- review-flow-graph: shared graph/flow abstraction files
|
|
996
|
-
```
|
|
997
|
-
|
|
998
|
-
Which reviewers are even applicable is **detected, not eyeballed**:
|
|
999
|
-
|
|
1000
|
-
```bash
|
|
1001
|
-
keryx review stack --json
|
|
1002
|
-
```
|
|
1003
|
-
|
|
1004
|
-
It reads `package.json` once and every installed review-category skill's declared
|
|
1005
|
-
`metadata.stack_requires`, and reports per reviewer whether the requirement is met.
|
|
1006
|
-
Show only what it includes, and carry its exclusions with their reasons into the
|
|
1007
|
-
report — a reviewer silently absent reads as a reviewer that found nothing.
|
|
1008
|
-
|
|
1009
|
-
**Auto-select** (skip these questions) when:
|
|
1010
|
-
- `review_flags` is explicitly set in automation settings → use that
|
|
1011
|
-
- `convention_reviewers` is explicitly set in automation settings → use that for optional convention reviewers
|
|
1012
|
-
- User already chose at Post-Implementation Checkpoint (2.5.1 option A) → use auto-detect (A)
|
|
1013
|
-
|
|
1014
|
-
The selection is held for this run and named in the dispatch. There is no
|
|
1015
|
-
`convention_reviewers` field in `state.json` and nothing writes one; the choice is
|
|
1016
|
-
carried in the dispatch prompt and reported in 2.9.
|
|
1017
|
-
|
|
1018
|
-
#### 2.6.1 Execute the Round
|
|
1019
|
-
|
|
1020
|
-
**Step 1 — check the budget before dispatching, while stopping is still possible.**
|
|
1021
|
-
|
|
1022
|
-
```bash
|
|
1023
|
-
keryx review budget --spent <usd-so-far> --outstanding <subagents this orchestrator has in flight>
|
|
1024
|
-
```
|
|
1025
|
-
|
|
1026
|
-
`--outstanding` is not optional here. `src/review/caps.ts` names `job-orchestrator`
|
|
1027
|
-
as the outermost of the three nesting levels — `job-orchestrator` →
|
|
1028
|
-
`flow-orchestrator` → `review-orchestrator` — that its cap of 4 in-flight reviewers
|
|
1029
|
-
was chosen to survive. keryx is a CLI invoked once per command; it cannot observe
|
|
1030
|
-
subagents running inside another orchestrator's process. **The cap binds the nested
|
|
1031
|
-
total only when the parent declares its own in-flight count.** Omit `--outstanding`
|
|
1032
|
-
and the cap bounds the reviewer fan-out alone, which the record then states plainly.
|
|
1033
|
-
|
|
1034
|
-
A non-zero exit means the spend ceiling (3 USD by default) is reached: stop and ask
|
|
1035
|
-
the user rather than dispatching another fan-out.
|
|
1036
|
-
|
|
1037
|
-
**Step 2 — open a managed round.**
|
|
1038
|
-
|
|
1039
|
-
```bash
|
|
1040
|
-
keryx review start --target branch --ref <feature-branch> --head "$(git -C <worktree> rev-parse HEAD)"
|
|
1041
|
-
# reviewing an existing PR instead:
|
|
1042
|
-
keryx review start --target pull-request --ref <pr-number> --head <pr-head-sha>
|
|
1043
|
-
```
|
|
1044
|
-
|
|
1045
|
-
**A fix round is managed, not optional.** A round whose findings were never ingested
|
|
1046
|
-
cannot be cited as a completed round, because nothing durable records what it found.
|
|
1047
|
-
|
|
1048
|
-
**Step 3 — collect inbound PR comments, every round.**
|
|
1049
|
-
|
|
1050
|
-
```bash
|
|
1051
|
-
keryx review comments collect --repo <owner/repo> --pr <n> --sha <head-sha> \
|
|
1052
|
-
--self <our-login> --round <n> --out <JOBS_ROOT>/<job-name>/comments-r<n>.json
|
|
1053
|
-
```
|
|
1054
|
-
|
|
1055
|
-
`--sha` is required and is the commit collected against; the completion gate compares
|
|
1056
|
-
it to the PR head, so a collection that ran before the comments arrived reads as
|
|
1057
|
-
stale rather than clean. Bot reviewers count as reviewers. Do **not** reply yet —
|
|
1058
|
-
replies happen once, in 2.7, after the last round.
|
|
1059
|
-
|
|
1060
|
-
**Step 4 — build both scopes.**
|
|
1061
|
-
|
|
1062
|
-
```bash
|
|
1063
|
-
BASE_SHA="$(git -C <worktree> merge-base HEAD <base_branch>)"
|
|
1064
|
-
keryx review scope --ref "$BASE_SHA" --json > <JOBS_ROOT>/<job-name>/scope.json
|
|
1065
|
-
keryx review blast-radius --ref "$BASE_SHA" --json > <JOBS_ROOT>/<job-name>/blast-radius.json
|
|
1066
|
-
```
|
|
1067
|
-
|
|
1068
|
-
Scope A (`review scope`) is the bounded diff, with every drop recorded and its reason.
|
|
1069
|
-
Scope B (`review blast-radius`) is what the change can break — the regression set.
|
|
1070
|
-
**Keep both files.** `review ingest --blast-radius <file>` is refused on any round that
|
|
1071
|
-
dispatched `review-regression`, which is every recommended and full round, and an
|
|
1072
|
-
ingest carrying a scope-B finding without the record is refused in code.
|
|
1073
|
-
|
|
1074
|
-
**Step 5 — compute the model per dispatch, never by hand.**
|
|
1075
|
-
|
|
1076
|
-
```bash
|
|
1077
|
-
keryx review tier --scope <scope> --diff-lines <n> --findings <n> [--security] [--verifier reasoning] --json
|
|
1078
|
-
```
|
|
1079
|
-
|
|
1080
|
-
Paste the `model` block it prints into that dispatch. `model_strategy: "current"` is
|
|
1081
|
-
gone: it meant "do not switch models", which is exactly the behaviour this command
|
|
1082
|
-
replaced. The command names no model — it ranks what the provider reports at runtime
|
|
1083
|
-
and, when it cannot rank anything, prints `inherit: true`, which means the dispatch
|
|
1084
|
-
runs on the session model. That is a correct answer, not a failure.
|
|
1085
|
-
|
|
1086
|
-
**Step 6 — dispatch `review-orchestrator`.**
|
|
1087
|
-
|
|
1088
|
-
```
|
|
1089
|
-
Task({
|
|
1090
|
-
description: "Review round <n>: <job-name>",
|
|
1091
|
-
subagent_type: "general-purpose",
|
|
1092
|
-
prompt: |
|
|
1093
|
-
Load skill: skills/gdskills/review/review-orchestrator/SKILL.md
|
|
1094
|
-
|
|
1095
|
-
flags: <selected flags, e.g. --backend --security --testing-practices>
|
|
1096
|
-
commit_range: <BASE_SHA>..HEAD
|
|
1097
|
-
issue_url: <issue URL, when the job has one — enables the Stage 1 spec gate>
|
|
1098
|
-
context_doc: <JOBS_ROOT>/<job-name>/context_v<N>.md
|
|
1099
|
-
verification_mode: annotate
|
|
1100
|
-
managed_review: { mode: "review-flow", target: "branch", target_ref: "<feature-branch>" }
|
|
1101
|
-
is_fix_round: <true on any round after the first>
|
|
1102
|
-
pr_comments: { enabled: <true when a PR exists> }
|
|
1103
|
-
|
|
1104
|
-
Emit the unified report AND the fenced ```json keryx:findings``` block.
|
|
1105
|
-
Dispatch review-verifier (Wave C) over the consolidated findings and return
|
|
1106
|
-
its verification claims as a file path.
|
|
1107
|
-
})
|
|
1108
|
-
```
|
|
1109
|
-
|
|
1110
|
-
**Step 7 — verification is part of the round, not an extra.** `review-orchestrator`
|
|
1111
|
-
dispatches `review-verifier` in Wave C over the consolidated findings. The verifier
|
|
1112
|
-
**runs something** and can only delete — it never raises a severity, adds a finding,
|
|
1113
|
-
or rewrites one, and it never verifies a finding raised by the same reviewer. Its
|
|
1114
|
-
claims are merged by the CLI, not by hand.
|
|
1115
|
-
|
|
1116
|
-
**Step 8 — ingest the round.** This is what makes it citable.
|
|
1117
|
-
|
|
1118
|
-
```bash
|
|
1119
|
-
keryx review ingest --report <path/to/review-report.md> --ref <feature-branch> \
|
|
1120
|
-
--head "$(git -C <worktree> rev-parse HEAD)" \
|
|
1121
|
-
--scope <JOBS_ROOT>/<job-name>/scope.json \
|
|
1122
|
-
--blast-radius <JOBS_ROOT>/<job-name>/blast-radius.json \
|
|
1123
|
-
--verifications <path/to/verifications.json> --verification-mode annotate \
|
|
1124
|
-
--refuted <path/to/refuted.json> \
|
|
1125
|
-
--spent <usd-so-far> --outstanding <subagents in flight>
|
|
1126
|
-
```
|
|
1127
|
-
|
|
1128
|
-
An unrecognised option is **refused, not ignored** — a silently dropped flag writes
|
|
1129
|
-
nothing and still reports success. `--refuted` carries findings this round raised and
|
|
1130
|
-
then dismissed; without it the package keeps only the survivors of an unlogged triage.
|
|
1131
|
-
|
|
1132
|
-
**Findings are the canonical shape.** One vocabulary, everywhere in this skill:
|
|
1133
|
-
|
|
1134
|
-
- severities are `blocker`, `major`, `minor`, `info` — `review-finding.schema.json`;
|
|
1135
|
-
- the report ends with **exactly one** fenced block whose info string is
|
|
1136
|
-
` ```json keryx:findings ` — ingest reads that block, not the prose, and a round
|
|
1137
|
-
that emits only prose cannot seed the next one;
|
|
1138
|
-
- `reviewer` is the reviewer that actually produced the finding, never the
|
|
1139
|
-
orchestrator;
|
|
1140
|
-
- identity for dedupe and for the stuck check is `dedupe_key` when the finding has
|
|
1141
|
-
one, otherwise reviewer + file + symbol + problem — never the display id, which is
|
|
1142
|
-
per-report.
|
|
1143
|
-
|
|
1144
|
-
**Classify:**
|
|
1145
|
-
```
|
|
1146
|
-
NEEDS_FIX = count(blocker) > 0 OR count(major) > 0
|
|
1147
|
-
```
|
|
1148
|
-
|
|
1149
|
-
**Document:** record the report in the job package too, so the job and the review
|
|
1150
|
-
record point at each other:
|
|
1151
|
-
|
|
1152
|
-
```bash
|
|
1153
|
-
keryx job document <job-name> --type review --file <path/to/review-report.md>
|
|
1154
|
-
```
|
|
1155
|
-
|
|
1156
|
-
#### 2.6.2 PR Review Report Publication
|
|
1157
|
-
|
|
1158
|
-
If this job is reviewing an existing GitHub PR, or a PR number was resolved before the
|
|
1159
|
-
review step, ask whether to publish the consolidated review report — after the round is
|
|
1160
|
-
ingested and before any fix decisions.
|
|
1161
|
-
|
|
1162
|
-
Ask unless automation settings explicitly set `publish_pr_review_report`:
|
|
1163
|
-
|
|
1164
|
-
```text
|
|
1165
|
-
Publish the review report to the PR?
|
|
1166
|
-
|
|
1167
|
-
A) Concise PR comment only
|
|
1168
|
-
B) Concise PR comment + detailed AI markdown artifact (recommended for follow-up fixes)
|
|
1169
|
-
C) Do not publish
|
|
1170
|
-
|
|
1171
|
-
> pick a letter (default: C)
|
|
1172
|
-
```
|
|
1173
|
-
|
|
1174
|
-
**Rules:**
|
|
1175
|
-
- The PR comment and AI artifact must be written in English only, regardless of the chat language or reviewer output language.
|
|
1176
|
-
- Default is C. Never publish to a PR without explicit user confirmation or `publish_pr_review_report: comment`, `publish_pr_review_report: comment-and-ai-artifact`.
|
|
1177
|
-
- If the user chooses A, delegate concise comment formatting to `review-orchestrator`'s PR Review Report Publication contract.
|
|
1178
|
-
- If the user chooses B, also generate `.metaproject/jobs/<job-name>/review-ai-report.md` using `review-orchestrator`'s Detailed AI Markdown Artifact contract, and include in the comment's `Meta` section both an `AI artifact` path and an `AI artifact description` row explaining that the file carries detailed findings, fix guidance, patch guidance, regression coverage, validation plan, and follow-up agent context.
|
|
1179
|
-
- **If no PR exists yet**, do not ask now and do not stash a pending decision — nothing persists one. Ask this question again after the PR step (2.10) creates the PR, when the answer can actually be acted on.
|
|
1180
|
-
- The decision is acted on immediately or not at all. There is no `publication_plan` field in `state.json`; what was published is stated in the 2.9 report.
|
|
1181
|
-
|
|
1182
|
-
**Automation values:**
|
|
1183
|
-
- `publish_pr_review_report: ask` -> ask the question above.
|
|
1184
|
-
- `publish_pr_review_report: comment` -> publish the concise PR comment only.
|
|
1185
|
-
- `publish_pr_review_report: comment-and-ai-artifact` -> publish the concise PR comment and create the detailed AI markdown artifact.
|
|
1186
|
-
- `publish_pr_review_report: none` -> do not publish.
|
|
1187
|
-
|
|
1188
|
-
#### 2.6.3 Post-Review Checkpoint
|
|
1189
|
-
|
|
1190
|
-
After the round is ingested, present findings and ask the user:
|
|
1191
|
-
|
|
1192
|
-
```
|
|
1193
|
-
Review round <n> complete:
|
|
1194
|
-
🔴 <N> blocker 🟠 <M> major 🟡 <K> minor 🔵 <L> info
|
|
1195
|
-
verified: <V> claims recorded, <R> findings refuted
|
|
1196
|
-
inbound PR comments this round: <C>
|
|
1197
|
-
|
|
1198
|
-
A) 🔧 Auto-fix and continue (fix blocker + major)
|
|
1199
|
-
B) 📋 Show all findings — I'll decide what to fix
|
|
1200
|
-
C) ⏭ Skip fixes, proceed to PR as-is
|
|
1201
|
-
D) ⏹ Stop — I'll fix manually
|
|
1202
|
-
```
|
|
1203
|
-
|
|
1204
|
-
The counts come from the ingested package, not from re-reading the prose:
|
|
1205
|
-
|
|
1206
|
-
```bash
|
|
1207
|
-
keryx review status <review-id-or-path>
|
|
1208
|
-
```
|
|
1209
|
-
|
|
1210
|
-
**Mapping:**
|
|
1211
|
-
- A → proceed to the FIX step (2.7)
|
|
1212
|
-
- B → display all findings grouped by file, then re-ask A/C/D
|
|
1213
|
-
- C → skip FIX, go to VERIFY (2.8) — allowed only when 0 blockers; refuse while a blocker stands
|
|
1214
|
-
- D → close the open steps with a reason (2.1) and go to Phase 3
|
|
1215
|
-
|
|
1216
|
-
Whichever branch is taken, **every finding still needs a disposition** before the
|
|
1217
|
-
review can be completed — see 2.7. "Nobody chose to fix it" is `dismissed-wont-fix`
|
|
1218
|
-
with evidence, not silence.
|
|
1219
|
-
|
|
1220
|
-
**Auto-proceed** (skip this question) when:
|
|
1221
|
-
- 0 findings → go straight to VERIFY (2.8)
|
|
1222
|
-
- only `minor`/`info` findings → skip FIX, go to VERIFY (2.8)
|
|
1223
|
-
- `auto_create_pr: true` → auto-select A
|
|
1224
|
-
|
|
1225
|
-
### 2.7 Step: FIX (conditional)
|
|
1226
|
-
|
|
1227
|
-
Only runs if NEEDS_FIX is true. Default max: **3 iterations** (`max_review_iterations`).
|
|
1228
|
-
|
|
1229
|
-
Three is the shared round bound: `task-implementer`, `flow-orchestrator` and
|
|
1230
|
-
this skill all use it. *"The first three to four repair iterations account for
|
|
1231
|
-
most achievable gains"* ([arXiv:2607.05197](https://arxiv.org/abs/2607.05197));
|
|
1232
|
-
correctness falls **0.820 -> 0.673** across two forced revisions while
|
|
1233
|
-
cumulative ever-correct is **0.847**
|
|
1234
|
-
([arXiv:2607.24604](https://arxiv.org/abs/2607.24604)). Aider hardcodes
|
|
1235
|
-
`max_reflections = 3`; OpenHands' critic uses 3.
|
|
1236
|
-
|
|
1237
|
-
The bound is a ceiling, not a target. Repetition ends the loop earlier and
|
|
1238
|
-
**regardless of remaining iterations** — a counter cannot tell "converging
|
|
1239
|
-
slowly" from "stuck", and an agent emitting the identical failing output three
|
|
1240
|
-
times spends the whole budget before anything notices.
|
|
1241
|
-
|
|
1242
|
-
**A finding leaves this loop by being dispositioned, never by being absent.** The
|
|
1243
|
-
previous version of this section recomputed "unresolved" as whatever the next round
|
|
1244
|
-
still reported — so a finding the next reviewer simply did not look at was recorded as
|
|
1245
|
-
fixed. That is absence-as-evidence, and the completion gate refuses it.
|
|
1246
|
-
|
|
1247
|
-
```
|
|
1248
|
-
UNRESOLVED_FINDINGS = all blocker + major findings from step 2.6
|
|
1249
|
-
PREVIOUS_REVIEW_OUTPUT = <the ingested report from step 2.6>
|
|
1250
|
-
|
|
1251
|
-
FOR iteration in [1, 2, 3]:
|
|
1252
|
-
IF NOT NEEDS_FIX: BREAK
|
|
1253
|
-
|
|
1254
|
-
keryx job step <job-name> fix --status in-progress # increments metrics.steps[].retries
|
|
1255
|
-
|
|
1256
|
-
1. Group UNRESOLVED_FINDINGS by file
|
|
1257
|
-
2. Construct fix prompt — MUST include unresolved findings from previous attempt:
|
|
1258
|
-
|
|
1259
|
-
task_type: "fix"
|
|
1260
|
-
findings: <UNRESOLVED_FINDINGS, in the canonical finding shape>
|
|
1261
|
-
iteration: <N>
|
|
1262
|
-
previously_unresolved: <findings that were in UNRESOLVED_FINDINGS last iteration but still present>
|
|
1263
|
-
→ Prefix: "These specific findings were NOT fixed in iteration <N-1>: [list]"
|
|
1264
|
-
|
|
1265
|
-
3. Launch task-implementer with the fix prompt (subagent_type: "general-purpose"),
|
|
1266
|
-
on the model `keryx review tier --fix-attempt <N> --findings <n> --json` computes
|
|
1267
|
-
4. Run the sanity check (step 2.5.2 logic) — verify commits were made
|
|
1268
|
-
5. Run the next managed round — the FULL 2.6.1 sequence, not a bare re-dispatch:
|
|
1269
|
-
keryx review budget --spent <usd> --outstanding <n>
|
|
1270
|
-
keryx review start --target branch --ref <feature-branch> --head <new-head>
|
|
1271
|
-
keryx review comments collect --repo <r> --pr <n> --sha <new-head> --round <N+1> --out <file>
|
|
1272
|
-
keryx review scope --ref "$BASE_SHA" --json > scope.json
|
|
1273
|
-
keryx review blast-radius --ref "$BASE_SHA" --previous blast-radius.json --json > blast-radius.json
|
|
1274
|
-
<dispatch review-orchestrator with is_fix_round: true>
|
|
1275
|
-
keryx review ingest --report <new-report> --ref <feature-branch> --head <new-head> \
|
|
1276
|
-
--scope scope.json --blast-radius blast-radius.json \
|
|
1277
|
-
--verifications <file> --refuted <file> --outstanding <n>
|
|
1278
|
-
6. Recompute NEEDS_FIX from the ingested findings
|
|
1279
|
-
7. Record what became of each finding raised in the PREVIOUS round — every one of
|
|
1280
|
-
them, before the next iteration starts:
|
|
1281
|
-
|
|
1282
|
-
keryx review complete <previous-review-id-or-path> \
|
|
1283
|
-
--finding F-001 --disposition acted-on --evidence "fixed in <commit-sha>" \
|
|
1284
|
-
--finding F-002 --disposition dismissed-incorrect --evidence "<what was run, what it showed>" \
|
|
1285
|
-
--finding F-003 --disposition dismissed-out-of-scope --evidence "<decision, where written>"
|
|
1286
|
-
|
|
1287
|
-
States: unknown, acted-on, dismissed-incorrect, dismissed-wont-fix,
|
|
1288
|
-
dismissed-out-of-scope, dismissed-deprioritised. Everything except `unknown`
|
|
1289
|
-
must cite where the outcome is written down. A recorded state and its citation
|
|
1290
|
-
cannot be overwritten by a later close — record a correction as a new round.
|
|
1291
|
-
Closing with no dispositions leaves every finding reading `unknown`, which means
|
|
1292
|
-
"nobody wrote down what happened".
|
|
1293
|
-
8. UNRESOLVED_FINDINGS = the blocker + major findings of the NEW round that are
|
|
1294
|
-
still without a terminal disposition
|
|
1295
|
-
|
|
1296
|
-
9. STUCK CHECK — runs before the next iteration and ignores the budget:
|
|
1297
|
-
IF any finding identity is in UNRESOLVED_FINDINGS for the SECOND iteration
|
|
1298
|
-
OR the new review output is identical to PREVIOUS_REVIEW_OUTPUT
|
|
1299
|
-
THEN log "stuck: <what repeated>" and BREAK, even with iterations left.
|
|
1300
|
-
Identity is the finding's dedupe_key when it has one, otherwise
|
|
1301
|
-
reviewer + file + symbol + problem — never the display id, which is
|
|
1302
|
-
per-report and would fire on every second iteration whatever happened.
|
|
1303
|
-
|
|
1304
|
-
Detection is also available from the durable record rather than this
|
|
1305
|
-
session's memory, which is the version that survives a restart:
|
|
1306
|
-
keryx review loop --flow <flow-id>
|
|
1307
|
-
It escalates with a non-zero exit on a recurring finding or two identical
|
|
1308
|
-
consecutive rounds, regardless of the remaining budget.
|
|
1309
|
-
10. PREVIOUS_REVIEW_OUTPUT = the new ingested report
|
|
1310
|
-
|
|
1311
|
-
keryx job step <job-name> fix --status completed
|
|
1312
|
-
|
|
1313
|
-
AFTER THE LAST ROUND ONLY — answer every inbound PR comment, once:
|
|
1314
|
-
keryx review comments reply --repo <owner/repo> --pr <n> --outcomes <file> \
|
|
1315
|
-
--sha <head-sha> --final [--flow-link <url>]
|
|
1316
|
-
|
|
1317
|
-
IF still NEEDS_FIX after max iterations, or the stuck check broke the loop:
|
|
1318
|
-
Log "Unresolved after <N> iterations" with finding list, and say WHICH of the
|
|
1319
|
-
two ended it — a budget exhausted and a loop detected call for different next
|
|
1320
|
-
steps. Give every surviving finding a disposition (dismissed-wont-fix or
|
|
1321
|
-
dismissed-deprioritised, with evidence) rather than leaving it `unknown`
|
|
1322
|
-
→ continue to VERIFY (2.8)
|
|
1323
|
-
```
|
|
1324
|
-
|
|
1325
|
-
`comments reply` **refuses without `--final`**: replying per round turns one review
|
|
1326
|
-
thread into six, and a reply written mid-loop states an intention rather than an
|
|
1327
|
-
outcome. Each reply is cut in code to 2 sentences and 600 characters, threaded where
|
|
1328
|
-
GitHub gives a thread, capped at 30 with one summary comment for the remainder.
|
|
1329
|
-
`--dry-run` rehearses the whole pass without posting.
|
|
1330
|
-
|
|
1331
|
-
**Fix prompt escalation pattern:**
|
|
1332
|
-
- Iteration 1: "Fix these findings: [list]"
|
|
1333
|
-
- Iteration 2: "These findings were NOT fixed in iteration 1: [subset]. Fix them now."
|
|
1334
|
-
- Iteration 3: "FINAL attempt. These findings remain after 2 fix passes: [subset]. This is the last fix iteration."
|
|
1335
|
-
|
|
1336
|
-
### 2.8 Step: VERIFY (code-verifier)
|
|
1337
|
-
|
|
1338
|
-
Dispatch `code-verifier` as a sub-agent. This is the quality gate; there is no separate
|
|
1339
|
-
`CHECKS` step, and nothing in this document jumps to one.
|
|
1340
|
-
|
|
1341
|
-
```
|
|
1342
|
-
Task({
|
|
1343
|
-
description: "Quality gate: <job-name>",
|
|
1344
|
-
subagent_type: "general-purpose",
|
|
1345
|
-
prompt: |
|
|
1346
|
-
You are code-verifier. Load skill: skills/gdskills/orchestration/code-verifier/SKILL.md
|
|
1347
|
-
|
|
1348
|
-
codebase_path: <worktree_path>
|
|
1349
|
-
base_branch: <base_branch>
|
|
1350
|
-
scope: changed
|
|
1351
|
-
|
|
1352
|
-
Run all 4 phases and return VERIFICATION_RESULT.
|
|
1353
|
-
})
|
|
1354
|
-
```
|
|
1355
|
-
|
|
1356
|
-
**Handle result:**
|
|
1357
|
-
```
|
|
1358
|
-
IF VERIFICATION_RESULT.gate == "PASS" or "PASS_WITH_WARNINGS":
|
|
1359
|
-
→ Proceed to review
|
|
1360
|
-
→ Log findings as informational in the job report
|
|
1361
|
-
|
|
1362
|
-
IF VERIFICATION_RESULT.gate == "FAIL":
|
|
1363
|
-
→ Extract blocker/major findings
|
|
1364
|
-
→ Check whether the fix step has already run:
|
|
1365
|
-
keryx job status <job-name> --json # retries["fix"] is the recorded count
|
|
1366
|
-
- If it has not → run the fix step (2.7) with these findings
|
|
1367
|
-
- If `retries["fix"]` has reached 3 → escalate to the user and go to report.
|
|
1368
|
-
Three is the bound, and it is the same three everywhere in this skill.
|
|
1369
|
-
```
|
|
1370
|
-
|
|
1371
|
-
**Document result:** write the verification report, then record it:
|
|
1372
|
-
|
|
1373
|
-
```bash
|
|
1374
|
-
keryx job document <job-name> --type verification-report --file <path/to/verification-report.md>
|
|
1375
|
-
keryx job step <job-name> verify --status completed --reason "gate: <PASS|PASS_WITH_WARNINGS|FAIL>"
|
|
1376
|
-
```
|
|
1377
|
-
|
|
1378
|
-
### 2.8.1 Step: VERIFY-POST-FIX (code-verifier, conditional)
|
|
1379
|
-
|
|
1380
|
-
After fix iterations, dispatch `code-verifier` again with identical parameters.
|
|
1381
|
-
|
|
1382
|
-
```
|
|
1383
|
-
IF fix ran:
|
|
1384
|
-
keryx job step <job-name> verify-post-fix --status in-progress
|
|
1385
|
-
Dispatch code-verifier (same params as step 2.8)
|
|
1386
|
-
IF gate still FAIL:
|
|
1387
|
-
Log "Verification failed after fix" → go to report with a warning
|
|
1388
|
-
IF gate PASS:
|
|
1389
|
-
Proceed to report
|
|
1390
|
-
keryx job document <job-name> --type verification-report --file <path/to/verification-post-fix.md>
|
|
1391
|
-
keryx job step <job-name> verify-post-fix --status completed --reason "gate: <status>"
|
|
1392
|
-
|
|
1393
|
-
IF fix did not run:
|
|
1394
|
-
keryx job step <job-name> verify-post-fix --status skipped --reason "no fix round was needed"
|
|
1395
|
-
```
|
|
1396
|
-
|
|
1397
|
-
### 2.8.2 Step: PERF-CHECK (optional)
|
|
1398
|
-
|
|
1399
|
-
Auto-trigger `perf-check` when frontend/bundle files were modified:
|
|
1400
|
-
|
|
1401
|
-
```
|
|
1402
|
-
IF any modified file matches: *.tsx, *.jsx, *.css, *.scss, webpack.*, vite.*, next.config.*
|
|
1403
|
-
AND project has build output (dist/, build/, .next/)
|
|
1404
|
-
THEN:
|
|
1405
|
-
Dispatch perf-check --bundle
|
|
1406
|
-
Add findings to report (informational, not blocking)
|
|
1407
|
-
```
|
|
1408
|
-
|
|
1409
|
-
Skip if no frontend files changed or no build output exists. Results are advisory — they don't block the PR. Either way the step is closed on the record:
|
|
1410
|
-
|
|
1411
|
-
```bash
|
|
1412
|
-
keryx job step <job-name> perf-check --status completed|skipped --reason "<result or why it did not run>"
|
|
1413
|
-
```
|
|
1414
|
-
|
|
1415
|
-
### 2.8.3 Step: SKILL LEARNING (conditional)
|
|
1416
|
-
|
|
1417
|
-
Close the self-learning loop (see `rules/core/skill-lifecycle.mdc`). Collect the
|
|
1418
|
-
learning signals produced upstream:
|
|
1419
|
-
- `skill_drift` fields from each task-implementer result (`stale:`/`missing:`).
|
|
1420
|
-
- the `## Skill Learning` block from `review-orchestrator`.
|
|
1421
|
-
|
|
1422
|
-
```
|
|
1423
|
-
IF no skill_drift and Skill Learning == none:
|
|
1424
|
-
→ skip this step (log "no skill drift")
|
|
1425
|
-
|
|
1426
|
-
ELSE for each flagged project-skill:
|
|
1427
|
-
1. Dispatch a subagent to build the learning proposal:
|
|
1428
|
-
- Model: COMPUTED, not chosen — run
|
|
1429
|
-
keryx review tier --scope narrow --json
|
|
1430
|
-
and paste the `model` block into the dispatch. The command names no model:
|
|
1431
|
-
it ranks what the provider reports at runtime, and when it cannot rank
|
|
1432
|
-
anything it prints `inherit: true`, which means the dispatch runs on the
|
|
1433
|
-
session model. See rules/core/model-selection.mdc for what the tiers mean.
|
|
1434
|
-
- Command: keryx skills learn --from-review <review-report-path> \
|
|
1435
|
-
--skill <module>/<skill>
|
|
1436
|
-
(or --from-test / --from-failure when the signal came from verification)
|
|
1437
|
-
- The subagent returns the proposal path. It does NOT apply.
|
|
1438
|
-
2. The orchestrator (flagship) reads the proposal and either:
|
|
1439
|
-
- keryx skills learn apply <proposal.json> (accept), or
|
|
1440
|
-
- discards it and notes why in the report.
|
|
1441
|
-
```
|
|
1442
|
-
|
|
1443
|
-
Never apply a proposal unread, and never run `learn` in a hook. Record applied
|
|
1444
|
-
skill updates in the Job Report under "Skill Updates".
|
|
1445
|
-
|
|
1446
|
-
### 2.9 Step: REPORT
|
|
1447
|
-
|
|
1448
|
-
Aggregate all information into a human-readable summary.
|
|
1449
|
-
|
|
1450
|
-
**Report structure:**
|
|
1451
|
-
```markdown
|
|
1452
|
-
# Job Report: <Title>
|
|
1453
|
-
|
|
1454
|
-
## Summary
|
|
1455
|
-
- **Intent:** <implement / analyze / review>
|
|
1456
|
-
- **Source:** <issue URL or description>
|
|
1457
|
-
- **Branch:** `<branch_name>`
|
|
1458
|
-
- **Tasks:** <completed>/<total> completed
|
|
1459
|
-
- **Review Rounds:** <N> (managed records: <review-id list>)
|
|
1460
|
-
- **Final Status:** <READY FOR PR | HAS WARNINGS | HAS ISSUES | ANALYSIS ONLY>
|
|
1461
|
-
|
|
1462
|
-
## Analysis
|
|
1463
|
-
<analysis summary>
|
|
1464
|
-
|
|
1465
|
-
## Tasks
|
|
1466
|
-
### task-1: <Name>
|
|
1467
|
-
- **Status:** success
|
|
1468
|
-
- **Files:** <list>
|
|
1469
|
-
- **Commits:** <hashes>
|
|
1470
|
-
|
|
1471
|
-
## Review Results
|
|
1472
|
-
Round <n> — `.metaproject/reviews/<review-id>/`
|
|
1473
|
-
| Reviewer | blocker | major | minor | info |
|
|
1474
|
-
|---|---|---|---|---|
|
|
1475
|
-
| review-logic | <N> | <N> | <N> | <N> |
|
|
1476
|
-
| … | | | | |
|
|
1477
|
-
|
|
1478
|
-
Verification: <V> claims recorded, <R> findings refuted, <U> unverified.
|
|
1479
|
-
Reviewers excluded by `keryx review stack`: <name — reason>.
|
|
1480
|
-
Inbound PR comments: <C> collected, <A> answered in the final reply pass.
|
|
1481
|
-
|
|
1482
|
-
## Unresolved Issues
|
|
1483
|
-
- [ ] <file>:<line> — <message> (from <reviewer>, disposition `<state>`, evidence `<ref>`)
|
|
1484
|
-
|
|
1485
|
-
## Final Checks
|
|
1486
|
-
- Lint: PASS
|
|
1487
|
-
- Type Check: PASS
|
|
1488
|
-
- Tests: 42 passed, 0 failed
|
|
1489
|
-
|
|
1490
|
-
## Skill Updates
|
|
1491
|
-
- `<module>/<skill>` v1.2.0 → v1.3.0 (from review F-012; applied) | none
|
|
1492
|
-
|
|
1493
|
-
## Changes Summary
|
|
1494
|
-
### Files Modified (<N>)
|
|
1495
|
-
- `src/...`
|
|
1496
|
-
|
|
1497
|
-
### Files Created (<N>)
|
|
1498
|
-
- `src/...`
|
|
1499
|
-
|
|
1500
|
-
### Commits (<N>)
|
|
1501
|
-
- `abc1234` feat(pipelines): add validation
|
|
1502
|
-
```
|
|
1503
|
-
|
|
1504
|
-
### 2.10 Step: PR (conditional)
|
|
1505
|
-
|
|
1506
|
-
Only runs if `create_pr` is true and intent is `implement`.
|
|
1507
|
-
|
|
1508
|
-
**Dispatch `pr-issue-documenter` to generate the PR description:**
|
|
1509
|
-
|
|
1510
|
-
Pass the following context to `pr-issue-documenter`:
|
|
1511
|
-
```
|
|
1512
|
-
ACTION: generate-pr-description
|
|
1513
|
-
JOB_NAME: <job-name>
|
|
1514
|
-
BRANCH: <feature_branch>
|
|
1515
|
-
BASE: <base_branch>
|
|
1516
|
-
ISSUE_NUMBER: <issue_number if available>
|
|
1517
|
-
CONTEXT_PATH: <JOBS_ROOT>/<job-name>/context_v<N>.md
|
|
1518
|
-
```
|
|
1519
|
-
|
|
1520
|
-
`pr-issue-documenter` will analyze the branch diff and produce a structured PR description (Summary + Changes by area + Key Files table). Use its output as the `body` for the PR.
|
|
1521
|
-
|
|
1522
|
-
**Enrich PR with changelog entry:**
|
|
1523
|
-
|
|
1524
|
-
Dispatch `changelog` skill to generate a changelog snippet for this branch:
|
|
1525
|
-
```
|
|
1526
|
-
changelog <base_branch>..HEAD --format compact
|
|
1527
|
-
```
|
|
1528
|
-
Append the changelog snippet to the PR body under a `## Changelog` section.
|
|
1529
|
-
|
|
1530
|
-
**Present to user:**
|
|
1531
|
-
```
|
|
1532
|
-
Implementation complete. Draft PR proposal:
|
|
1533
|
-
|
|
1534
|
-
Title: <type>(#<issue>): <description>
|
|
1535
|
-
Base: <base> ← <head>
|
|
1536
|
-
|
|
1537
|
-
<pr-issue-documenter output>
|
|
1538
|
-
|
|
1539
|
-
## Changelog
|
|
1540
|
-
<changelog snippet>
|
|
1541
|
-
|
|
1542
|
-
Create this draft PR? (yes/no/edit)
|
|
1543
|
-
```
|
|
1544
|
-
|
|
1545
|
-
If user says "edit" → show the full body, let them modify before creating.
|
|
1546
|
-
|
|
1547
|
-
**If confirmed:**
|
|
1548
|
-
```bash
|
|
1549
|
-
gh pr create --title "<title>" --body "$(cat <<'EOF'
|
|
1550
|
-
<body>
|
|
1551
|
-
EOF
|
|
1552
|
-
)" --base <base_branch> --head <feature_branch> --draft
|
|
1553
|
-
```
|
|
1554
|
-
|
|
1555
|
-
Then record the step, with the PR on the record:
|
|
1556
|
-
|
|
1557
|
-
```bash
|
|
1558
|
-
keryx job step <job-name> pr --status completed --reason "<PR URL>"
|
|
1559
|
-
```
|
|
1560
|
-
|
|
1561
|
-
If the job had review findings but no PR until now, ask the 2.6.2 publication
|
|
1562
|
-
question here — this is the point at which it can be acted on.
|
|
1563
|
-
|
|
1564
|
-
---
|
|
1565
|
-
|
|
1566
|
-
## Phase 3: COMPLETION
|
|
1567
|
-
|
|
1568
|
-
### 3.1 Close the Job Package
|
|
1569
|
-
|
|
1570
|
-
```bash
|
|
1571
|
-
keryx job complete <job-name>
|
|
1572
|
-
```
|
|
1573
|
-
|
|
1574
|
-
This is a **gate, not a formality.** It refuses while any step is still open or
|
|
1575
|
-
`failed`, and the refusal names them:
|
|
1576
|
-
|
|
1577
|
-
```
|
|
1578
|
-
Cannot complete job <name> — 12/15 steps terminal (not terminal: perf-check, deploy; failed: fix).
|
|
1579
|
-
Close each with: keryx job step <name> <step-id> --status completed|skipped [--reason "<why>"]
|
|
1580
|
-
```
|
|
1581
|
-
|
|
1582
|
-
So close every remaining step first, with a reason that says what happened:
|
|
1583
|
-
|
|
1584
|
-
```bash
|
|
1585
|
-
keryx job step <job-name> deploy --status skipped --reason "user declined the staging deploy"
|
|
1586
|
-
```
|
|
1587
|
-
|
|
1588
|
-
A job that ended badly is closed the same way — each unfinished step recorded as
|
|
1589
|
-
`skipped` with the reason it stopped. There is no "aborted" status to set: what
|
|
1590
|
-
happened is in the step statuses and in `journal.md`, which is a record, not a label.
|
|
1591
|
-
|
|
1592
|
-
On success the package moves to `phase: COMPLETION` and `plan.current_step` is
|
|
1593
|
-
cleared, so 0.0 will no longer offer it for resumption.
|
|
1594
|
-
|
|
1595
|
-
### 3.2 Present Results
|
|
1596
|
-
|
|
1597
|
-
Tell user:
|
|
1598
|
-
1. What was accomplished (summary)
|
|
1599
|
-
2. Where the package is: `.metaproject/jobs/<job-name>/`
|
|
1600
|
-
3. PR URL (if created)
|
|
1601
|
-
4. Step durations and retries, read from the package
|
|
1602
|
-
5. Any unresolved issues, each with its recorded disposition
|
|
1603
|
-
|
|
1604
|
-
```
|
|
1605
|
-
✅ Job completed successfully.
|
|
1606
|
-
|
|
1607
|
-
Package: <JOBS_ROOT>/<job-name>/
|
|
1608
|
-
Branch: feature/<slug> (worktree: <path>)
|
|
1609
|
-
PR: <URL or "not created">
|
|
1610
|
-
Review: <N> managed rounds, .metaproject/reviews/<review-id>/
|
|
1611
|
-
Steps: <done>/<total>, retries <sum>
|
|
1612
|
-
|
|
1613
|
-
keryx job status <job-name> — the step list, retries and recorded documents
|
|
1614
|
-
<JOBS_ROOT>/<job-name>/journal.md — every recorded event, in order
|
|
1615
|
-
```
|
|
1616
|
-
|
|
1617
|
-
### 3.3 Post-Completion Options
|
|
1618
|
-
|
|
1619
|
-
After presenting results, offer next steps:
|
|
1620
|
-
|
|
1621
|
-
```
|
|
1622
|
-
What would you like to do next?
|
|
1623
|
-
|
|
1624
|
-
A) ✅ Done — nothing else needed
|
|
1625
|
-
B) 🚀 Deploy to staging — run /deploy staging
|
|
1626
|
-
C) 🔄 Start another job
|
|
1627
|
-
D) 📝 Update CLAUDE.md with session learnings
|
|
1628
|
-
```
|
|
1629
|
-
|
|
1630
|
-
- B → dispatch `deploy` skill with `staging` environment
|
|
1631
|
-
- D → dispatch `claude-md-management` skill
|
|
1632
|
-
|
|
1633
|
-
**Auto-skip** if the job was `analyze` or `review` intent (no deploy makes sense).
|
|
1634
|
-
|
|
1635
|
-
---
|
|
1636
|
-
|
|
1637
|
-
## Plan Extension (Dynamic Planning)
|
|
1638
|
-
|
|
1639
|
-
When the orchestrator starts with an `analyze` intent and the user then says "yes, implement":
|
|
1640
|
-
|
|
1641
|
-
1. **Keep the existing package** — its completed steps (analyze, context, report) stay
|
|
1642
|
-
completed and stay on the record.
|
|
1643
|
-
2. **Create the implementation package** and run it as an `implement` job:
|
|
1644
|
-
|
|
1645
|
-
```bash
|
|
1646
|
-
keryx job init --name <analysis-job-name>-impl --intent implement --project <project_dir>
|
|
1647
|
-
```
|
|
1648
|
-
|
|
1649
|
-
`keryx job` does not rewrite a package's plan after `init`, and this skill does not
|
|
1650
|
-
ask it to: a plan that could be rewritten in place is a plan whose recorded history
|
|
1651
|
-
cannot be trusted. The two packages are linked by naming and by a journal line:
|
|
1652
|
-
|
|
1653
|
-
```bash
|
|
1654
|
-
keryx job step <analysis-job-name> proposal --status completed \
|
|
1655
|
-
--reason "user accepted; implementation continues in job <analysis-job-name>-impl"
|
|
1656
|
-
```
|
|
1657
|
-
3. **Complete the analysis job** (`keryx job complete <analysis-job-name>`) once its
|
|
1658
|
-
steps are closed, so it stops being offered for resumption in 0.0.
|
|
1659
|
-
4. **Continue execution** from Phase 1.3 of the new package.
|
|
1660
|
-
|
|
1661
|
-
This is the core of dynamic planning — the work grows based on user decisions, and each
|
|
1662
|
-
stage keeps its own auditable package rather than one package quietly changing shape.
|
|
1663
|
-
|
|
1664
|
-
---
|
|
1665
|
-
|
|
1666
|
-
## State Management
|
|
1667
|
-
|
|
1668
|
-
There are two kinds of state, and confusing them is how a job loses its record.
|
|
1669
|
-
|
|
1670
|
-
**Persisted — written by `keryx job`, survives the session.** This is exactly what
|
|
1671
|
-
`state.schema.json` declares and exactly what the six commands write. The root carries
|
|
1672
|
-
`additionalProperties: false`, so a field that is not on this list cannot be stored:
|
|
1673
|
-
|
|
1674
|
-
```
|
|
1675
|
-
state.json:
|
|
1676
|
-
phase: CONTEXT | PLAN | EXECUTION | COMPLETION (job init, job step, job complete)
|
|
1677
|
-
intent: implement | analyze | review | custom (job init)
|
|
1678
|
-
job_name: <slug matching ^[a-z0-9-]+$> (job init)
|
|
1679
|
-
create_pr: <bool>
|
|
1680
|
-
context:
|
|
1681
|
-
project_dir: <path> (job init --project)
|
|
1682
|
-
base_branch: <string>
|
|
1683
|
-
issue: { number, title, url, type }
|
|
1684
|
-
plan:
|
|
1685
|
-
steps: [{ id, type, agent, depends, conditional,
|
|
1686
|
-
status: pending|in_progress|completed|skipped|failed }] (job step)
|
|
1687
|
-
current_step: <first step that is not terminal> (maintained by job step)
|
|
1688
|
-
documentation:
|
|
1689
|
-
job_path: .metaproject/jobs/<job-name>
|
|
1690
|
-
documents_created: [<file name per recorded document>] (job document)
|
|
1691
|
-
metrics:
|
|
1692
|
-
steps: [{ step_id, status, started_at, completed_at, duration_ms, retries }] (job step)
|
|
1693
|
-
jobs_root: .metaproject/jobs
|
|
1694
|
-
updated_at: <ISO 8601, stamped on every write>
|
|
1695
|
-
```
|
|
1696
|
-
|
|
1697
|
-
`journal.md` sits beside it: append-only, one timestamped line per event, with the
|
|
1698
|
-
`--reason` text where one was given. Between the two, "what happened to this job" is
|
|
1699
|
-
answerable without this session.
|
|
1700
|
-
|
|
1701
|
-
**In-session — held by the orchestrator for this run, and NOT persisted.** Say it in
|
|
1702
|
-
the dispatch prompt, or it does not reach the sub-agent:
|
|
1703
|
-
|
|
1704
|
-
```
|
|
1705
|
-
branch: { name, worktree_path, merge_base, package_manager, run_command }
|
|
1706
|
-
analysis: { total_tasks, tasks, dependency_order }
|
|
1707
|
-
context_doc: the path to the highest-numbered context_v<N>.md in the package
|
|
1708
|
-
review: the current round's findings — the durable copy is the managed review
|
|
1709
|
-
package, not this
|
|
1710
|
-
```
|
|
1711
|
-
|
|
1712
|
-
Five fields this skill used to claim it recorded — `sanity_check`,
|
|
1713
|
-
`convention_reviewers`, `publication_plan.mode`, `pending_pr_review_report_comment`,
|
|
1714
|
-
`pending_review_ai_artifact` — are **not** persisted and are not in the schema. Nor is
|
|
1715
|
-
a `paused` or `timeout` status. Nothing writes them, so nothing claims them: what would
|
|
1716
|
-
have gone into them goes into a `--reason` on the journal, or into the 2.9 report.
|
|
1717
|
-
|
|
1718
|
-
---
|
|
1719
|
-
|
|
1720
|
-
## state.json Specification
|
|
1721
|
-
|
|
1722
|
-
**Location:** `.metaproject/jobs/<job-name>/state.json`
|
|
1723
|
-
|
|
1724
|
-
**Schema:** `skills/gdskills/orchestration/job-orchestrator/state.schema.json`, registered
|
|
1725
|
-
as the contract `job-orchestrator-state`.
|
|
1726
|
-
|
|
1727
|
-
**Who writes it:** `keryx job`, and nothing else. Every write is validated against the
|
|
1728
|
-
registered contract first and a non-conforming state is **refused**, not written:
|
|
1729
|
-
|
|
1730
|
-
```
|
|
1731
|
-
Refusing to write .metaproject/jobs/<name>/state.json — it does not validate against
|
|
1732
|
-
job-orchestrator-state:
|
|
1733
|
-
- /plan/steps/0/status: must be one of pending, in_progress, completed, skipped, failed
|
|
1734
|
-
```
|
|
1735
|
-
|
|
1736
|
-
**Do not hand-write it.** No `cat > state.json`, no `jq` edit, no sub-agent writing it
|
|
1737
|
-
directly. A hand-written state bypasses the validation and the journal, which is how a
|
|
1738
|
-
package ends up describing a job that did not happen.
|
|
1739
|
-
|
|
1740
|
-
Validate any state file against the contract directly if you need to:
|
|
1741
|
-
|
|
1742
|
-
```bash
|
|
1743
|
-
keryx skills contracts validate .metaproject/jobs/<job-name>/state.json --schema job-orchestrator-state
|
|
1744
|
-
```
|
|
1745
|
-
|
|
1746
|
-
**When it is written:**
|
|
1747
|
-
|
|
1748
|
-
| Command | What it changes |
|
|
1749
|
-
|---|---|
|
|
1750
|
-
| `keryx job init` | creates the package, the plan, `phase: PLAN` |
|
|
1751
|
-
| `keryx job step` | a step's status, `plan.current_step`, `metrics.steps[]` (including `retries`), `phase: EXECUTION` |
|
|
1752
|
-
| `keryx job document` | `documentation.documents_created`, and copies the file in |
|
|
1753
|
-
| `keryx job complete` | `phase: COMPLETION`, clears `plan.current_step` — refused unless every step is terminal |
|
|
1754
|
-
|
|
1755
|
-
**Job resumption (Phase 0.0):** `keryx job list --json` finds packages whose `phase` is
|
|
1756
|
-
not `COMPLETION`; `keryx job status <name> --json` names `next_step` — the first step
|
|
1757
|
-
that is neither `completed` nor `skipped`. Both answers are computed from the file, so
|
|
1758
|
-
a resumed session does not depend on remembering where it was.
|
|
1759
|
-
|
|
1760
|
-
---
|
|
1761
|
-
|
|
1762
|
-
## Interpreting Subagent Results
|
|
1763
|
-
|
|
1764
|
-
**Rule:** `rules/core/subagent-status-protocol.md`
|
|
1765
|
-
|
|
1766
|
-
All subagents dispatched by this orchestrator MUST begin their final response with `STATUS: <STATUS>`. The orchestrator reads this line first and routes accordingly.
|
|
1767
|
-
|
|
1768
|
-
### Iron Law
|
|
1769
|
-
|
|
1770
|
-
**IF A SUBAGENT DOES NOT START WITH `STATUS:`, TREAT IT AS `NEEDS_CONTEXT` AND REQUEST A PROPERLY FORMATTED RESPONSE**
|
|
1771
|
-
|
|
1772
|
-
Do not attempt to infer status from prose. Do not trust a response that "looks fine" but lacks the status line. Run one explicit retry: "Your response did not start with STATUS: <STATUS>. Please reformat using the subagent status protocol (rules/core/subagent-status-protocol.md) and resend your result."
|
|
1773
|
-
|
|
1774
|
-
### How to handle each status
|
|
1775
|
-
|
|
1776
|
-
**`STATUS: DONE`**
|
|
1777
|
-
- Accept result.
|
|
1778
|
-
- Extract structured payload (JSON result, files changed, commits, verification results).
|
|
1779
|
-
- Record it: `keryx job step <job-name> <step-id> --status completed`.
|
|
1780
|
-
- Continue to next step in the plan.
|
|
1781
|
-
|
|
1782
|
-
**`STATUS: DONE_WITH_CONCERNS`**
|
|
1783
|
-
- Accept result as complete.
|
|
1784
|
-
- Read the `## Concerns for orchestrator` section carefully.
|
|
1785
|
-
- Decide: (a) log concern and continue, (b) surface concern to user at next checkpoint, or (c) re-dispatch with adjusted scope if the concern affects correctness.
|
|
1786
|
-
- Do NOT silently discard concerns. Put them on the record and include them in the final report:
|
|
1787
|
-
`keryx job step <job-name> <step-id> --status completed --reason "<the concern>"`
|
|
1788
|
-
— the reason lands in `journal.md`, so the concern outlives the session.
|
|
1789
|
-
|
|
1790
|
-
**`STATUS: BLOCKED`**
|
|
1791
|
-
- Do NOT proceed to any step that depends on this task.
|
|
1792
|
-
- Read `## Reason` and `## What I need from orchestrator`.
|
|
1793
|
-
- Resolve the blocker: provide the missing file, make the decision, fix the dependency, or escalate to the user.
|
|
1794
|
-
- Re-dispatch the subagent with the resolved context.
|
|
1795
|
-
- If the blocker cannot be resolved (e.g., missing information requires user input) → surface to user: "Task <id> is blocked: <reason>. What would you like to do?"
|
|
1796
|
-
|
|
1797
|
-
**`STATUS: NEEDS_CONTEXT`**
|
|
1798
|
-
- Do NOT mark step as failed.
|
|
1799
|
-
- Read `## Missing information` and `## Where it might be found`.
|
|
1800
|
-
- Locate the missing information (check job context document, issue body, package.json, codebase).
|
|
1801
|
-
- Re-dispatch the subagent with the enriched task input.
|
|
1802
|
-
- If the information is not available anywhere → escalate to user with the specific question.
|
|
1803
|
-
|
|
1804
|
-
### Red Flag
|
|
1805
|
-
|
|
1806
|
-
**"The subagent didn't use the status protocol, but the result looks fine"**
|
|
1807
|
-
|
|
1808
|
-
Do not accept this. A subagent that ignores the status protocol is unpredictable — its next failure may not look fine. Enforce the protocol on every response. Run the retry. If the subagent still does not comply after the retry, log it as a critical failure and ask the user how to proceed.
|
|
1809
|
-
|
|
1810
|
-
---
|
|
1811
|
-
|
|
1812
|
-
## Constructing Subagent Context
|
|
1813
|
-
|
|
1814
|
-
**Rule:** `rules/core/subagent-context-construction.md`
|
|
1815
|
-
|
|
1816
|
-
Every prompt dispatched to a subagent must be **explicitly constructed** by the orchestrator. Subagents do not inherit session context, job state, or prior agent output — they only know what the orchestrator tells them.
|
|
1817
|
-
|
|
1818
|
-
### Template dispatch block
|
|
1819
|
-
|
|
1820
|
-
Use this structure for every subagent dispatch:
|
|
1821
|
-
|
|
1822
|
-
```
|
|
1823
|
-
Task({
|
|
1824
|
-
description: "<one-line summary for logs>",
|
|
1825
|
-
subagent_type: "general-purpose",
|
|
1826
|
-
prompt: |
|
|
1827
|
-
## Task
|
|
1828
|
-
<Exactly what to do — no ambiguity>
|
|
1829
|
-
|
|
1830
|
-
## Acceptance Criteria
|
|
1831
|
-
- <criterion 1>
|
|
1832
|
-
- <criterion 2>
|
|
1833
|
-
|
|
1834
|
-
## Context
|
|
1835
|
-
<Only what is relevant for THIS task — decisions, constraints, background>
|
|
1836
|
-
|
|
1837
|
-
## Files to read
|
|
1838
|
-
- <absolute/path/to/file1.ts>
|
|
1839
|
-
- <absolute/path/to/file2.ts>
|
|
1840
|
-
|
|
1841
|
-
## Constraints
|
|
1842
|
-
- Do NOT modify <file or pattern>
|
|
1843
|
-
- <other hard stops>
|
|
1844
|
-
})
|
|
1845
|
-
```
|
|
1846
|
-
|
|
1847
|
-
`subagent_type` is **`general-purpose`**. That is the dispatcher's own name for a
|
|
1848
|
-
general agent; `"general"` is not a value any dispatcher accepts, and a dispatch
|
|
1849
|
-
carrying it does not run.
|
|
1850
|
-
|
|
1851
|
-
### Minimality principle
|
|
1852
|
-
|
|
1853
|
-
Pass only what the subagent needs for this specific task. Do not dump job state, full analysis JSON, or conversation history. Extraneous context fills the subagent's context window with noise and increases hallucination risk.
|
|
1854
|
-
|
|
1855
|
-
Each subagent type gets scoped context:
|
|
1856
|
-
- `issue-analyzer` — issue data + codebase paths only
|
|
1857
|
-
- `context-collector` — focus areas + analysis summary (not full analysis JSON)
|
|
1858
|
-
- `task-implementer` — its specific task object + `CONTEXT_PATH` (not other tasks' data)
|
|
1859
|
-
- Reviewers — diff range + file list (not implementation details)
|
|
1860
|
-
|
|
1861
|
-
### Red Flag
|
|
1862
|
-
|
|
1863
|
-
**"The subagent can read the job state.json if it needs more context"**
|
|
1864
|
-
|
|
1865
|
-
→ Iron Law: **Orchestrator constructs context. Subagents receive, not retrieve.**
|
|
1866
|
-
|
|
1867
|
-
The subagent must not fetch orchestrator state independently. If the subagent needs information, the orchestrator puts it in the dispatch prompt. A subagent reading `state.json` on its own is a sign the orchestrator dispatch was incomplete.
|
|
1868
|
-
|
|
1869
|
-
---
|
|
1870
|
-
|
|
1871
|
-
## Automation Settings
|
|
1872
|
-
|
|
1873
|
-
| Setting | Default | Options | Description |
|
|
1874
|
-
|---------|---------|---------|-------------|
|
|
1875
|
-
| `skip_confirmation` | `true` | `true` only | Sub-agents run without per-dispatch confirmation. `{"const": true}` in the input contract. Does **not** cover the 0.4 operator gate — that one is `plan_approval`. |
|
|
1876
|
-
| `base_branch` | auto-detect | any | Base branch (auto-detect from repo default, or ask user). No default in the contract. |
|
|
1877
|
-
| `max_review_iterations` | `3` | 1-3 | Max review → fix iterations. Three everywhere: this table, 2.7, and the input contract's `maximum` and `default`. |
|
|
1878
|
-
| `create_pr` | `true` | true/false | Whether to propose PR at the end |
|
|
1879
|
-
| `auto_create_pr` | `false` | true/false | Auto-create PR without asking |
|
|
1880
|
-
| `review_flags` | auto-detect | `review-orchestrator` flags | Reviewer selection passed to `review-orchestrator` (e.g. `--backend --security`). Unset means auto-detect from the diff. |
|
|
1881
|
-
| `convention_reviewers` | `"ask"` | `"ask"` / `"all"` / `"none"` / skill names | Optional convention reviewers to include in review |
|
|
1882
|
-
| `verification_mode` | `annotate` | `off`/`annotate`/`filter` | Passed to `review-orchestrator` and to `review ingest --verification-mode` |
|
|
1883
|
-
| `run_final_checks` | `true` | true/false | Run lint/type-check/test |
|
|
1884
|
-
| `run_interview` | `true` | true/false | Run interview skill in Phase 0 |
|
|
1885
|
-
| `dry_run` | `false` | true/false | Plan-only mode: full Phase 0+1, no agent dispatch or git ops |
|
|
1886
|
-
| `plan_approval` | `true` | true/false | Show agent plan and ask approve/adjust before execution (1.3) |
|
|
1887
|
-
| `run_test_gen` | `true` | true/false | Auto-run test-gen if implementer skips tests |
|
|
1888
|
-
| `run_security_audit` | `true` | true/false | Auto-run security-audit if auth/API/DB files touched |
|
|
1889
|
-
| `run_perf_check` | `true` | true/false | Auto-run perf-check if frontend/bundle files changed |
|
|
1890
|
-
| `run_changelog` | `true` | true/false | Auto-generate changelog entry and include in PR description |
|
|
1891
|
-
| `publish_pr_review_report` | `ask` | `ask`/`comment`/`comment-and-ai-artifact`/`none` | Whether to publish a concise PR review comment and optional detailed AI markdown artifact |
|
|
1892
|
-
| `run_deploy` | `ask` | `ask`/`true`/`false` | Post-PR deploy: ask user (ask), always deploy (true), never (false) |
|
|
1893
|
-
|
|
1894
|
-
`review_mode` is gone. It defaulted to `"code-review"` — a skill that is not bundled
|
|
1895
|
-
and not catalogued — and its `"individual"` alternative named the legacy hand-dispatch
|
|
1896
|
-
path 2.6 replaced. Reviewer selection is `review_flags`, and the reviewers are
|
|
1897
|
-
`review-orchestrator`'s.
|
|
1898
|
-
|
|
1899
|
-
## Dry-Run Mode
|
|
1900
|
-
|
|
1901
|
-
When `dry_run: true` is set (or `--dry-run` is passed):
|
|
1902
|
-
|
|
1903
|
-
1. **Phase 0** runs fully — context collection, interviewer (if applicable), summary + confirm
|
|
1904
|
-
2. **Phase 1** runs fully — plan is built and displayed with step tree
|
|
1905
|
-
3. **Phase 2 is skipped entirely** — no sub-agents dispatched, no git operations
|
|
1906
|
-
4. **Output:** Full plan tree with agent names, input data shapes, dependencies:
|
|
1907
|
-
|
|
1908
|
-
```
|
|
1909
|
-
Dry-run plan for: issue-4141--pipeline-validation
|
|
1910
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1911
|
-
Step 1: analyze [issue-analyzer] → input: issue #4141
|
|
1912
|
-
Step 2: context [context-collector] → input: analysis result, project_dir
|
|
1913
|
-
Step 3: prepare [orchestrator] → creates: feature/pipeline-validation worktree
|
|
1914
|
-
Step 4: tests-creator [tests-creator × 3] → RED stubs, one per task
|
|
1915
|
-
Step 5: implement [task-implementer × 3] → wave-parallel, 3 tasks
|
|
1916
|
-
Step 6: sanity-check [orchestrator] → verifies commits exist
|
|
1917
|
-
Step 7: verify [code-verifier] → lint + type-check + test + imports
|
|
1918
|
-
Step 8: review [review-orchestrator] → managed round, ingested
|
|
1919
|
-
Step 9: security [security-audit] → conditional: auth/API/DB/env files
|
|
1920
|
-
Step 10: fix [task-implementer] → conditional: if NEEDS_FIX
|
|
1921
|
-
Step 11: verify-post-fix [code-verifier] → conditional: after fix
|
|
1922
|
-
Step 12: perf-check [perf-check] → conditional: frontend/bundle files
|
|
1923
|
-
Step 13: report [orchestrator] → aggregates all results
|
|
1924
|
-
Step 14: pr [orchestrator + gh CLI] → conditional: if create_pr
|
|
1925
|
-
Step 15: deploy [deploy] → conditional: if user asks
|
|
1926
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1927
|
-
Estimated sub-agent calls: 11-14 (varies with tasks and review findings)
|
|
1928
|
-
No changes will be made. Use without --dry-run to execute.
|
|
1929
|
-
```
|
|
1930
|
-
|
|
1931
|
-
5. Ask user: "Execute this plan? (yes / adjust / abort)"
|
|
1932
|
-
|
|
1933
|
-
## Budget Guards
|
|
1934
|
-
|
|
1935
|
-
**There are no timeouts, because this execution model has no clock.** This skill runs
|
|
1936
|
-
as a model inside a turn-based session: it cannot observe wall-clock time passing, it
|
|
1937
|
-
cannot kill a sub-agent mid-flight, and it has no persisted start time to measure
|
|
1938
|
-
against. A `step_timeout_ms` that "kills the agent if exceeded" was a guard nothing
|
|
1939
|
-
could ever enforce, and a job could not end with a `timeout` status because no such
|
|
1940
|
-
status exists in `state.schema.json`.
|
|
1941
|
-
|
|
1942
|
-
What actually bounds this orchestrator:
|
|
1943
|
-
|
|
1944
|
-
| Guard | Bound | Where it is enforced |
|
|
1945
|
-
|-------|-------|----------------------|
|
|
1946
|
-
| review → fix rounds | 3 | 2.7, and `max_review_iterations` (`maximum: 3`) in the input contract |
|
|
1947
|
-
| repetition, whatever the count says | first repeat | the STUCK CHECK in 2.7, and `keryx review loop` against the durable record |
|
|
1948
|
-
| retries per step | recorded, not guessed | `metrics.steps[].retries`, incremented by `keryx job step --status in-progress` and read back with `keryx job status --json` |
|
|
1949
|
-
| reviewer fan-out | 4 in flight | `keryx review budget --outstanding <n>` before every dispatch (2.6.1) |
|
|
1950
|
-
| spend | 3 USD by default | `keryx review budget --spent <usd>` — a non-zero exit means stop and ask |
|
|
1951
|
-
|
|
1952
|
-
Each of these is a number some command reads or writes. A guard no command can
|
|
1953
|
-
observe is not a guard; this section lists only observable ones.
|
|
1954
|
-
|
|
1955
|
-
**Context passing rules (minimal context principle):**
|
|
1956
|
-
- `issue-analyzer`: receives only issue data + codebase paths (NOT previous job state)
|
|
1957
|
-
- `context-collector`: receives focus areas + analysis summary (NOT full analysis JSON)
|
|
1958
|
-
- `task-implementer`: receives only its specific task object + context.md path (NOT other tasks' results)
|
|
1959
|
-
- Reviewers: receive only the diff range + file list (NOT implementation details)
|
|
1960
|
-
|
|
1961
|
-
---
|
|
1962
|
-
|
|
1963
|
-
## Error Handling
|
|
1964
|
-
|
|
1965
|
-
Each step failure is classified into one of three classes with different recovery paths:
|
|
1966
|
-
|
|
1967
|
-
| Class | Meaning | Action |
|
|
1968
|
-
|-------|---------|--------|
|
|
1969
|
-
| `terminal` | Unrecoverable — cannot continue | ABORT immediately, surface actionable message |
|
|
1970
|
-
| `retryable` | Transient failure — malformed output, an unusable reply, a command that failed on something transient | Auto-retry up to 2× with **identical prompt**, re-opening the step each time so `retries` counts it. After 2 failures → escalate to `recoverable` |
|
|
1971
|
-
| `recoverable` | Partial success or skippable failure | Ask user with specific "continue from here / skip step / abort" options |
|
|
1972
|
-
|
|
1973
|
-
### Error Table
|
|
1974
|
-
|
|
1975
|
-
| Error | Class | Action |
|
|
1976
|
-
|-------|-------|--------|
|
|
1977
|
-
| Issue not found (404) | `terminal` | ABORT — issue-analyzer reports 404 |
|
|
1978
|
-
| Analysis returns 0 tasks | `recoverable` | Try smart fallback: (1) re-read issue with broader scope, (2) ask user to clarify, (3) if still 0 → ABORT |
|
|
1979
|
-
| Branch/worktree creation fails | `terminal` | ABORT — report git error. NEVER fall back to `git checkout -b` |
|
|
1980
|
-
| Interviewer `ready_to_proceed: false` | `terminal` | STOP — tell user which blockers remain |
|
|
1981
|
-
| Sub-agent returns malformed JSON | `retryable` | Retry with: "Output was malformed. Fix: [errors]. Try again." (max 2×) |
|
|
1982
|
-
| Sub-agent returns nothing usable | `retryable` | Re-open the step (`job step --status in-progress`, which counts the retry) and re-dispatch the identical prompt (max 2×) |
|
|
1983
|
-
| Task implementation fails | `recoverable` | Ask: "Step failed. Continue remaining tasks / skip this task / abort?" |
|
|
1984
|
-
| `keryx job` refuses a write | `terminal` | The message names the field that failed validation. Fix the input; do NOT hand-write `state.json` to route around it. |
|
|
1985
|
-
| `keryx job complete` refuses | `recoverable` | It names the open and failed steps. Close each with `job step --status completed\|skipped --reason "<why>"`. |
|
|
1986
|
-
| `keryx review ingest` refuses a scope-B finding | `terminal` for that round | Recompute `keryx review blast-radius --json` and re-ingest with `--blast-radius`. The round is not recordable until the set is supplied. |
|
|
1987
|
-
| All reviewers fail | `recoverable` | Record the round as failed with a reason, add a warning to the report, continue to VERIFY (2.8) |
|
|
1988
|
-
| Fix loop exceeds max_review_iterations | `recoverable` | Disposition every surviving finding, log which ended the loop, continue to VERIFY (2.8) |
|
|
1989
|
-
| Final checks fail | `recoverable` | Include in report, still propose PR (user decides) |
|
|
1990
|
-
| gh CLI not available | `recoverable` | Print PR data, user creates manually. `keryx review comments` needs it too — say so rather than reporting `0 outstanding`. |
|
|
1991
|
-
|
|
1992
|
-
### Retry Protocol (for `retryable` errors)
|
|
1993
|
-
|
|
1994
|
-
```
|
|
1995
|
-
attempt 1: keryx job step <job-name> <step-id> --status in-progress
|
|
1996
|
-
run step normally
|
|
1997
|
-
→ failure: classify error
|
|
1998
|
-
→ if retryable: keryx job step <job-name> <step-id> --status in-progress # retries += 1
|
|
1999
|
-
retry with the EXACT same prompt + "Fix these errors: [list]"
|
|
2000
|
-
→ if fails again: escalate to recoverable → ask user
|
|
2001
|
-
→ if success: keryx job step <job-name> <step-id> --status completed
|
|
2002
|
-
```
|
|
2003
|
-
|
|
2004
|
-
**Critical:** on retry, re-send the **same prompt** — hold it for the duration of the
|
|
2005
|
-
step and re-send it verbatim. Never re-derive it; re-derivation causes drift.
|
|
2006
|
-
|
|
2007
|
-
The prompt itself is **not** persisted: `keryx job` writes no `step.prompt` and no
|
|
2008
|
-
prompt size, so do not instruct a resuming session to read one. What *is* persisted is
|
|
2009
|
-
that the attempt happened — `metrics.steps[].retries`, incremented every time the step
|
|
2010
|
-
re-enters `in_progress`, and the `--reason` line in `journal.md`. A resumed session
|
|
2011
|
-
therefore knows how many attempts a step has had, which is the fact the retry budget
|
|
2012
|
-
needs, and reconstructs the prompt from the plan and the analysis exactly as the first
|
|
2013
|
-
attempt did.
|
|
2014
|
-
|
|
2015
|
-
---
|
|
2016
|
-
|
|
2017
|
-
## Progress Notifications
|
|
2018
|
-
|
|
2019
|
-
The orchestrator must keep the user informed during long-running execution. This is especially important for non-interactive channels (Telegram, Slack, CI).
|
|
2020
|
-
|
|
2021
|
-
**At each phase transition:**
|
|
2022
|
-
```
|
|
2023
|
-
🔄 Phase 0 → Phase 1: Building execution plan...
|
|
2024
|
-
🔄 Phase 1 → Phase 2: Executing 7 steps...
|
|
2025
|
-
✅ Phase 2 → Phase 3: Execution complete, generating report...
|
|
2026
|
-
```
|
|
2027
|
-
|
|
2028
|
-
**At each step transition (Phase 2):**
|
|
2029
|
-
```
|
|
2030
|
-
📋 Job: issue-4141--pipeline-validation
|
|
2031
|
-
├─ ✅ Analyze issue — 3 tasks found
|
|
2032
|
-
├─ ✅ Collect context — context.md ready
|
|
2033
|
-
├─ ✅ Prepare branch — feature/pipeline-validation
|
|
2034
|
-
├─ 🔄 Implement (2/3 tasks done)
|
|
2035
|
-
│ ├─ ✅ task-1: Add validation schema
|
|
2036
|
-
│ ├─ ✅ task-2: Implement validator
|
|
2037
|
-
│ └─ 🔄 task-3: Add integration tests...
|
|
2038
|
-
├─ ⏳ Verify
|
|
2039
|
-
├─ ⏳ Review
|
|
2040
|
-
├─ ⏳ Fix (if needed)
|
|
2041
|
-
└─ ⏳ PR
|
|
2042
|
-
```
|
|
2043
|
-
|
|
2044
|
-
**Notify at every step boundary** — before dispatching and after recording the result.
|
|
2045
|
-
Those are the moments this skill actually regains control, so they are the only moments
|
|
2046
|
-
it can say anything; a "notify every 30 seconds" rule would need a timer nothing here
|
|
2047
|
-
has. `keryx job status <job-name>` renders the same tree from the package, which is
|
|
2048
|
-
what to show a user who asks mid-run.
|
|
2049
|
-
|
|
2050
|
-
**If notification tools are unavailable** (no MCP, no Telegram): fall back to inline text output between steps.
|
|
2051
|
-
|
|
2052
|
-
---
|
|
2053
|
-
|
|
2054
|
-
## Rules of Engagement
|
|
2055
|
-
|
|
2056
|
-
Everything this orchestrator does is described once, with its reason, in the
|
|
2057
|
-
section that owns it. This section is not a second copy of that. It carries the
|
|
2058
|
-
three rules stated nowhere else, and the four whose cost, when you get them
|
|
2059
|
-
wrong, cannot be undone by trying again.
|
|
2060
|
-
|
|
2061
|
-
### Stated only here
|
|
2062
|
-
|
|
2063
|
-
- **Do not ask the user anything between Phase 0 and completion.** Two
|
|
2064
|
-
exceptions: a critical failure, and a decision to extend the plan (analyze →
|
|
2065
|
-
implement). Everything else was settled in Phase 0, or is settled by the
|
|
2066
|
-
package rather than by asking.
|
|
2067
|
-
- **Do not push the branch until the user confirms**, unless `auto_create_pr` is
|
|
2068
|
-
set. A push is visible to everyone watching the repository, and there is no
|
|
2069
|
-
version of un-pushing it that they do not see.
|
|
2070
|
-
- **Say where the job package is when the job ends.** It is the only durable
|
|
2071
|
-
record of the run, and a user who cannot find it is left with nothing to read.
|
|
2072
|
-
|
|
2073
|
-
### Unrecoverable if wrong
|
|
2074
|
-
|
|
2075
|
-
- **Branch with `git worktree add`** — never `git checkout -b` or
|
|
2076
|
-
`git switch -c`. Those switch the main working directory out from under the
|
|
2077
|
-
user's own session, mid-run.
|
|
2078
|
-
- **Run every later command in the worktree directory**, not the project root.
|
|
2079
|
-
A build, test or commit that lands in the wrong tree is attributed to work
|
|
2080
|
-
nobody did.
|
|
2081
|
-
- **`keryx job` is the only writer of `state.json`**, this orchestrator
|
|
2082
|
-
included. It validates each write against the `job-orchestrator-state`
|
|
2083
|
-
contract; a hand-written file satisfies no contract, and the next session
|
|
2084
|
-
resumes into a state that never existed.
|
|
2085
|
-
- **Ask for the project directory in Phase 0.** There is no default. A wrong
|
|
2086
|
-
guess writes a job package into somebody else's repository.
|
|
2087
|
-
|
|
2088
|
-
---
|
|
2089
|
-
|
|
2090
|
-
## Configurable Jobs Root
|
|
2091
|
-
|
|
2092
|
-
`JOBS_ROOT` in this document is shorthand for **`.metaproject/jobs`, relative to the
|
|
2093
|
-
project directory** — and that is the only value it takes. `keryx job` resolves it from
|
|
2094
|
-
the working directory and records it in `state.json → jobs_root`; there is no
|
|
2095
|
-
environment variable and no override, so do not tell a sub-agent to look one up.
|
|
2096
|
-
|
|
2097
|
-
```bash
|
|
2098
|
-
JOBS_ROOT=".metaproject/jobs"
|
|
2099
|
-
```
|
|
2100
|
-
|
|
2101
|
-
The project directory is the one collected in Phase 0.2 and passed as
|
|
2102
|
-
`keryx job init --project <path>`. Run `keryx job` commands from that directory, and
|
|
2103
|
-
expand `<JOBS_ROOT>` to the literal path when writing a sub-agent prompt — a subagent
|
|
2104
|
-
receives paths, it does not resolve them.
|
|
2105
|
-
|
|
2106
|
-
---
|
|
2107
|
-
|
|
2108
|
-
## Post-Mortem (for failed/aborted jobs)
|
|
2109
|
-
|
|
2110
|
-
When a job ends with a step recorded `failed`, or with unresolved blocker findings:
|
|
2111
|
-
|
|
2112
|
-
1. **Auto-generate post-mortem** document. The timeline is not recalled — it is read
|
|
2113
|
-
off `journal.md`, which `keryx job` timestamped as the job ran, and the retry counts
|
|
2114
|
-
come from `keryx job status <job-name> --json`:
|
|
2115
|
-
|
|
2116
|
-
```markdown
|
|
2117
|
-
# Post-Mortem: <job-name>
|
|
2118
|
-
|
|
2119
|
-
## Timeline
|
|
2120
|
-
(from .metaproject/jobs/<job-name>/journal.md — every line as recorded)
|
|
2121
|
-
- <ISO timestamp> - created
|
|
2122
|
-
- <ISO timestamp> - step: implement in-progress (retries 0)
|
|
2123
|
-
- <ISO timestamp> - step: implement in-progress (retries 1)
|
|
2124
|
-
- <ISO timestamp> - step: implement failed (retries 1) — <reason>
|
|
2125
|
-
|
|
2126
|
-
## What Went Wrong
|
|
2127
|
-
- <Step name> failed with: <error class> — <error message>
|
|
2128
|
-
- Recorded retries: <metrics.steps[].retries>
|
|
2129
|
-
- Root cause hypothesis: <analysis>
|
|
2130
|
-
|
|
2131
|
-
## What Worked
|
|
2132
|
-
- <N> tasks completed successfully
|
|
2133
|
-
- Context collection was accurate
|
|
2134
|
-
|
|
2135
|
-
## Recommendations for Retry
|
|
2136
|
-
- Fix <specific issue> before re-running
|
|
2137
|
-
- Consider splitting task-3 into smaller subtasks
|
|
2138
|
-
```
|
|
2139
|
-
|
|
2140
|
-
2. Save to `.metaproject/jobs/<job-name>/post-mortem.md`
|
|
2141
|
-
3. Include in final user message: "Post-mortem saved to `.metaproject/jobs/<job-name>/post-mortem.md`"
|
|
2142
|
-
|
|
2143
|
-
There is no `aborted` or `timeout` job status to key this on and nothing writes one.
|
|
2144
|
-
The trigger is what the package says: a `failed` step, or findings still without a
|
|
2145
|
-
terminal disposition.
|
|
2146
|
-
|
|
2147
|
-
---
|
|
2148
|
-
|
|
2149
|
-
## Metrics Collection
|
|
2150
|
-
|
|
2151
|
-
`keryx job step` writes a metrics row per step. Nothing here is collected by hand.
|
|
2152
|
-
|
|
2153
|
-
**Written per step, into `state.json → metrics.steps[]`:**
|
|
2154
|
-
```json
|
|
2155
|
-
{
|
|
2156
|
-
"step_id": "implement",
|
|
2157
|
-
"status": "completed",
|
|
2158
|
-
"started_at": "2026-08-30T10:30:00.000Z",
|
|
2159
|
-
"completed_at": "2026-08-30T10:35:22.000Z",
|
|
2160
|
-
"duration_ms": 322000,
|
|
2161
|
-
"retries": 0
|
|
2162
|
-
}
|
|
2163
|
-
```
|
|
2164
|
-
|
|
2165
|
-
- `started_at` is stamped every time the step enters `in_progress`.
|
|
2166
|
-
- `retries` counts attempts **beyond the first**: the first `--status in-progress`
|
|
2167
|
-
leaves it at 0 and every re-entry adds one. It is on disk, so a resumed session
|
|
2168
|
-
reads the real count instead of restarting at zero.
|
|
2169
|
-
- `duration_ms` is `completed_at - started_at` for the last attempt.
|
|
2170
|
-
- `total_tokens` is declared in the schema and **nothing writes it**. Do not report a
|
|
2171
|
-
token figure as if it came from the package; if you have one, say where it came from.
|
|
2172
|
-
|
|
2173
|
-
**Read it back:**
|
|
2174
|
-
```bash
|
|
2175
|
-
keryx job status <job-name> --json # `retries` per step, plus phase and next_step
|
|
2176
|
-
```
|
|
2177
|
-
|
|
2178
|
-
**Aggregated in the report:**
|
|
2179
|
-
```markdown
|
|
2180
|
-
## Metrics
|
|
2181
|
-
| Step | Duration | Retries |
|
|
2182
|
-
|------|----------|---------|
|
|
2183
|
-
| Analyze | 45s | 0 |
|
|
2184
|
-
| Context | 30s | 0 |
|
|
2185
|
-
| Implement | 5m 22s | 1 |
|
|
2186
|
-
| Review | 1m 10s | 0 |
|
|
2187
|
-
| **Total** | **7m 47s** | **1** |
|
|
2188
|
-
```
|
|
2189
|
-
|
|
2190
|
-
This data identifies which steps are bottlenecks and which ones needed a second attempt.
|