@tyroneross/build-loop 0.30.3 → 0.35.0
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/.agents/plugins/marketplace.json +2 -2
- package/.claude-plugin/marketplace.json +4 -4
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +11 -2
- package/README.md +8 -7
- package/agents/advisor.md +111 -0
- package/agents/alignment-checker.md +11 -0
- package/agents/assessment-orchestrator.md +1 -1
- package/agents/build-orchestrator.md +28 -33
- package/agents/fact-checker.md +1 -1
- package/agents/fix-critique.md +1 -1
- package/agents/independent-auditor.md +1 -1
- package/agents/overfitting-reviewer.md +1 -1
- package/agents/plan-critic.md +8 -6
- package/agents/promotion-reviewer.md +1 -1
- package/agents/retrospective-synthesizer.md +20 -3
- package/agents/scope-auditor.md +1 -1
- package/agents/security-reviewer.md +1 -1
- package/agents/self-improvement-architect.md +1 -1
- package/commands/{handoff.md → compose-handoff.md} +4 -4
- package/commands/{optimize.md → optimize-run.md} +1 -1
- package/commands/{agent-rally-point.md → rally-point.md} +3 -3
- package/commands/{research.md → research-run.md} +1 -1
- package/commands/setup-memory.md +32 -0
- package/commands/{plan-verify.md → verify-plan.md} +1 -1
- package/docs/agent-surface-policy.md +38 -20
- package/docs/memory-setup.md +19 -14
- package/hooks/_resolve_python.sh +28 -0
- package/hooks/closeout.sh +58 -0
- package/hooks/git/pre-push +69 -6
- package/hooks/hooks.json +34 -13
- package/hooks/post-push-closeout.sh +73 -0
- package/hooks/session-start-closeout.sh +69 -0
- package/hooks/session-start-memory.sh +27 -0
- package/hooks/session-start-plugin-heal.sh +33 -0
- package/hooks/test_closeout.sh +124 -0
- package/package.json +7 -4
- package/plugin-artifacts/codex/.codex-plugin/plugin.json +41 -0
- package/plugin-artifacts/codex/AGENTS.md +507 -0
- package/plugin-artifacts/codex/BUILD-ARTIFACT.md +5 -0
- package/plugin-artifacts/codex/LICENSE +202 -0
- package/plugin-artifacts/codex/README.md +404 -0
- package/plugin-artifacts/codex/docs/agent-surface-policy.md +63 -0
- package/plugin-artifacts/codex/references/advisor-dispatch-ladder.md +62 -0
- package/plugin-artifacts/codex/references/agent-role-taxonomy.md +135 -0
- package/plugin-artifacts/codex/references/autonomous-and-per-commit-modes.md +161 -0
- package/plugin-artifacts/codex/references/autonomy-config.md +231 -0
- package/plugin-artifacts/codex/references/capability-routing.md +182 -0
- package/plugin-artifacts/codex/references/codex-subagents.md +106 -0
- package/plugin-artifacts/codex/references/coordination-file-template.md +181 -0
- package/plugin-artifacts/codex/references/coordination-rules.md +283 -0
- package/plugin-artifacts/codex/references/dogfood-reload-checkpoint.md +112 -0
- package/plugin-artifacts/codex/references/halt-and-ask-protocol.md +102 -0
- package/plugin-artifacts/codex/references/implementer-envelope-schema.md +302 -0
- package/plugin-artifacts/codex/references/intent-capability-pack.md +257 -0
- package/plugin-artifacts/codex/references/intent-exploration-prompts.md +96 -0
- package/plugin-artifacts/codex/references/leadership.md +72 -0
- package/plugin-artifacts/codex/references/memory-systems.md +238 -0
- package/plugin-artifacts/codex/references/memory.md +299 -0
- package/plugin-artifacts/codex/references/model-tier-mapping.md +257 -0
- package/plugin-artifacts/codex/references/modular-systems-pack.md +96 -0
- package/plugin-artifacts/codex/references/phase-1-assess.md +231 -0
- package/plugin-artifacts/codex/references/phase-2-plan.md +78 -0
- package/plugin-artifacts/codex/references/phase-3-execute.md +49 -0
- package/plugin-artifacts/codex/references/phase-4-review.md +322 -0
- package/plugin-artifacts/codex/references/phase-5-iterate.md +71 -0
- package/plugin-artifacts/codex/references/phase-6-learn.md +56 -0
- package/plugin-artifacts/codex/references/recent-design-structures.md +274 -0
- package/plugin-artifacts/codex/references/research-trigger-policy.md +140 -0
- package/plugin-artifacts/codex/references/runtime-smoke-triggers.md +42 -0
- package/plugin-artifacts/codex/references/self-review.md +234 -0
- package/plugin-artifacts/codex/references/single-writer-commit-protocol.md +90 -0
- package/plugin-artifacts/codex/references/task-capture-policy.md +68 -0
- package/plugin-artifacts/codex/references/ui-io-contract.md +116 -0
- package/plugin-artifacts/codex/references/ui-spotcheck-protocol.md +65 -0
- package/plugin-artifacts/codex/skills/build-loop/SKILL.md +372 -0
- package/plugin-artifacts/codex/skills/build-loop/detect-plugins.mjs +82 -0
- package/plugin-artifacts/codex/skills/build-loop/eval-guide.md +65 -0
- package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +549 -0
- package/plugin-artifacts/codex/skills/build-loop/phases/fact-check.md +42 -0
- package/plugin-artifacts/codex/skills/build-loop/phases/ui-validation.md +267 -0
- package/plugin-artifacts/codex/skills/build-loop/references/advisor-dispatch-ladder.md +62 -0
- package/plugin-artifacts/codex/skills/build-loop/references/apple-native-planning.md +439 -0
- package/plugin-artifacts/codex/skills/build-loop/references/autonomous-and-per-commit-modes.md +161 -0
- package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +182 -0
- package/plugin-artifacts/codex/skills/build-loop/references/codex-subagents.md +106 -0
- package/plugin-artifacts/codex/skills/build-loop/references/coordination.md +161 -0
- package/plugin-artifacts/codex/skills/build-loop/references/correction-aware-capture.md +177 -0
- package/plugin-artifacts/codex/skills/build-loop/references/independent-auditor.md +72 -0
- package/plugin-artifacts/codex/skills/build-loop/references/intent-capability-pack.md +257 -0
- package/plugin-artifacts/codex/skills/build-loop/references/intent-exploration-prompts.md +96 -0
- package/plugin-artifacts/codex/skills/build-loop/references/leadership.md +72 -0
- package/plugin-artifacts/codex/skills/build-loop/references/memory.md +299 -0
- package/plugin-artifacts/codex/skills/build-loop/references/modular-systems-pack.md +96 -0
- package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +129 -0
- package/plugin-artifacts/codex/skills/build-loop/references/pay-it-forward-arch.md +98 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +231 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +78 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +49 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +322 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +71 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +56 -0
- package/plugin-artifacts/codex/skills/build-loop/references/recent-design-structures.md +274 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/ASSESSMENT.md +85 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +149 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +32 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +48 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +60 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +51 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +71 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +52 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/trace-comparison.md +202 -0
- package/plugin-artifacts/codex/skills/build-loop/references/self-recursive-dev.md +77 -0
- package/plugin-artifacts/codex/skills/build-loop/references/self-review.md +234 -0
- package/plugin-artifacts/codex/skills/build-loop/references/ui-io-contract.md +116 -0
- package/plugin-artifacts/codex/skills/build-loop/scanners/audit-design-rules.mjs +476 -0
- package/plugin-artifacts/codex/skills/build-loop/scanners/require-visual-evidence.mjs +239 -0
- package/plugin-artifacts/codex/skills/build-loop/templates/backlog-item.md +35 -0
- package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +100 -0
- package/plugin-artifacts/codex/skills/build-loop/templates/ui-subagent-prompt.md +179 -0
- package/plugin-artifacts/codex/skills/build-loop/templates/ux-fix-plan.md +40 -0
- package/scripts/_paths.py +59 -13
- package/scripts/build_codex_plugin_artifact.py +314 -0
- package/scripts/check_cache_sync.py +1 -1
- package/scripts/install_memory.py +11 -3
- package/scripts/prune_plugin_cache.py +225 -11
- package/scripts/sync_navgator_lessons.py +25 -0
- package/scripts/sync_plugin_cache.py +66 -36
- package/skills/agent-rally-point/SKILL.md +1 -1
- package/skills/agent-rally-watcher/SKILL.md +1 -1
- package/skills/build-loop/SKILL.md +11 -155
- package/skills/build-loop/references/advisor-dispatch-ladder.md +62 -0
- package/skills/build-loop/references/autonomous-and-per-commit-modes.md +161 -0
- package/skills/build-loop/references/capability-routing.md +4 -3
- package/skills/build-loop/references/codex-subagents.md +8 -0
- package/skills/build-loop/references/coordination.md +1 -1
- package/skills/build-loop/references/intent-capability-pack.md +88 -1
- package/skills/build-loop/references/memory.md +17 -2
- package/skills/build-loop/references/phase-1-assess.md +13 -0
- package/skills/build-loop/references/phase-2-plan.md +2 -1
- package/skills/build-loop/references/phase-3-execute.md +4 -2
- package/skills/build-loop/references/phase-4-review.md +12 -0
- package/skills/build-loop/references/phase-6-learn.md +1 -1
- package/skills/build-loop/references/self-review.md +4 -2
- package/skills/build-loop/templates/codex-worker-prompt.md +45 -34
- package/skills/handoff/SKILL.md +3 -3
- package/skills/loop-builder/SKILL.md +98 -0
- package/skills/loop-builder/presets/active-project-evidence.yaml +97 -0
- package/skills/loop-builder/presets/generic-artifact-loop.yaml +95 -0
- package/skills/loop-builder/presets/presentation-audit.yaml +96 -0
- package/skills/loop-builder/presets/research-synthesis.yaml +96 -0
- package/skills/loop-builder/presets/source-ingestion-raw-data-audit.yaml +96 -0
- package/skills/loop-builder/references/spec-format.md +80 -0
- package/skills/loop-builder/scripts/loop_builder.py +346 -0
- package/skills/model-tiering/SKILL.md +65 -40
- package/skills/optimize/SKILL.md +2 -2
- package/skills/plan-verify/SKILL.md +1 -1
- package/skills/plugin-builder/references/distribution.md +8 -0
- package/skills/research/SKILL.md +33 -6
- package/skills/runtime-parity-verification/SKILL.md +51 -0
- package/skills/spec-writing/SKILL.md +19 -0
- package/templates/memory/README.md +65 -0
- package/templates/memory/charter.md.template +46 -0
- package/templates/memory/manifest.json +24 -4
- package/codex-skills/debug-loop/SKILL.md +0 -18
- package/codex-skills/handoff/SKILL.md +0 -22
- package/codex-skills/knowledge/SKILL.md +0 -21
- package/codex-skills/optimize/SKILL.md +0 -18
- package/codex-skills/research/SKILL.md +0 -18
- /package/commands/{knowledge-review.md → review-knowledge.md} +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Agent Surface Policy
|
|
2
|
+
|
|
3
|
+
Build Loop keeps one user-facing Codex entrypoint while preserving the richer
|
|
4
|
+
Claude Code skill tree for hosts that can route helpers internally.
|
|
5
|
+
|
|
6
|
+
## Public Entry Points
|
|
7
|
+
|
|
8
|
+
Codex must expose exactly one user-facing Build Loop choice:
|
|
9
|
+
|
|
10
|
+
- `build-loop` — main workflow and router for build, fix, debug, optimize,
|
|
11
|
+
research, knowledge capture, handoff, and plugin-test work
|
|
12
|
+
|
|
13
|
+
Claude Code may expose advanced direct overrides in its command/skill surface
|
|
14
|
+
where useful:
|
|
15
|
+
|
|
16
|
+
- `build-loop`
|
|
17
|
+
- `debug-loop`
|
|
18
|
+
- `optimize`
|
|
19
|
+
- `research`
|
|
20
|
+
- `knowledge`
|
|
21
|
+
- `handoff`
|
|
22
|
+
|
|
23
|
+
## Host Rules
|
|
24
|
+
|
|
25
|
+
Codex and ChatGPT install from `plugin-artifacts/codex`, not from the source
|
|
26
|
+
repo root. Codex auto-discovers root `skills/*/SKILL.md` files and manifest
|
|
27
|
+
skill paths supplement that default, so installing the source root leaks every
|
|
28
|
+
internal helper into the picker. The artifact is generated by:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python3 scripts/build_codex_plugin_artifact.py --source . --target plugin-artifacts/codex
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The artifact contains one `skills/build-loop/SKILL.md` copied from the
|
|
35
|
+
canonical workflow and `.codex-plugin/plugin.json` rewritten to
|
|
36
|
+
`"skills": "./skills"`. It must not contain any other `SKILL.md` files.
|
|
37
|
+
|
|
38
|
+
The local Codex marketplace (`.agents/plugins/marketplace.json`) points at this
|
|
39
|
+
artifact. Release and marketplace updates must do the same.
|
|
40
|
+
|
|
41
|
+
Claude Code keeps `.claude-plugin/plugin.json` pointed at `./skills` because
|
|
42
|
+
commands and orchestrator agents load internal skills by qualified name. Helper
|
|
43
|
+
skills must set `user-invocable: false`; the public entrypoints set
|
|
44
|
+
`user-invocable: true`.
|
|
45
|
+
|
|
46
|
+
Cursor and other AGENTS.md-style tools should treat `AGENTS.md` plus this file
|
|
47
|
+
as the routing contract. Start from `build-loop`. Read helper files under
|
|
48
|
+
`skills/` only when the active entrypoint, a command, or an orchestrator
|
|
49
|
+
instruction explicitly references them.
|
|
50
|
+
|
|
51
|
+
## Cache Hygiene
|
|
52
|
+
|
|
53
|
+
Plugin cache pruning is explicit and auditable:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm run codex:sync-cache
|
|
57
|
+
python3 scripts/prune_plugin_cache.py --source . --apply
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`npm run codex:sync-cache` rebuilds the slim artifact first, then syncs that
|
|
61
|
+
artifact into the Codex cache. The prune command keeps the current host manifest
|
|
62
|
+
version and deletes older verified cache directories for the same plugin. Use
|
|
63
|
+
`--host codex` or `--host claude` for a single host.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
|
|
3
|
+
# Advisor dispatch ladder (Phase 2 plan synthesis at Frontier)
|
|
4
|
+
|
|
5
|
+
The Advisor (Fable) is the Frontier standing role that **authors and re-plans** the Phase 2 plan synthesis. Generating a plan is harder than evaluating one, so the deepest reasoning pays here — but the Advisor is **pull-based**: summoned only when stakes-gating trips, not every run. This ladder enforces that the plan is authored at Frontier *when it matters*, without breaking the runs where it doesn't.
|
|
6
|
+
|
|
7
|
+
It deliberately **mirrors the GAP-1 independent-auditor ladder** (`phase-4-review.md` §"Sub-step A"). Same shape, same honesty discipline, an analogous `advisor_status` field. If you know that ladder, you know this one.
|
|
8
|
+
|
|
9
|
+
## When the ladder is evaluated (stakes-gating)
|
|
10
|
+
|
|
11
|
+
The orchestrator walks this ladder at the Phase 2 plan-synthesis step **only when** any of these objective triggers fire:
|
|
12
|
+
|
|
13
|
+
- `state.json.synthesisDensity > 5` (synthesis-dense plan), or
|
|
14
|
+
- `triggers.riskSurfaceChange` (security/persistence/runtime/deploy/trust boundary), or
|
|
15
|
+
- `stakes >= medium` (from the commander's-intent posture / charter), or
|
|
16
|
+
- an explicit `dispatch_tier: frontier` on any work item in the draft plan.
|
|
17
|
+
|
|
18
|
+
If none trips, the ladder is skipped entirely — the orchestrator synthesizes the plan inline as today (most runs stay single-context; this respects the multi-agent-handoff risk by not decomposing more than needed). **Triggers are objective signals, never self-reported confidence** (models are systematically overconfident).
|
|
19
|
+
|
|
20
|
+
## The four rungs (record `advisor_status` honestly)
|
|
21
|
+
|
|
22
|
+
Dispatching the Advisor via `Agent(subagent_type="build-loop:advisor")` requires the Agent tool. A *nested* orchestrator (dispatched as a subagent — Mode B — or running per-commit mode) does **not** have the Agent tool, because the harness blocks sub-subagents. Walk the ladder and record `advisor_status`:
|
|
23
|
+
|
|
24
|
+
1. **Rung 0 — own context already Frontier** (the orchestrator is itself running on Fable, e.g. `/build-loop:run` while the session model is Fable): **synthesize the plan inline** — it is *already* Frontier, no handoff needed. → `advisor_status: inline-frontier`. Zero added cost.
|
|
25
|
+
|
|
26
|
+
2. **Rung 1 — Agent tool present** (top-level / Mode A, own context not already Frontier): **dispatch the Fable Advisor** (`Agent(subagent_type="build-loop:advisor")`) to author/re-plan, then verify via plan-critic + scope-auditor. → `advisor_status: ran:dispatched-agent`.
|
|
27
|
+
|
|
28
|
+
3. **Rung 2 — no Agent tool, peer host reachable** (nested Mode B, but a peer host — rally channel / `codex exec` — can execute; reachable because the orchestrator retains Bash even when nested): **run the Advisor as a peer process** over the same channel the cross-vendor reviewer uses. Reconcile the peer's plan + envelope into the plan artifact. → `advisor_status: ran:peer-host(<host>)`. Prefer this over the fallback whenever a peer host can execute (fresh-context synthesis is plausibly *higher quality*, not merely cheaper — see "Quality, not only cost" below).
|
|
29
|
+
|
|
30
|
+
4. **Rung 3 — none reachable** (no Agent tool, no peer host): **synthesize inline on the orchestrator's own model (Opus)**, labeled honestly. → `advisor_status: fallback:inline-opus`.
|
|
31
|
+
|
|
32
|
+
## Non-breaking guarantee
|
|
33
|
+
|
|
34
|
+
**Rung 3 IS today's behavior** — the orchestrator synthesizing the plan inline on Opus. The floor of this ladder equals the current state; it is strictly better whenever a dispatch path (Rung 1/2) or an already-Frontier context (Rung 0) is reachable. The handoff cost fires *only* in Rung 1/2 — i.e., only when the active context isn't already Frontier — so you pay it exactly where it buys an upgrade and never where planning is already Frontier. Worst case equals current; there is no regression path.
|
|
35
|
+
|
|
36
|
+
## Quality, not only cost
|
|
37
|
+
|
|
38
|
+
Dispatch is a **quality lever**, not just a cost knob. Context-separation evidence (⚠️ 2026 cross-context-review lead, directionally consistent with the corroborated self-correction literature: correction needs *external* feedback; intrinsic self-correction degrades accuracy) indicates synthesis in a *fresh* context beats same-session work. So Rungs 1/2 (fresh-context dispatch) are plausibly *higher quality* than Rung 0/3 inline — inline is a genuine quality compromise, taken only when dispatch is unreachable. The Advisor is a **separate agent**, never the executor self-reflecting.
|
|
39
|
+
|
|
40
|
+
## Ledger row per Advisor action (the instrument)
|
|
41
|
+
|
|
42
|
+
The orchestrator (single writer) appends one row to `.build-loop/agent-ledger.jsonl` per Advisor action via `scripts/agent_ledger.py`:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
action: author | re-plan
|
|
46
|
+
agent: advisor · tier: frontier · model: <resolved id (fable / gpt-5.x / …)>
|
|
47
|
+
rung: 0|1|2|3 · status: pass|fail|partial · trigger: <synthesisDensity>5 | riskSurfaceChange | stakes>=medium | dispatch_tier:frontier>
|
|
48
|
+
refs: {output: docs/plans/<slug>.md, input: <prior plan / failure evidence>}
|
|
49
|
+
note: <on re-plan: failure evidence + why a retry is justified>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This closes the unmeasured quality-delta: the A/B test reads the ledger to compare plan outcomes by `rung`/`model` and find whether Frontier planning actually pays.
|
|
53
|
+
|
|
54
|
+
## Re-plan mode (the remediation contract, v1)
|
|
55
|
+
|
|
56
|
+
When the orchestrator diagnoses a **planning miss** during Iterate (the plan itself no longer fits, on an objective signal — test/build failure, auditor verdict, retry-count, scope breach), it re-enters this ladder with `action: re-plan`. The Advisor reads the **failure evidence + the diff vs the current plan**, diagnoses planning-miss vs execution-miss (*its* Frontier call, never the failing executor's self-report), and on a planning miss issues **corrected instructions** — a diff against the prior plan + the evidence — so execution resumes at the cheap tier on a sound plan.
|
|
57
|
+
|
|
58
|
+
**v1 scope:** author + re-plan only. The **take-over-execution rung** (the Advisor executing a chunk directly) and **proactive mid-run checkpoint check-ins** are **v2** — land after the A/B confirms the core pays.
|
|
59
|
+
|
|
60
|
+
## Always verified — never self-certifying
|
|
61
|
+
|
|
62
|
+
The Advisor's authored/re-planned plan is checked by the existing Frontier critics before any implementer runs: `plan_verify.py` (deterministic) → `plan-critic` (reasoning; **blocking on the same stakes triggers**, advisory otherwise) → `scope-auditor` at the Plan→Execute boundary. Frontier-authored output does not get a pass on review. Keep the verification panel multi-specialist — do not collapse it to a single judge.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
|
|
3
|
+
# Agent Role Taxonomy
|
|
4
|
+
|
|
5
|
+
This reference answers two recurring coordination questions:
|
|
6
|
+
|
|
7
|
+
1. Who is lead?
|
|
8
|
+
2. Is a "coder", "backend", or "database" entity an agent, a skill, or a task role?
|
|
9
|
+
|
|
10
|
+
Use this doc with `references/model-tier-mapping.md`: this file defines
|
|
11
|
+
responsibility boundaries, while model-tiering defines the model class used for
|
|
12
|
+
each role.
|
|
13
|
+
|
|
14
|
+
## Binding Rule
|
|
15
|
+
|
|
16
|
+
The lead is the session holding the current valid Rally Point leadership lease.
|
|
17
|
+
It is not a hardcoded tool name, default UI label, or mock value. If no valid
|
|
18
|
+
lease exists, the first active orchestrator that claims the lease becomes lead
|
|
19
|
+
until it transfers, relinquishes, or expires.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
python3 scripts/agent_rally.py lead status --workdir "$PWD" --json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
When the displayed lead conflicts with the live lease, trust the live lease and
|
|
26
|
+
file the display as a Rally Point bug.
|
|
27
|
+
|
|
28
|
+
## Roles
|
|
29
|
+
|
|
30
|
+
| Role | Current surface | Default tier | Owns | Must not own |
|
|
31
|
+
|---|---|---:|---|---|
|
|
32
|
+
| Human/operator | User prompt and explicit gates | n/a | Goal, production push approval, irreversible delete approval, major user-impact decisions | Routine commit cadence, reversible implementation choices |
|
|
33
|
+
| Lead orchestrator | `agents/build-orchestrator.md`; Rally Point leadership lease | Thinking | Run plan, phase transitions, ownership partition, dispatch, final judgment, commits, release/report | Pretending peer handoffs are approval, ignoring stale/off-task peers |
|
|
34
|
+
| Peer host/session | Rally Point presence/inbox/handoff | Host-selected | Its claimed lane, verdicts, handoffs, review requests | Files claimed by another active peer, silent lead takeover |
|
|
35
|
+
| Coder subagent | `agents/implementer.md` | Code | Bounded implementation against owned files and a written spec | Architecture expansion, git staging/commit/push, cross-lane cleanup |
|
|
36
|
+
| Domain assessor | `agents/database-assessor.md`, `api-assessor.md`, `frontend-assessor.md`, `performance-assessor.md` | Code or Thinking by complexity | Diagnosis and evidence in one domain | Shipping code by default; use implementer for the fix |
|
|
37
|
+
| Architecture/scope specialist | `architecture-scout`, `scope-auditor`, architecture skills | Thinking | Blast-radius tracing, caller impact, scope gaps | Applying the fix after finding the gap |
|
|
38
|
+
| Reviewer/auditor | `independent-auditor`, `security-reviewer`, `plan-critic`, `fix-critique`, `synthesis-critic` | Code or Thinking by rubric/judgment mix | Read-only challenge, risk ranking, verdicts | Mutating code under review |
|
|
39
|
+
| UI/design specialist | `design-contract-specialist`, `ui-validator`, `ui-design` skill | Code or Thinking by task | UI contract, visual validation, design direction | Business logic outside the UI contract |
|
|
40
|
+
| Retrospective/learning agent | `retrospective-synthesizer`, `recurring-pattern-detector`, `self-improvement-architect` | Pattern to Thinking | Pattern extraction, proposals, lessons | Silent promotion of new enforcement |
|
|
41
|
+
| Skill | `skills/*/SKILL.md` | n/a | Procedural guidance, routing rules, references, scripts | Acting as a live worker or owner |
|
|
42
|
+
| Script/tool | `scripts/*` | n/a | Deterministic checks, writes, summaries | Making LLM judgment calls unless explicitly wrapped by an agent |
|
|
43
|
+
|
|
44
|
+
## Coder vs Backend/Database Agent
|
|
45
|
+
|
|
46
|
+
Build-loop already has a dedicated coder subagent: `implementer`. Do not add a
|
|
47
|
+
separate generic `coder` agent unless evidence shows agents or users repeatedly
|
|
48
|
+
miss that `implementer` is the coding role.
|
|
49
|
+
|
|
50
|
+
For backend/database work:
|
|
51
|
+
|
|
52
|
+
1. Use the domain assessor when the problem is diagnostic or cross-layer:
|
|
53
|
+
`database-assessor`, `api-assessor`, `performance-assessor`, or
|
|
54
|
+
`assessment-orchestrator`.
|
|
55
|
+
2. Use `implementer` when the fix is scoped to owned files and the "what" is
|
|
56
|
+
decided.
|
|
57
|
+
3. Escalate to `scope-auditor` or `architecture-scout` when a persistence,
|
|
58
|
+
schema, API, or data-contract boundary might widen the blast radius.
|
|
59
|
+
|
|
60
|
+
This keeps roles MECE: assessors diagnose, implementer edits, reviewers judge,
|
|
61
|
+
and the lead orchestrator commits.
|
|
62
|
+
|
|
63
|
+
## Lead Responsibilities
|
|
64
|
+
|
|
65
|
+
The lead orchestrator must:
|
|
66
|
+
|
|
67
|
+
- Claim or verify the leadership lease at Phase 1 and renew it at phase starts.
|
|
68
|
+
- Keep Rally Point status/watch active when peers, inbox items, or an active
|
|
69
|
+
coord file exist.
|
|
70
|
+
- Write task heartbeats for long-running work and pass `--task-ref` into
|
|
71
|
+
status/watch.
|
|
72
|
+
- Assign exactly one owner per file/chunk before dispatch.
|
|
73
|
+
- Dispatch subagents by role, not by vague labels like "backend agent" unless
|
|
74
|
+
the role maps to one of the surfaces above.
|
|
75
|
+
- Remain the single writer to `.git/`; subagents return envelopes, not commits.
|
|
76
|
+
- Decide routine reversible choices under `references/leadership.md`.
|
|
77
|
+
|
|
78
|
+
## Peer Responsibilities
|
|
79
|
+
|
|
80
|
+
Every peer host/session must:
|
|
81
|
+
|
|
82
|
+
- Use a stable `tool` id (`claude_code`, `codex`, `cursor`, etc.).
|
|
83
|
+
- Publish presence and lane ownership before mutating shared files.
|
|
84
|
+
- Read direct and broadcast inbox messages before acting on a handoff preview.
|
|
85
|
+
- Post verdicts or handoffs through Rally Point, not only terminal prose.
|
|
86
|
+
- Use `heartbeat --task-ref` during long-running tasks so other sessions can
|
|
87
|
+
distinguish "process alive" from "still on task".
|
|
88
|
+
|
|
89
|
+
## Core vs Sub-Agent — the classification rule
|
|
90
|
+
|
|
91
|
+
External analyses tend to classify by model tier ("`model: fable` ⇒ core") or by
|
|
92
|
+
blocking power ("core agents halt the loop"). Both are wrong as definitions:
|
|
93
|
+
|
|
94
|
+
- **Core = produces a verdict some pipeline step is contingent on.** The
|
|
95
|
+
independent-auditor's `nay`, plan-verify's blocking findings, and
|
|
96
|
+
`judgment_gate`'s `fail` gate specific steps; that contingency is what makes
|
|
97
|
+
the role core. Most Frontier critics are advisory by charter
|
|
98
|
+
(synthesis-critic is WARN-only, alignment-checker never blocks) — high tier,
|
|
99
|
+
not core. "Can halt the loop" misclassifies: build-loop verdicts gate steps;
|
|
100
|
+
they never hard-halt the loop outside the defined stop conditions.
|
|
101
|
+
- **Tier follows role, never the reverse.** The role's responsibility row
|
|
102
|
+
(above) plus `references/model-tier-mapping.md` selects the tier. A future
|
|
103
|
+
re-tiering (e.g., a cheaper model clearing the Frontier contract) must not
|
|
104
|
+
reclassify an agent's authority.
|
|
105
|
+
|
|
106
|
+
## Delegation depth is a security property
|
|
107
|
+
|
|
108
|
+
The no-sub-sub-agents rule (subagents never dispatch agents) is not just
|
|
109
|
+
context hygiene: it caps the delegation chain at depth 2
|
|
110
|
+
(orchestrator → worker). Enterprise NHI guidance flags 3–5-hop delegation
|
|
111
|
+
chains as the silent-privilege-escalation surface; build-loop designs that
|
|
112
|
+
class out structurally. Treat any proposal to let a subagent dispatch
|
|
113
|
+
(including "just this once" orchestration conveniences) as a security-surface
|
|
114
|
+
change → `triggers.riskSurfaceChange: true`, security-reviewer in scope.
|
|
115
|
+
|
|
116
|
+
The one sanctioned agent-initiated escalation is `status: blocked` +
|
|
117
|
+
`novel_decisions[]` (the C5 backstop) — build-loop's handoff *detection phase*.
|
|
118
|
+
A worker that detects out-of-scope work returns it for routing; it never
|
|
119
|
+
self-routes. Keep C5 healthy instead of adding peer-to-peer routing fabric;
|
|
120
|
+
recovery from failed handoffs likewise stays centralized in the orchestrator's
|
|
121
|
+
status-routing + stuck-cascade, never per-worker.
|
|
122
|
+
|
|
123
|
+
## When To Add A New Agent
|
|
124
|
+
|
|
125
|
+
Add a new agent only when all are true:
|
|
126
|
+
|
|
127
|
+
1. The task repeats across builds.
|
|
128
|
+
2. The task has a stable input/output envelope.
|
|
129
|
+
3. The responsibility is not already owned by one row above.
|
|
130
|
+
4. A skill or script cannot express the behavior cleanly.
|
|
131
|
+
5. Verification can check the output before the orchestrator accepts it.
|
|
132
|
+
|
|
133
|
+
If the need is "teach agents how to do X", add or update a skill/reference. If
|
|
134
|
+
the need is "perform X repeatedly with a bounded contract", add an agent. If
|
|
135
|
+
the need is "compute X deterministically", add a script.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
# Autonomous Mode + Per-Commit Mode (conditional detail)
|
|
4
|
+
|
|
5
|
+
Extracted from `SKILL.md` (WP-A, 2026-06-09): both modes are conditional — their
|
|
6
|
+
tables and contracts are load-bearing only when the mode is active, yet they
|
|
7
|
+
loaded in every session. The SKILL.md body now carries a one-line pointer to
|
|
8
|
+
each; the full detail lives here and loads on demand.
|
|
9
|
+
|
|
10
|
+
## Autonomous Mode (Queue-Drain Loop)
|
|
11
|
+
|
|
12
|
+
Autonomous mode generalizes Phase 5 Iterate into a self-replenishing worker that drains its own `ux-queue/` + `issues/` + `proposals/`, alignment-checks each item against the original intent, executes the aligned subset, and commits in batches until the queue is empty or the wall-clock budget elapses. Default since this mode shipped (`--autonomous=false` opts back to classic one-pass).
|
|
13
|
+
|
|
14
|
+
**End-of-run backlog/issues drain — SHIPPED DEFAULT 2026-06-04**: every run now auto-drains `.build-loop/issues/` then `.build-loop/backlog/` at end-of-thread without asking. Reversible per-repo via `.build-loop/config.json`:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{ "sessionPrefs": { "continueFromQueues": "never" } }
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`PRODUCTION`/`DECISION`-classified items still surface (not auto-executed). The continuation runs the same alignment-checker + scope-auditor + independent-auditor wiring as the in-run iterate loop. Stop conditions: iterate-cap (25 autonomous / 5 classic), budget exhausted, PRODUCTION encountered, 5 consecutive iterate failures, explicit user pause. Surfaced in the run report's `## Queue continuation` section.
|
|
21
|
+
|
|
22
|
+
### Flag surface
|
|
23
|
+
|
|
24
|
+
| Invocation | Effect |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `/build-loop:run "goal text"` | default mode, 2h budget, autonomous=true |
|
|
27
|
+
| `/build-loop:run --long "goal text"` | long mode, 8h budget |
|
|
28
|
+
| `/build-loop:run --budget 4h "goal text"` | custom budget (overrides `--long`) |
|
|
29
|
+
| `/build-loop:run --budget 30m "goal text"` | accepts `30s`, `30m`, `4h`, or bare integer seconds |
|
|
30
|
+
| `/build-loop:run --autonomous=false "goal text"` | classic single-pass; queue items become `followup/` |
|
|
31
|
+
| `/build-loop:run "overnight refactor of auth ..."` | keyword `overnight` → long mode, 8h |
|
|
32
|
+
|
|
33
|
+
**Flag precedence (strict, top wins):**
|
|
34
|
+
|
|
35
|
+
1. `--budget <duration>` — explicit duration always wins; mode tagged `custom`.
|
|
36
|
+
2. `--long` — sets mode `long`, budget 8h.
|
|
37
|
+
3. Keyword detection in goal text — only when `--long` not explicitly set.
|
|
38
|
+
4. Default — mode `default`, budget 2h, autonomous=true.
|
|
39
|
+
|
|
40
|
+
`--autonomous=false` is orthogonal: it can combine with any budget flag but disables the queue-drain loop entirely. With autonomous off, `--budget` still tracks wall-clock but the orchestrator runs classic Phase 1–6 once and reports.
|
|
41
|
+
|
|
42
|
+
### Keyword fallback
|
|
43
|
+
|
|
44
|
+
Case-insensitive whole-word match against the goal text (or `intent.update_intent`). Detection runs ONLY when `--long` is not explicit on the command line. The flag always wins over keyword inference.
|
|
45
|
+
|
|
46
|
+
| Keyword | Example phrasings |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `long` | "long refactor of …" |
|
|
49
|
+
| `long-running` | "long-running migration" |
|
|
50
|
+
| `overnight` | "overnight build" |
|
|
51
|
+
| `large-scale` | "large-scale rewrite" |
|
|
52
|
+
| `multi-day` | "multi-day backfill" |
|
|
53
|
+
|
|
54
|
+
Keyword list is configurable via `.build-loop/config.json.autonomy.keywordsLong[]`. The default list above is hard-coded in the orchestrator.
|
|
55
|
+
|
|
56
|
+
### Budget tracking
|
|
57
|
+
|
|
58
|
+
The orchestrator writes `state.execution.budget` at autonomous-mode start:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"mode": "default | long | custom",
|
|
63
|
+
"started_at": "<iso8601 UTC>",
|
|
64
|
+
"deadline_at": "<iso8601 UTC>",
|
|
65
|
+
"last_checkin_at": "<iso8601 UTC> | null",
|
|
66
|
+
"commits_since_push": 0,
|
|
67
|
+
"checkin_interval_pct": 50
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`scripts/budget_check.py` reads this block at every iterate-loop entry, every commit, and every phase boundary, returning a routing envelope (`continue | checkin | finalize_and_stop`). The script is informational — exit 0 always; sub-5ms compute.
|
|
72
|
+
|
|
73
|
+
**Resume contract**: when a budget block exists and the run resumes via `--resume <run_id>`, the orchestrator MUST reuse the original `deadline_at`. A 2h budget that crashed at 1h59m does NOT get a fresh 2h. `scripts/resume_resolver.py._resolve_budget_on_resume()` is the single source of truth for this rule and surfaces the preserved budget under `budget_resume.preserve_deadline: true`.
|
|
74
|
+
|
|
75
|
+
### Iteration caps
|
|
76
|
+
|
|
77
|
+
| Mode | Per-build cap | Per-item cap |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| Classic (autonomous=false) | 5 | n/a |
|
|
80
|
+
| Autonomous default | 25 | 3 same-verdict |
|
|
81
|
+
| Autonomous long | 25 | 3 same-verdict |
|
|
82
|
+
|
|
83
|
+
`maxIterateAttemptsAutonomous` is configurable in `.build-loop/config.json.autonomy.maxIterateAttemptsAutonomous`.
|
|
84
|
+
|
|
85
|
+
### Question timeout (autonomous auto-decide)
|
|
86
|
+
|
|
87
|
+
In autonomous / `--long` mode a question that would otherwise block on the human auto-resolves if unanswered within a window, so an unattended run never stalls. When the orchestrator surfaces such a question it states a **recommended default** + a deadline; `scripts/question_timeout.py` is consulted (e.g. on a `ScheduleWakeup` resume) and returns `answered | take_default | wait`. On `take_default` the orchestrator takes the recommended option, records it to `state.execution.autonomousDefaults[]` + `auto-decision-capture`, continues, and lists every auto-decided question in the end-of-run readback for override (prefer the reversible option when deciding).
|
|
88
|
+
|
|
89
|
+
**Never auto-resolves — waits indefinitely:** production push, destructive/irreversible delete, and anything the autonomy gate verdicts `confirm`/`block` (gates #1–#2 in `agents/build-orchestrator.md`). Only reversible / `user_impact: major` decisions (gate #3) and steering clarifications time out — the single production gate is preserved.
|
|
90
|
+
|
|
91
|
+
Config (`.build-loop/config.json.autonomy`): `questionTimeoutMinutes` (default 10), `onTimeout` (`decide_default` default | `wait`).
|
|
92
|
+
|
|
93
|
+
### Per-Phase A constraint
|
|
94
|
+
|
|
95
|
+
Phase A (current ship) wires queue drain + alignment-check + time budget. **Pushes stay manual** — `scripts/autonomous_push.py` and the K-commit batch-push policy ship in Phase B. The `should_push_now` field returned by `budget_check.py` is informational in Phase A; the orchestrator surfaces it in check-ins but does not push autonomously yet.
|
|
96
|
+
|
|
97
|
+
## Per-Commit Mode (Self-Recursive Builds)
|
|
98
|
+
|
|
99
|
+
Per-commit mode splits a multi-commit build into one independent orchestrator dispatch per commit, so each commit reviews and lands cleanly before the next one starts. It activates automatically when the working directory IS the runtime — that is, when the user is editing the build-loop plugin itself (or any plugin whose runtime symlink points back to the working tree). It can also be explicitly opted into or out of via skill arguments.
|
|
100
|
+
|
|
101
|
+
### Detection
|
|
102
|
+
|
|
103
|
+
Phase 1 Assess writes `selfRecursive.enabled: true|false` to `.build-loop/state.json` (commit 1 wired this via `scripts/detect_self_recursive.py`). The skill body MUST read this field BEFORE deciding which dispatch shape to use. If the field is absent, treat it as `false`.
|
|
104
|
+
|
|
105
|
+
### Mode Resolution
|
|
106
|
+
|
|
107
|
+
| Skill arg | `selfRecursive` | Resulting mode |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `--per-commit` (explicit) | either | per-commit |
|
|
110
|
+
| `--no-per-commit` (explicit) | either | single-orchestrator |
|
|
111
|
+
| (none) | true | per-commit (default for self-recursive) |
|
|
112
|
+
| (none) | false | single-orchestrator (today's behavior) |
|
|
113
|
+
|
|
114
|
+
Passing both `--per-commit` and `--no-per-commit` is a user error — fail loud with a one-line message naming the conflict and stop before any dispatch.
|
|
115
|
+
|
|
116
|
+
### Dispatch Contract (Per-Commit Mode)
|
|
117
|
+
|
|
118
|
+
1. **Plan first, dispatch many.** The skill body invokes a single planning orchestrator (Phase 1 Assess + Phase 2 Plan only). Its return must include a per-commit work list at `.build-loop/per-commit-plan.json` with this exact JSON shape:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"run_id": "run_<UTC>_<hash>",
|
|
123
|
+
"commits": [
|
|
124
|
+
{
|
|
125
|
+
"id": "c1",
|
|
126
|
+
"subject": "feat(scripts): add foo helper",
|
|
127
|
+
"scope": "...",
|
|
128
|
+
"files_planned": ["scripts/foo.py", "tests/test_foo.py"],
|
|
129
|
+
"spec": "verbatim packet for the implementer orchestrator",
|
|
130
|
+
"depends_on": []
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
"branch": "feat/...",
|
|
134
|
+
"from_branch": "main"
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
2. **Per-commit orchestrator dispatch.** For each commit in the plan (respecting `depends_on`), the skill body dispatches a fresh `Agent(subagent_type="build-loop:build-orchestrator", ...)` carrying ONLY that commit's packet plus a `PER_COMMIT_DISPATCH: { commit_id, run_id, prior_commit_hashes }` prompt prefix. Each dispatched orchestrator runs Phase 3 Execute + Phase 4 Review for ITS commit only, then commits and returns. The dispatched orchestrator's behavior on the prefix is documented in `agents/build-orchestrator.md` §0a.
|
|
139
|
+
|
|
140
|
+
3. **Aggregate.** The skill body collects each orchestrator's return envelope and writes a final report combining all commits' results. On partial failure (commit N fails), do NOT dispatch downstream commits; retain `.build-loop/per-commit-plan.json` so a subsequent `/build-loop:run --resume` invocation can pick up where it stopped. **Parent-dispatch contract (GAP-1):** the dispatcher (this skill body) HAS the Agent tool, so it is the parent that owes the audit. For every returned envelope whose `auditor_status` is `not-run:parent-must-dispatch` or `cross-vendor-deferred`, the dispatcher MUST — before declaring that commit/run review-complete — dispatch `Agent(subagent_type="build-loop:independent-auditor")` on that commit's diff range, append the verdict to `.build-loop/judge-decisions.json`, and re-run `write_run_entry --scope build` so the review-completeness gate passes. A nested per-commit orchestrator cannot audit itself; the audit is the dispatcher's responsibility, not an optional step.
|
|
141
|
+
|
|
142
|
+
**Parent owes Phase 6 Learn + retrospective (E3).** A stop-early dispatch that never reaches Phase 4 Review-G can't run Phase 6 Learn or the post-push retro — so the dispatching parent owes them at close, under the same parent-dispatch contract as GAP-1 (not optional, name the owner at dispatch). Full contract: `agents/build-orchestrator.md` §Phase 4 A (E3 block).
|
|
143
|
+
|
|
144
|
+
### State.json schema
|
|
145
|
+
|
|
146
|
+
The per-commit dispatcher tracks its own progress under a `perCommit` block alongside the existing `execution` block:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"perCommit": {
|
|
151
|
+
"enabled": true,
|
|
152
|
+
"mode_source": "self_recursive_default|explicit_flag|opt_out",
|
|
153
|
+
"plan_path": ".build-loop/per-commit-plan.json",
|
|
154
|
+
"completed": [{"commit_id": "c1", "hash": "abc123", "completed_at": "..."}],
|
|
155
|
+
"in_flight": "c2",
|
|
156
|
+
"queued": ["c3"]
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
M2's `execution.iterate_attempt` continues to track per-commit-orchestrator attempt counters (each dispatched orchestrator manages its own iterate counter) — do not duplicate iteration tracking inside `perCommit`.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
|
|
3
|
+
# Autonomy Gate — Configuration Reference
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
`scripts/autonomy_gate.py` is the generalized action classifier that lets Phase 4.5 Auto-Resolve drain non-destructive open items (guidance fixes, cache resyncs, lint cleanups, open-rec executions) without prompting the operator. The existing `scripts/deployment_policy.py` already handles push/deploy/release commands; this gate handles everything else, and delegates to deployment_policy when a command looks deployment-flavored. Together they form the complete autonomy boundary: deployment_policy is authoritative for deploy targets, autonomy_gate is authoritative for everything else.
|
|
8
|
+
|
|
9
|
+
## Default policy
|
|
10
|
+
|
|
11
|
+
### confirmFor — 7 built-in patterns
|
|
12
|
+
|
|
13
|
+
These patterns require operator confirmation (`exit 1`). They are active whenever a repo does NOT supply its own `confirmFor` list:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
npm publish*
|
|
17
|
+
git push --force*
|
|
18
|
+
git push * main
|
|
19
|
+
git push * master
|
|
20
|
+
production deploy*
|
|
21
|
+
DROP TABLE*
|
|
22
|
+
rm -rf /*
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Matching uses `fnmatch.fnmatch` (Unix-shell-style globs, case-insensitive).
|
|
26
|
+
|
|
27
|
+
### warnFor — empty by default (NEW)
|
|
28
|
+
|
|
29
|
+
No commands are flagged by default. Repos may add patterns to `warnFor` to observe match-rate without blocking (`exit 0`). The canonical workflow is to ship a candidate pattern as `warnFor` first, observe 10+ builds via `state.json.runs[].autonomyEvents[]`, then promote to `confirmFor` if the match-rate justifies it.
|
|
30
|
+
|
|
31
|
+
### blockFor — empty by default
|
|
32
|
+
|
|
33
|
+
No commands are hard-blocked by default. Repos may add patterns to `blockFor` to create absolute vetoes (`exit 2`).
|
|
34
|
+
|
|
35
|
+
### Boolean flags
|
|
36
|
+
|
|
37
|
+
| Flag | Default | Meaning |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `autoFixGuidance` | `true` | Phase 4.5 may auto-apply guidance-class fixes without operator confirmation |
|
|
40
|
+
| `autoExecuteOpenRecs` | `true` | Phase 4.5 may auto-execute open recommendations without operator confirmation |
|
|
41
|
+
|
|
42
|
+
These flags are read by the skill body and orchestrator (Chunks B/C). `autonomy_gate.py` surfaces them in the envelope's `flags` key but does not act on them directly.
|
|
43
|
+
|
|
44
|
+
## Repo override schema
|
|
45
|
+
|
|
46
|
+
Add an `autonomy` block to `.build-loop/config.json`:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"autonomy": {
|
|
51
|
+
"autoFixGuidance": true,
|
|
52
|
+
"autoExecuteOpenRecs": true,
|
|
53
|
+
"confirmFor": [
|
|
54
|
+
"wipe database*",
|
|
55
|
+
"reset production*"
|
|
56
|
+
],
|
|
57
|
+
"warnFor": [
|
|
58
|
+
"touch-prod-config*"
|
|
59
|
+
],
|
|
60
|
+
"blockFor": [
|
|
61
|
+
"rm -rf /"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
All five fields are optional. Omitting `confirmFor`, `warnFor`, or `blockFor` leaves the defaults active. Setting them (even to `[]`) replaces the defaults.
|
|
68
|
+
|
|
69
|
+
**Tie semantics**: when a command matches both `confirmFor` and `warnFor`, `confirmFor` wins. The stricter verdict always takes precedence.
|
|
70
|
+
|
|
71
|
+
## Replacement semantics
|
|
72
|
+
|
|
73
|
+
`confirmFor`, `warnFor`, and `blockFor` **REPLACE** the defaults — they do not extend them. This is intentional: repos that need a smaller or entirely different set of guarded commands should not be forced to fight the defaults.
|
|
74
|
+
|
|
75
|
+
To extend the defaults, copy the 7 default `confirmFor` patterns into your config and add your custom patterns alongside them:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"autonomy": {
|
|
80
|
+
"confirmFor": [
|
|
81
|
+
"npm publish*",
|
|
82
|
+
"git push --force*",
|
|
83
|
+
"git push * main",
|
|
84
|
+
"git push * master",
|
|
85
|
+
"production deploy*",
|
|
86
|
+
"DROP TABLE*",
|
|
87
|
+
"rm -rf /*",
|
|
88
|
+
"wipe database*"
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Precedence
|
|
95
|
+
|
|
96
|
+
The gate applies rules in this order, stopping at the first match:
|
|
97
|
+
|
|
98
|
+
1. **deployment_policy first** — if the command contains deploy/push/release keywords, shell out to `python3 scripts/deployment_policy.py --workdir <path> --command <command>`. Use its verdict directly. `list_source: "deployment_policy"`.
|
|
99
|
+
2. **Repo blockFor next** — if any `blockFor` glob from `.build-loop/config.json` matches the command, return `block` (`exit 2`). `list_source: "config"`.
|
|
100
|
+
3. **Repo confirmFor next** — if any `confirmFor` glob from config matches, return `confirm` (`exit 1`). `list_source: "config"`. **confirmFor wins over warnFor on a tie** — checked first.
|
|
101
|
+
4. **Repo warnFor next** — if any `warnFor` glob from config matches, return `warn` (`exit 0`). `list_source: "config"`. (NEW)
|
|
102
|
+
5. **Default confirmFor next** — if no repo `confirmFor` was provided, check the 7 default patterns. Match → `confirm` (`exit 1`). `list_source: "default"`.
|
|
103
|
+
6. **Default warnFor next** — if no repo `warnFor` was provided, check the default warn list (empty). Match → `warn` (`exit 0`). `list_source: "default"`. (NEW, no-op by default)
|
|
104
|
+
7. **Default blockFor next** — if no repo `blockFor` was provided, check the default block list (empty). Match → `block` (`exit 2`). `list_source: "default"`.
|
|
105
|
+
8. **Otherwise** — return `auto` (`exit 0`). `list_source: "default"` or `"config"` depending on whether a config file exists.
|
|
106
|
+
|
|
107
|
+
Note: repo `confirmFor`, `warnFor`, and `blockFor` only apply when explicitly set in config. If `confirmFor` is absent from config, step 3 is skipped and step 5 applies. If `confirmFor` is present (even as `[]`), step 5 is skipped entirely. Same logic applies to `warnFor` (step 4 vs step 6) and `blockFor` (step 2 vs step 7).
|
|
108
|
+
|
|
109
|
+
## Relationship to deployment_policy.py
|
|
110
|
+
|
|
111
|
+
`deployment_policy.py` is the canonical gate for push/deploy commands. It understands deployment targets (preview, testflight, production, unknown) and repo-level target policies. `autonomy_gate.py` delegates to it rather than duplicating that logic.
|
|
112
|
+
|
|
113
|
+
`autonomy_gate.py` generalizes for everything else: lint fixes, cache ops, open-rec execution, guidance application, and any other non-deploy action the orchestrator may want to auto-execute. It also delegates to deployment_policy when it detects deployment-flavored keywords.
|
|
114
|
+
|
|
115
|
+
Do not modify deployment_policy.py to handle non-deploy actions. The two scripts are intentionally decoupled; autonomy_gate calls deployment_policy as a subprocess.
|
|
116
|
+
|
|
117
|
+
## Usage from skill body / orchestrator
|
|
118
|
+
|
|
119
|
+
### Human-readable output (default)
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
python3 scripts/autonomy_gate.py \
|
|
123
|
+
--workdir /path/to/repo \
|
|
124
|
+
--action "cache resync" \
|
|
125
|
+
--command "rsync ... codex cache"
|
|
126
|
+
# output: auto: cache resync — no pattern matched; safe to execute
|
|
127
|
+
# exit: 0
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### JSON envelope (for machine consumers)
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
python3 scripts/autonomy_gate.py \
|
|
134
|
+
--workdir /path/to/repo \
|
|
135
|
+
--action "npm publish" \
|
|
136
|
+
--command "npm publish" \
|
|
137
|
+
--json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Output:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"action": "confirm",
|
|
145
|
+
"matched_rule": "npm publish*",
|
|
146
|
+
"list_source": "default",
|
|
147
|
+
"reason": "matched default confirmFor pattern",
|
|
148
|
+
"label": "npm publish",
|
|
149
|
+
"command": "npm publish",
|
|
150
|
+
"flags": {
|
|
151
|
+
"autoFixGuidance": true,
|
|
152
|
+
"autoExecuteOpenRecs": true
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Exit code mapping (mirror of deployment_policy.py)
|
|
158
|
+
|
|
159
|
+
| Exit code | Meaning |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `0` | `auto` — safe to execute without operator input |
|
|
162
|
+
| `0` | `warn` — safe to execute; flagged for match-rate tracking (NEW) |
|
|
163
|
+
| `1` | `confirm` — operator must approve before proceeding |
|
|
164
|
+
| `2` | `block` — do not execute under any circumstance |
|
|
165
|
+
|
|
166
|
+
### Consuming in a shell script
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
python3 scripts/autonomy_gate.py \
|
|
170
|
+
--workdir "$WORKDIR" \
|
|
171
|
+
--action "$ACTION_LABEL" \
|
|
172
|
+
--command "$COMMAND" \
|
|
173
|
+
--json > /tmp/gate_result.json
|
|
174
|
+
exit_code=$?
|
|
175
|
+
action=$(python3 -c "import json,sys; print(json.load(open('/tmp/gate_result.json'))['action'])")
|
|
176
|
+
|
|
177
|
+
case $exit_code in
|
|
178
|
+
0)
|
|
179
|
+
if [ "$action" = "warn" ]; then
|
|
180
|
+
echo "[warn] Executing (flagged): $ACTION_LABEL"
|
|
181
|
+
else
|
|
182
|
+
echo "Auto-executing: $ACTION_LABEL"
|
|
183
|
+
fi ;;
|
|
184
|
+
1) echo "Needs confirmation: $ACTION_LABEL" ; exit 1 ;;
|
|
185
|
+
2) echo "BLOCKED: $ACTION_LABEL" ; exit 2 ;;
|
|
186
|
+
esac
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Reading flags from the envelope
|
|
190
|
+
|
|
191
|
+
The `flags` key surfaces the two boolean flags regardless of which rule triggered. Consumers check them before deciding whether to auto-apply guidance or open-rec items:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
import json, subprocess, sys
|
|
195
|
+
|
|
196
|
+
result = subprocess.run(
|
|
197
|
+
[sys.executable, "scripts/autonomy_gate.py",
|
|
198
|
+
"--workdir", workdir, "--action", label, "--command", cmd, "--json"],
|
|
199
|
+
capture_output=True, text=True,
|
|
200
|
+
)
|
|
201
|
+
data = json.loads(result.stdout)
|
|
202
|
+
if result.returncode == 0 and data["flags"]["autoFixGuidance"]:
|
|
203
|
+
apply_guidance_fix()
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Warn-before-block workflow
|
|
207
|
+
|
|
208
|
+
The canonical pattern for introducing new guarded patterns:
|
|
209
|
+
|
|
210
|
+
1. **Ship as `warnFor`**: add the candidate glob to `warnFor` in `.build-loop/config.json`. The gate executes the action, records it in `## Done` with a `[warn] <reason>` prefix, and appends one entry to `state.json.runs[].autonomyEvents[]`.
|
|
211
|
+
|
|
212
|
+
2. **Observe match-rate**: run ~10 builds. Inspect `autonomyEvents[]` entries for this pattern. High match-rate + never-intended-to-run = promote to `confirmFor`. Low match-rate = the pattern is too broad; refine the glob first.
|
|
213
|
+
|
|
214
|
+
3. **Promote to `confirmFor`**: move the glob from `warnFor` to `confirmFor`. From this point the gate will pause execution and route the item to `## Held` for manual operator approval.
|
|
215
|
+
|
|
216
|
+
This three-step lifecycle keeps the autonomy policy calibrated. Jumping straight to `confirmFor` with an untested glob creates friction for every legitimate execution of that command. Jumping straight to `blockFor` without data risks blocking operations that are actually safe in this repo's context.
|
|
217
|
+
|
|
218
|
+
**`autonomyEvents[]` entry shape** (one entry per `warn` verdict, appended by the orchestrator at the end of Sub-step F):
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"action": "warn",
|
|
222
|
+
"matched_rule": "<glob>",
|
|
223
|
+
"list_source": "config",
|
|
224
|
+
"label": "<action label>",
|
|
225
|
+
"command": "<full command>",
|
|
226
|
+
"run_id": "<state.json run_id>",
|
|
227
|
+
"timestamp": "<iso8601>"
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The orchestrator emits this entry. The gate script itself does not write to `state.json` — separation of concerns: gate classifies, orchestrator records.
|