@yunhozz/arc 0.1.9 → 0.2.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/MANIFEST.sha256 +109 -75
- package/README.md +19 -31
- package/claude/agents/{arc-coder.md → arc-implementer.md} +7 -7
- package/claude/agents/arc-planner.md +4 -4
- package/claude/agents/arc-qa.md +4 -4
- package/claude/agents/arc-reviewer.md +5 -5
- package/claude/agents/arc-scouter.md +3 -3
- package/claude/skill/SKILL.md +7 -7
- package/claude/skill/models.toml +3 -3
- package/claude/skill/references/commit.md +22 -7
- package/claude/skill/references/coordination.md +25 -18
- package/claude/skill/references/git-recovery.md +1 -1
- package/claude/skill/references/handoff-prep.md +25 -2
- package/claude/skill/references/handoff.md +116 -24
- package/claude/skill/references/planning.md +78 -22
- package/claude/skill/references/verification.md +155 -17
- package/claude/skill/runtime/acceptance.mjs +68 -0
- package/claude/skill/runtime/assignment.mjs +42 -0
- package/claude/skill/runtime/bootstrap.mjs +35 -0
- package/claude/skill/runtime/cli.mjs +8 -0
- package/claude/skill/runtime/command.mjs +21 -0
- package/claude/skill/runtime/cooperative-schema.mjs +55 -0
- package/claude/skill/runtime/cooperative.mjs +136 -0
- package/claude/skill/runtime/evaluate.mjs +40 -4
- package/claude/skill/runtime/external.mjs +51 -0
- package/claude/skill/runtime/gate.mjs +7 -7
- package/claude/skill/runtime/git-evidence.mjs +46 -0
- package/claude/skill/runtime/operations.mjs +2 -2
- package/claude/skill/runtime/role-policy.json +64 -19
- package/claude/skill/runtime/schema.mjs +1 -0
- package/claude/skill/runtime/scope.mjs +36 -0
- package/claude/skill/runtime/store.mjs +25 -4
- package/claude/skill/runtime/verification.mjs +123 -0
- package/claude/skill/scripts/model_config.py +2 -2
- package/codex/agents/{arc-coder.toml → arc-implementer.toml} +8 -8
- package/codex/agents/arc-planner.toml +6 -6
- package/codex/agents/arc-qa.toml +6 -6
- package/codex/agents/arc-reviewer.toml +6 -6
- package/codex/agents/arc-scouter.toml +5 -5
- package/codex/skill/SKILL.md +9 -9
- package/codex/skill/models.toml +3 -3
- package/codex/skill/references/commit.md +23 -8
- package/codex/skill/references/coordination.md +25 -18
- package/codex/skill/references/git-recovery.md +2 -2
- package/codex/skill/references/handoff-prep.md +25 -2
- package/codex/skill/references/handoff-worktree.md +4 -4
- package/codex/skill/references/handoff.md +126 -34
- package/codex/skill/references/planning.md +81 -23
- package/codex/skill/references/verification.md +160 -22
- package/codex/skill/runtime/acceptance.mjs +68 -0
- package/codex/skill/runtime/assignment.mjs +42 -0
- package/codex/skill/runtime/bootstrap.mjs +35 -0
- package/codex/skill/runtime/cli.mjs +8 -0
- package/codex/skill/runtime/command.mjs +21 -0
- package/codex/skill/runtime/cooperative-schema.mjs +55 -0
- package/codex/skill/runtime/cooperative.mjs +136 -0
- package/codex/skill/runtime/evaluate.mjs +40 -4
- package/codex/skill/runtime/external.mjs +51 -0
- package/codex/skill/runtime/gate.mjs +7 -7
- package/codex/skill/runtime/git-evidence.mjs +46 -0
- package/codex/skill/runtime/operations.mjs +2 -2
- package/codex/skill/runtime/role-policy.json +64 -19
- package/codex/skill/runtime/schema.mjs +1 -0
- package/codex/skill/runtime/scope.mjs +36 -0
- package/codex/skill/runtime/store.mjs +25 -4
- package/codex/skill/runtime/verification.mjs +123 -0
- package/codex/skill/scripts/model_config.py +3 -3
- package/lib/cli/postinstall.mjs +3 -16
- package/lib/cli/root.mjs +8 -18
- package/lib/cli/upgrade.mjs +1 -57
- package/lib/installer/manifest.mjs +7 -2
- package/lib/installer/plan.mjs +27 -13
- package/lib/installer/runtime-assets.mjs +25 -0
- package/lib/installer/shell-completion.mjs +15 -20
- package/lib/installer/targets.mjs +1 -1
- package/lib/installer/uninstall.mjs +5 -1
- package/lib/installer/upgrade-state.mjs +2 -2
- package/lib/installer/upgrade.mjs +2 -5
- package/lib/management/operations.mjs +39 -0
- package/lib/management/status.mjs +18 -0
- package/lib/management/update.mjs +58 -0
- package/lib/management/workflow.mjs +51 -0
- package/lib/models/config.mjs +1 -1
- package/lib/models/profiles.mjs +1 -1
- package/lib/policy/placement.mjs +6 -6
- package/lib/policy/render.mjs +3 -3
- package/lib/policy/role-policy.json +64 -19
- package/lib/release/artifact.mjs +1 -1
- package/lib/runtime/acceptance.mjs +68 -0
- package/lib/runtime/assignment.mjs +42 -0
- package/lib/runtime/bootstrap.mjs +35 -0
- package/lib/runtime/cli.mjs +8 -0
- package/lib/runtime/command.mjs +21 -0
- package/lib/runtime/cooperative-schema.mjs +55 -0
- package/lib/runtime/cooperative.mjs +136 -0
- package/lib/runtime/evaluate.mjs +40 -4
- package/lib/runtime/external.mjs +51 -0
- package/lib/runtime/gate.mjs +7 -7
- package/lib/runtime/git-evidence.mjs +46 -0
- package/lib/runtime/operations.mjs +2 -2
- package/lib/runtime/schema.mjs +1 -0
- package/lib/runtime/scope.mjs +36 -0
- package/lib/runtime/store.mjs +25 -4
- package/lib/runtime/verification.mjs +123 -0
- package/lib/tui/app.mjs +41 -0
- package/lib/tui/render.mjs +21 -0
- package/lib/tui/setup.mjs +20 -0
- package/lib/tui/terminal.mjs +71 -0
- package/lib/tui/workflow.mjs +12 -0
- package/package.json +1 -1
- package/scripts/postinstall.mjs +1 -3
- package/scripts/update-runtime-assets.mjs +6 -1
- package/lib/cli/choices.mjs +0 -47
- package/lib/cli/completion.mjs +0 -55
- package/lib/cli/index.mjs +0 -55
- package/lib/cli/preset.mjs +0 -29
- package/lib/cli/terminal.mjs +0 -19
- package/lib/cli/uninstall.mjs +0 -17
|
@@ -42,7 +42,7 @@ and records the actual absolute workspace/repository, branch or detached HEAD, H
|
|
|
42
42
|
explicit choice and preparation evidence, and absolute document paths inside that target. Planner drafts for that
|
|
43
43
|
verified workspace; Orchestrator saves directly in the selected target. Missing or mismatched evidence stops the
|
|
44
44
|
affected drafting or save and is reported to Orchestrator. Planned scope and paths do not establish actual preparation.
|
|
45
|
-
Initial target preparation does not authorize
|
|
45
|
+
Initial target preparation does not authorize Implementer; the complete handoff gate still applies.
|
|
46
46
|
|
|
47
47
|
Orchestrator classifies scope before implementation. The Orchestrator direct path for small tasks is defined only in
|
|
48
48
|
[handoff](handoff.md#orchestrator-direct-path-for-small-tasks); follow it there and stop and reclassify if scope or risk changes.
|
|
@@ -75,6 +75,15 @@ Initial design, required spec approval, and formal plan drafting/approval remain
|
|
|
75
75
|
Allow additional Planner calls for substantive omissions or user-approved scope/evidence changes. There is no fixed
|
|
76
76
|
call cap; never accept an incomplete draft to minimize calls. Do not add call-count conditions to Planner profiles.
|
|
77
77
|
|
|
78
|
+
The complete initial brief identifies original user requirements, criteria IDs, approved decisions and open decisions;
|
|
79
|
+
current behavior and connected source, generated, runtime, installer and documentation surfaces; conflicting rules and
|
|
80
|
+
resolution direction; exact current-stage deliverable and absolute output path. Keep the shared brief's fixed field order
|
|
81
|
+
in [coordination](coordination.md). Link accessible evidence and needed ranges instead of full dialogue or raw logs.
|
|
82
|
+
Consolidated feedback contains changed fields only and marks remaining fields `unchanged` relative to the received brief.
|
|
83
|
+
Do not call Planner again for already resolved questions. Missing target preparation or required decisions holds formal
|
|
84
|
+
drafting; initial design proposals may still precede target selection. Written-spec approval precedes dependent plan drafting.
|
|
85
|
+
|
|
86
|
+
|
|
78
87
|
## Design path and plan depth
|
|
79
88
|
|
|
80
89
|
Record design and plan depth separately from verification risk. Risk determines checks and review, not the design path;
|
|
@@ -86,12 +95,12 @@ a bounded path or document omission does not imply low risk, and architectural d
|
|
|
86
95
|
answers/revisions, and obtains approvals; Orchestrator never runs brainstorming or writing-plans itself (SKILL.md
|
|
87
96
|
Role gate); the direct path uses only a scope record.
|
|
88
97
|
2. Spike: apply Probe scope above; distinguish probe-only authorization from a sufficiently specified combined scope.
|
|
89
|
-
Bounded: approve a short design before
|
|
90
|
-
|
|
98
|
+
Bounded: approve a short design before Implementer or an Orchestrator direct edit (Planner's design before
|
|
99
|
+
Implementer; a direct edit uses only an approved scope record). Architectural: approve the design, then Planner returns a
|
|
91
100
|
complete spec draft and self-review; Orchestrator integrates, saves (user's path or
|
|
92
101
|
`docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`), self-reviews, and obtains written-spec approval before
|
|
93
102
|
implementation planning. Planner is read-only and cannot request approval.
|
|
94
|
-
3. After approved design/spec and before
|
|
103
|
+
3. After approved design/spec and before Implementer, Orchestrator assesses plan depth separately from file count, LOC,
|
|
95
104
|
or bounded scope. Architectural work always uses `writing-plans` and a written plan approval, regardless of locality,
|
|
96
105
|
risk, or size. For Bounded work skip the plan only for one local change with no dependent stages, cross-component
|
|
97
106
|
shared state, lifecycle or integration-order concerns, and one focused verification path; otherwise require a draft.
|
|
@@ -99,9 +108,9 @@ a bounded path or document omission does not imply low risk, and architectural d
|
|
|
99
108
|
this assessment, including any Bounded written spec requirement, recorded in the brief.
|
|
100
109
|
4. Record dependencies and any plan-depth rationale in the brief. Planner returns the complete proportional plan,
|
|
101
110
|
assumptions/open decisions, verification requirements, and self-review. Orchestrator integrates, saves to the user's
|
|
102
|
-
path or `docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md`, self-reviews, and obtains plan approval before
|
|
111
|
+
path or `docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md`, self-reviews, and obtains plan approval before Implementer.
|
|
103
112
|
Planner cannot save, implement, or request approval.
|
|
104
|
-
5. Every
|
|
113
|
+
5. Every Implementer first start and restart requires all applicable approvals and the Common handoff gate (SKILL.md,
|
|
105
114
|
handoff). Non-behavior configuration/documentation may skip inapplicable design/planning stages but not the gate.
|
|
106
115
|
|
|
107
116
|
When Orchestrator's recorded plan-depth judgment requires a Bounded written spec, record that and its scope,
|
|
@@ -129,12 +138,12 @@ and approved obligations. No-change, hold, and resume follow [commit](commit.md)
|
|
|
129
138
|
|
|
130
139
|
## Dependency and readiness record
|
|
131
140
|
|
|
132
|
-
After plan approval and before the first
|
|
141
|
+
After plan approval and before the first Implementer assignment, Orchestrator records all top-level task IDs in the
|
|
133
142
|
accessible canonical handoff record, linked to the approved plan version. For each task record explicit and implicit
|
|
134
143
|
predecessors, required inputs, outputs and shared contracts, owned files, conflicting shared resources, required
|
|
135
144
|
checks/QA path, ready/held status and reasons. Record the initial ready batch and capacity/serialization reasons.
|
|
136
145
|
Analyze shared APIs, contracts, generated artifacts and resources even when tasks edit different files. Unresolved
|
|
137
|
-
shared contracts or insufficient dependency information block the affected tasks; same-file concurrent
|
|
146
|
+
shared contracts or insufficient dependency information block the affected tasks; same-file concurrent Implementer edits
|
|
138
147
|
are blocked even for different lines. Do not infer independence from file separation or plan listing order.
|
|
139
148
|
|
|
140
149
|
A task is ready only when all applicable approvals and execution preparation are complete, required inputs/contracts
|
|
@@ -142,7 +151,7 @@ are available and settled, predecessors have required evidence and Orchestrator
|
|
|
142
151
|
commits (or accepted no-change records), ownership/resources do not conflict, its required check/QA path is available,
|
|
143
152
|
and a subagent slot exists under both the configured ARC full-tree cap shared by all roles and any lower actual runtime
|
|
144
153
|
limit (see [limits](limits.md)). Report runtime limits; ARC's cap is not a claim of runtime capability. Start all ready
|
|
145
|
-
independent tasks with fresh
|
|
154
|
+
independent tasks with fresh Implementers concurrently within capacity; record each hold or serialization reason instead of
|
|
146
155
|
silently following list order. Preserve existing risk gates, risk-scaled QA/Reviewer timing and execution-target
|
|
147
156
|
restrictions.
|
|
148
157
|
|
|
@@ -190,23 +199,23 @@ Claude v1 uses the current checkout or an approved task branch there; managed wo
|
|
|
190
199
|
Normal order: initial design approval → execution-target choice → target preparation and verification →
|
|
191
200
|
formal spec drafting (when required), saving and self-review → written-spec approval → formal plan drafting
|
|
192
201
|
(when required), saving and self-review → individual plan approvals → complete applicable set → existing-commit
|
|
193
|
-
verification and one batch docs commit of remaining approved documents → final Git verification →
|
|
202
|
+
verification and one batch docs commit of remaining approved documents → final Git verification → Implementer handoff.
|
|
194
203
|
Written-spec approval precedes dependent plan drafting. On document-omission paths skip only the inapplicable document
|
|
195
|
-
steps; preserve target choice, preparation, state/ownership checks and
|
|
204
|
+
steps; preserve target choice, preparation, state/ownership checks and Implementer gates.
|
|
196
205
|
|
|
197
206
|
While documents are being written, reviewed, or approved, do not stage documents or commit planning documents.
|
|
198
207
|
Selection and initial target preparation happen before formal drafting; document completion is a staging/commit gate,
|
|
199
|
-
not an initial preparation gate. An incomplete set or missing applicable approval blocks document commit and
|
|
200
|
-
not the initial choice request. No early
|
|
208
|
+
not an initial preparation gate. An incomplete set or missing applicable approval blocks document commit and Implementer,
|
|
209
|
+
not the initial choice request. No early Implementer work is authorized by approval of only some documents.
|
|
201
210
|
|
|
202
211
|
This ARC defers the local brainstorming early spec commit: save and self-review the spec, obtain written-spec
|
|
203
212
|
approval without committing, then write and approve all plans; commit the spec only in the final batch.
|
|
204
|
-
`writing-plans` commit steps do not permit document commits during planning or start
|
|
213
|
+
`writing-plans` commit steps do not permit document commits during planning or start Implementer.
|
|
205
214
|
Do not modify external skills.
|
|
206
215
|
|
|
207
216
|
| Path | Approvals and preparation |
|
|
208
217
|
|---|---|
|
|
209
|
-
| Spike probe | Approve question, method/scope, criteria, constraints; no spec/plan forced. If
|
|
218
|
+
| Spike probe | Approve question, method/scope, criteria, constraints; no spec/plan forced. If Implementer runs the probe, pass the Common handoff gate after approval. Read-only investigation needs no gate. |
|
|
210
219
|
| Bounded, plan skipped | Approve the short design and record plan-skip criteria; select target, prepare any documents or record absence, pass the gate. |
|
|
211
220
|
| Bounded, plan required | Approve short design and every required plan; a spec only when the depth judgment requires it, approved before dependent plans. One preparation batch, then the gate. |
|
|
212
221
|
| Architectural | Approve design, then spec, then every plan; select and prepare the target before formal drafting; complete the set before batch commit, final verification, and the gate. |
|
|
@@ -215,14 +224,43 @@ Do not modify external skills.
|
|
|
215
224
|
Apply Authorization and scope above to probe-only and combined requests; preserve required design/spec/plan gates.
|
|
216
225
|
These gates add no new spec obligation for Spike, Bounded plan-skip, or non-behavior documentation/configuration paths.
|
|
217
226
|
Document omission skips only document obligations, never target choice, Git/ownership checks,
|
|
218
|
-
or handoff evidence. New scope found in planning requires reassessing the list and additional approvals before dependent drafting or commit; revised approved
|
|
219
|
-
execution (a running
|
|
220
|
-
and preparation are complete;
|
|
227
|
+
or handoff evidence. New scope found in planning requires reassessing the list and additional approvals before dependent drafting or commit; revised approved document bodies need renewed approval except mechanical execution records defined below. New scope found during implementation stops dependent
|
|
228
|
+
execution (a running Implementer stops before edits dependent on new plans) until its documents, approvals,
|
|
229
|
+
and preparation are complete. Then reflect the approved plan version in its original planning-document commit under the update contract below; never retroactively authorize work before actual approval.
|
|
230
|
+
|
|
231
|
+
## Plan updates during execution
|
|
232
|
+
|
|
233
|
+
Mechanical execution records may be recorded without new user approval: checkbox completion, actual results, evidence
|
|
234
|
+
links and task completion state that preserve the approved execution contract. Record their classification, reason and
|
|
235
|
+
actual recording time in the canonical handoff record. Required checks' removal, invented success, unsupported acceptance
|
|
236
|
+
or scope changes mixed with a completion mark are not mechanical records.
|
|
237
|
+
|
|
238
|
+
Changes to goals, task scope or boundaries, acceptance criteria, method, risk, dependencies or required verification
|
|
239
|
+
require revised-version approval before affected work. Hold affected execution, obtain necessary design/spec/plan approvals
|
|
240
|
+
in order, and complete target, ownership, checks and handoff preparation before resuming. Other approved body corrections
|
|
241
|
+
follow the document-version approval rules; classify typos, paths, commands and explanations by their semantic effect.
|
|
242
|
+
|
|
243
|
+
Both mechanical records and approved contract revisions amend the original planning-document commit at a safe checkpoint.
|
|
244
|
+
Make no separate document commit or fixup commit, including for newly approved scope. Preserve implementation task commits.
|
|
245
|
+
This history update does not make actual approval time retroactive: the latest plan in the original commit is not evidence
|
|
246
|
+
that its contents were approved from the outset. Never use rewritten history to justify work started before approval.
|
|
247
|
+
|
|
248
|
+
In the canonical handoff record preserve plan absolute/Git paths; before and after content hashes and versions; prior and
|
|
249
|
+
revised approval references and actual times; change reason and classification; affected tasks and hold/preparation/resume
|
|
250
|
+
evidence. For mechanical records explain why no new approval is needed and record the time. Preserve recoverable document
|
|
251
|
+
contents, not hashes alone, and each old-to-new SHA mapping for the original document commit and descendant task commits.
|
|
252
|
+
Do not overwrite earlier approval references or the contents they approved.
|
|
253
|
+
|
|
254
|
+
Orchestrator alone performs the safe rewrite in [handoff-prep](handoff-prep.md#execution-time-plan-amendment) and
|
|
255
|
+
[commit](commit.md#execution-time-plan-document-updates). Shared/published or unknown history, merges, unclear ownership,
|
|
256
|
+
unexpected HEAD/dirty state and replay conflicts stop affected work. No force push or fallback document commit.
|
|
257
|
+
After rewriting, connect evidence to the new state under [verification](verification.md#evidence-after-plan-history-rewrite).
|
|
258
|
+
This contract adds no Git automation, runtime enforcement, authority or exemption from required checks/QA/Reviewer gates.
|
|
221
259
|
|
|
222
260
|
## Evidence refresh and limits
|
|
223
261
|
|
|
224
262
|
Missing or mismatched evidence, unfinished approvals, unclear ownership, or unresolved failure blocks the affected save,
|
|
225
|
-
target request, Git mutation, or
|
|
263
|
+
target request, Git mutation, or Implementer handoff; Orchestrator resolves it and reverifies.
|
|
226
264
|
Reverify when scope, approved versions, paths, target, or Git state changes. Never treat an early save or commit as
|
|
227
265
|
satisfying a gate or as approval; record the actual order and gaps. Structural checks prove only the written policy,
|
|
228
266
|
not agent runtime compliance; without execution records for role returns, approvals, saves, and Git actions,
|
|
@@ -239,8 +277,26 @@ skill. Missing files stop the stage; report paths without global fallback. Keep
|
|
|
239
277
|
[ARC role policy: contract begin]
|
|
240
278
|
Generated from lib/policy/role-policy.json; do not edit this managed section manually.
|
|
241
279
|
- [git.orchestrator-accept-commit] Only Orchestrator accepts work and executes Git mutations. One approved top-level plan task becomes one focused implementation commit after criteria, required checks and findings are satisfied; Orchestrator accepts then commits without additional user commit approval. Reports, passing checks and Reviewer opinions do not replace acceptance. Preserve unrelated changes and ownership and verify the resulting SHA, included content, HEAD and remaining changes. Existing small-task direct and plan-omission paths are unchanged.
|
|
242
|
-
- [review.significant-no-plan] For significant/high-risk work without a plan:
|
|
243
|
-
- [review.significant-plan] For significant/high-risk plan work: each task uses
|
|
244
|
-
- [review.final-plan-recheck] For final overall Reviewer findings on plan work, including behavior findings, use
|
|
280
|
+
- [review.significant-no-plan] For significant/high-risk work without a plan: Implementer → QA and required QA rechecks → Reviewer of the final full change → Orchestrator acceptance. MUST NOT omit Reviewer merely because no plan exists. This creates no new plan obligation.
|
|
281
|
+
- [review.significant-plan] For significant/high-risk plan work: each task uses Implementer → fresh QA as required → Orchestrator acceptance and focused commit. After all tasks are accepted and required QA is complete, Reviewer reviews the final full change once. Reviewer is NOT a per-task or per-commit required gate. Preserve required checks and necessary finding rechecks.
|
|
282
|
+
- [review.final-plan-recheck] For final overall Reviewer findings on plan work, including behavior findings, use Implementer → Reviewer without QA reassignment; repeat until resolved. This exception applies only at the final plan stage. Preserve required QA and QA failure rechecks before initial final review and outside this exception.
|
|
283
|
+
- [planning.plan-amend] During approved task execution, mechanical plan progress records need no new user approval; changed goals, scope, criteria, method, risk, dependencies or required verification require revised-version approval and preparation before affected work. In both cases Orchestrator amends the original planning-document commit at a safe boundary, without a separate document or fixup commit. Preserve actual approval chronology, recoverable old/new contents, hashes, versions and SHA mappings; never retroactively authorize earlier work. Rewrite only unpublished, unshared local linear history with clear ownership and no merges; stop on unknown publication, ownership, unexpected state or replay conflicts, without force push or a fallback document commit. Preserve implementation task boundaries and revalidate affected evidence. See planning, handoff-prep, commit and verification for the full contract.
|
|
284
|
+
- [planning.planner-brief] Before formal drafting, Orchestrator supplies one complete stage-specific brief with original requirements and criteria IDs, approved/open decisions, verified target and ownership, document paths and preceding approved versions, current behavior and connected source/generated/runtime/installer/documentation surfaces, policy conflicts, depth, dependencies, checks, holds and exact deliverable. Preserve shared brief field order. Review the complete draft once and consolidate substantive feedback as changed fields with other fields marked unchanged. Preserve sequential design, spec and plan approvals; no fixed call cap or incomplete drafts, and no calls for already resolved questions.
|
|
245
285
|
- [platform.claude] Existing per-role tool allowlists reduce available tools; Bash and role contracts are not a filesystem sandbox. A role-scoped Git guard is a separate integration and is not supplied by these policy sections alone.
|
|
246
286
|
[ARC role policy: contract end]
|
|
287
|
+
|
|
288
|
+
## Approved cooperative execution path within the repository
|
|
289
|
+
|
|
290
|
+
The approved installed workflow entry connects document commits to the initial Implementer assignment in plan mode.
|
|
291
|
+
Resolve `<target-home>/skills/arc/runtime/cli.mjs` from the actual loaded ARC skill location selected by the installation
|
|
292
|
+
resolver, including custom homes. Invoke `node` with that path and command options as separate arguments; for shell
|
|
293
|
+
calls use `node "$ARC_RUNTIME_ENTRY" <command> --cwd "$ARC_CHECKOUT" --workflow "$ARC_WORKFLOW_ID" --input -`
|
|
294
|
+
with safely assigned, quoted values. See [handoff](handoff.md) for invocation and continuity requirements.
|
|
295
|
+
An entry update does not migrate existing state or renew approvals; runtime/target drift still requires current evidence.
|
|
296
|
+
Its scope is decisions and records within the repository's cooperative path. It adds no authority to install native hooks/providers/installers or block direct tool calls.
|
|
297
|
+
`no-plan`/omission is unsupported by this CLI, and this boundary remains in Phases 2 and 3. This does not imply an omission policy violation or a new obligation to write documents.
|
|
298
|
+
|
|
299
|
+
Orchestrator records the SHA-256 values of the user-approved spec and plan, their shared docs-only commit, document version and approval version.
|
|
300
|
+
The CLI verifies the exact changed paths in actual Git objects and the current document bytes before persisting an assignment intent.
|
|
301
|
+
A new workflow or late document commit cannot prove earlier execution was compliant. Earlier agent history and execution outside this path remain unverified.
|
|
302
|
+
Approval attestations and native returns are `operator-attested`; an agent ID is not an authenticated identity.
|
|
@@ -19,6 +19,19 @@ text presence alone cannot establish agent compliance. Distinguish tested behavi
|
|
|
19
19
|
Unexpected failures trigger diagnosis and stop dependent work; expected failure-first RED does not authorize unrelated
|
|
20
20
|
repairs.
|
|
21
21
|
|
|
22
|
+
## Evidence after plan history rewrite
|
|
23
|
+
|
|
24
|
+
After an approved execution-time plan rewrite, verify new HEAD, approved plan version/content and old-to-new SHA mapping;
|
|
25
|
+
descendant implementation content and task boundaries; and remaining staged/unstaged/untracked state. Preserve the actual
|
|
26
|
+
approval chronology and recoverable previous contents in the canonical handoff record. The latest version in the original
|
|
27
|
+
commit does not establish approval before its actual approval time.
|
|
28
|
+
|
|
29
|
+
SHA change alone does not invalidate all prior acceptance evidence. Check whether evidence bound to an exact HEAD,
|
|
30
|
+
document or policy can be linked to the new state. If it cannot be linked, or its meaning is affected, repeat affected
|
|
31
|
+
checks and required rechecks. Preserve existing runtime evidence invalidation and exact-state requirements; do not rewrite
|
|
32
|
+
old fingerprints to imply a run against the new HEAD. Refresh affected briefs and gates before dependent work.
|
|
33
|
+
Structural checks establish written-contract alignment, not live agent compliance or successful Git history replay.
|
|
34
|
+
|
|
22
35
|
## Reviewer timing and task acceptance
|
|
23
36
|
|
|
24
37
|
Task acceptance and its focused commit need only the task's risk-scaled evidence: a FRESH QA instance per task that
|
|
@@ -30,17 +43,17 @@ Reviewer reviews once on the final full change after all plan tasks are accepted
|
|
|
30
43
|
QA recheck at the final relevant state; without a plan, Reviewer follows QA before acceptance.
|
|
31
44
|
A task commit does not mark unperformed final verification complete.
|
|
32
45
|
|
|
33
|
-
Fresh-per-task rules apply to
|
|
46
|
+
Fresh-per-task rules apply to Implementer and QA, not Reviewer. Orchestrator may reuse a Reviewer only while independent
|
|
34
47
|
of implementation and self-review, relevant assignment context remains valid, and refreshed review scope, target
|
|
35
48
|
state, and evidence are provided; otherwise assign another independent Reviewer. Reusing a Reviewer does not reuse
|
|
36
49
|
an earlier verdict or waive required review timing or coverage.
|
|
37
50
|
|
|
38
51
|
For final Reviewer findings on already committed plan work, Orchestrator defines a follow-up task and required
|
|
39
|
-
planning/approvals.
|
|
52
|
+
planning/approvals. Implementer leaves corrections uncommitted during rechecks. Orchestrator refreshes the latest committed
|
|
40
53
|
state plus uncommitted diff and changed-file list in the Reviewer artifact/brief. Reuse an independent Reviewer or
|
|
41
|
-
assign another independent Reviewer as needed. Repeat
|
|
54
|
+
assign another independent Reviewer as needed. Repeat Implementer → Reviewer without QA reassignment until findings are
|
|
42
55
|
resolved; Orchestrator then accepts the corrections and creates one focused follow-up commit.
|
|
43
|
-
Final QA findings retain
|
|
56
|
+
Final QA findings retain Implementer correction and QA recheck before a new focused commit.
|
|
44
57
|
Do not automatically amend/reset or duplicate the original task commit. Scope expansion keeps existing new
|
|
45
58
|
planning and approval obligations.
|
|
46
59
|
|
|
@@ -70,19 +83,19 @@ conditions and expected result to observations. Partial confirmation, out-of-sco
|
|
|
70
83
|
environment-blocked gaps stay unverified; omit no criteria. PASS, if used, means only run status.
|
|
71
84
|
Structural checks prove structure only, not behavior, installation, or live agent compliance.
|
|
72
85
|
|
|
73
|
-
For QA execution failure or an unmet criterion within the current task, Orchestrator defaults to the current
|
|
86
|
+
For QA execution failure or an unmet criterion within the current task, Orchestrator defaults to the current Implementer
|
|
74
87
|
for correction and the current QA for a post-fix recheck, subject to the context, task-boundary and amendment rules in
|
|
75
88
|
[coordination](coordination.md). The finding alone does not create a new task. QA reruns the
|
|
76
89
|
reproduction path and invalidated related checks before Reviewer, reporting the actual actor, target state, outcomes, and limitations,
|
|
77
90
|
and the prior finding resolved, unresolved, or unverified with evidence. Reusing QA does not reuse stale evidence.
|
|
78
|
-
An unresolved finding returns to
|
|
91
|
+
An unresolved finding returns to Implementer correction and another QA recheck before Reviewer.
|
|
79
92
|
Environment blocks, missing checks, and out-of-scope criteria are evidence gaps, not presumed defects;
|
|
80
93
|
Reviewer does not substitute for QA evidence. Outside the required final plan correction loop,
|
|
81
94
|
Orchestrator decides when a Reviewer recheck is warranted by the changed scope and independence.
|
|
82
95
|
|
|
83
96
|
For an acceptance-linked finding Reviewer reports criterion, expected behavior, observed problem, related source,
|
|
84
97
|
reproduction conditions and steps, and evidence, labeling each source-inferred or execution-observed,
|
|
85
|
-
without running QA tests. Outside the final plan Reviewer correction exception, Orchestrator routes it to
|
|
98
|
+
without running QA tests. Outside the final plan Reviewer correction exception, Orchestrator routes it to Implementer and QA recheck. Reviewer still handles structure, design,
|
|
86
99
|
factual, and security findings; observable security/interface issues may need both QA and Reviewer.
|
|
87
100
|
|
|
88
101
|
Orchestrator accepts using verdicts, findings, rechecks, and remaining gaps, not an overall run result;
|
|
@@ -95,9 +108,9 @@ Read brief-cited `references/superpowers/test-driven-development/SKILL.md`; pres
|
|
|
95
108
|
### Final plan Reviewer correction loop
|
|
96
109
|
|
|
97
110
|
For a plan's final overall Reviewer findings, including behavior findings, Orchestrator assigns
|
|
98
|
-
|
|
111
|
+
Implementer → Reviewer recheck with no QA reassignment. Repeat corrections and Reviewer rechecks until findings are resolved;
|
|
99
112
|
the initial single full review does not prohibit necessary rechecks. Before the initial final overall Reviewer,
|
|
100
|
-
risk-required checks and QA execution failures or unmet criteria still require
|
|
113
|
+
risk-required checks and QA execution failures or unmet criteria still require Implementer correction → QA recheck.
|
|
101
114
|
This exception applies only to findings from the final overall Reviewer of work with a plan.
|
|
102
115
|
Work without a plan retains its existing verification flow. Scope expansion, separate mandatory obligations,
|
|
103
116
|
or unresolved evidence gaps hold affected work for Orchestrator to resolve and obtain required approvals.
|
|
@@ -120,14 +133,14 @@ For Orchestrator, **Evidence verdict**: each criterion is proven, unmet, or unve
|
|
|
120
133
|
|
|
121
134
|
## Risk-scaled execution
|
|
122
135
|
|
|
123
|
-
Orchestrator assigns edits exclusively to
|
|
136
|
+
Orchestrator assigns edits exclusively to Implementer except under the Orchestrator direct path in [handoff](handoff.md#orchestrator-direct-path-for-small-tasks), and determines affected
|
|
124
137
|
behavior, risk, and smallest meaningful verification.
|
|
125
138
|
|
|
126
139
|
| Risk | Minimum flow |
|
|
127
140
|
|---|---|
|
|
128
|
-
| Small, low risk |
|
|
129
|
-
| Ordinary behavior |
|
|
130
|
-
| Significant/high risk |
|
|
141
|
+
| Small, low risk | Implementer, or Orchestrator direct path → Orchestrator's focused checks → acceptance |
|
|
142
|
+
| Ordinary behavior | Implementer → independent QA → acceptance |
|
|
143
|
+
| Significant/high risk | Implementer → QA → independent Reviewer of the final full change → acceptance; with a plan, each plan task Implementer → FRESH QA → acceptance/commit satisfies the QA step, then independent Reviewer once on the final full change after all plan tasks |
|
|
131
144
|
|
|
132
145
|
Ordinary and significant plan tasks need a FRESH QA before acceptance; only small, low-risk tasks may be accepted on
|
|
133
146
|
Orchestrator focused checks. Small, low risk means narrow, understood, readily reversible, and verifiable by focused
|
|
@@ -143,7 +156,7 @@ a plan keeps Reviewer after QA before acceptance. Preserve specific approved obl
|
|
|
143
156
|
before dependent implementation. Reuse evidence only when scope, relevant state, independence, freshness, and flow
|
|
144
157
|
position satisfy each covered requirement; changes, failures, or missing/conflicting evidence invalidate affected reuse.
|
|
145
158
|
QA checks independently without edits; Reviewer independently reads the final full change after QA for significant
|
|
146
|
-
work, without QA, planning, edits, delegation, or completion decisions. Orchestrator routes fixes to
|
|
159
|
+
work, without QA, planning, edits, delegation, or completion decisions. Orchestrator routes fixes to Implementer,
|
|
147
160
|
obtains affected QA rechecks outside the final plan Reviewer correction exception and required final review, and accepts after findings/evidence gaps are resolved or
|
|
148
161
|
explicitly dispositioned.
|
|
149
162
|
|
|
@@ -155,11 +168,136 @@ After gates hold, continue approved scope without saved documents through requir
|
|
|
155
168
|
Completion continuity above; a role report alone does not complete the work.
|
|
156
169
|
|
|
157
170
|
|
|
171
|
+
## Verification lifecycle in the cooperative CLI
|
|
172
|
+
|
|
173
|
+
The supported `workflow` path is an approved complete spec+plan. No-plan, small-task and document omission paths remain
|
|
174
|
+
`cooperative.unsupported`; this outcome does not imply a violation of existing ARC policy or a new obligation to write documents.
|
|
175
|
+
The CLI does not execute checks or invoke Reviewer. All actors, results and verdicts are `operator-attested`; they do not prove
|
|
176
|
+
identity, actual independence, semantic sufficiency or enforced execution.
|
|
177
|
+
|
|
178
|
+
An Orchestrator actor (`actor.role: "orchestrator"`) registers a verification contract by recording
|
|
179
|
+
`data: {kind: "task", task: {...}}` in `acceptance-evidence` through `record`. The task specifies `id`, absolute `paths`,
|
|
180
|
+
`criteria`, `requiredChecks`, `dependencies`, `approvalRef`, `approvalVersion`, `documentVersion`,
|
|
181
|
+
`scopeVersion` and `targetVersion`. Only pending tasks can be registered; this record is neither acceptance nor a commit.
|
|
182
|
+
Each requiredChecks descriptor is `{executable, args, cwd, env, outputs}`; executable, cwd and outputs are absolute paths.
|
|
183
|
+
cwd and outputs must be within the workspace. Do not include Reviewer in task requiredChecks.
|
|
184
|
+
|
|
185
|
+
`changeFingerprints.tasks[taskId]` and `changeFingerprints.final` in `status` are independent observations.
|
|
186
|
+
They include read-only Git inventory/index observations and current regular-file bytes, modes and deletions. Task fingerprints
|
|
187
|
+
cover owned paths; the final fingerprint covers the whole repository snapshot. Unsupported observations such as symlinks,
|
|
188
|
+
submodules and unmerged indexes cause a hold. This is not a sandbox that atomically locks observation and execution.
|
|
189
|
+
Leave runtimeHash drift as stale/hold; do not automatically update the stored version or convert it through migration or renewed approval.
|
|
190
|
+
|
|
191
|
+
`operation: "check"` in `prepare` accepts `taskId` and
|
|
192
|
+
`arguments: {scope: "task", actor: {id, role: "qa"}, descriptor, changeFingerprint, findingIds?}`.
|
|
193
|
+
Actor ID attestations must be independent of Implementer and Orchestrator; QA/Implementer reuse across tasks is rejected. The descriptor must
|
|
194
|
+
exactly match the registered requiredChecks. After the intent is persisted, the responsible role executes within its existing approved scope.
|
|
195
|
+
`result` or `reconcile` records `intentId` and `{status, messageRef, data}`. data specifies the same
|
|
196
|
+
`actor`, `descriptor` and `scope` as the intent, `taskId` for tasks, `changeFingerprint`, and
|
|
197
|
+
`verdict: "proven" | "unmet" | "unverified"`. Even a succeeded/proven result is valid only for that change version.
|
|
198
|
+
This is an operator verdict record; it does not replace semantic proof of a criterion or Orchestrator acceptance.
|
|
199
|
+
Failures, unknown, mismatch and unverified outcomes are not passing evidence. Preserve previous results and failure records.
|
|
200
|
+
|
|
201
|
+
A failed check/review leaves an open finding. Link a separate finding to an existing check/review through `record` with
|
|
202
|
+
`data: {action: "open", id, checkId, message}`. After a Implementer fix, record
|
|
203
|
+
`data: {action: "resolve", id, actor: {id, role: "implementer"}, changeFingerprint}` and the fix evidence messageRef.
|
|
204
|
+
The actor must be the Implementer assigned to that task, or a relevant task for an overall finding. This marks the finding resolved;
|
|
205
|
+
it becomes closed only when a subsequent prepare includes it in `findingIds` and revalidation passes for the same change version.
|
|
206
|
+
Earlier QA failures retain the Implementer→QA recheck requirement.
|
|
207
|
+
|
|
208
|
+
`operation: "review"` uses `scope: "final"`, `actor.role: "reviewer"` and
|
|
209
|
+
`descriptor: {kind: "source-review", paths: [...]}`, without taskId. The initial final review requires acceptance of all tasks
|
|
210
|
+
and current required task QA evidence. Reviewer is not a prerequisite gate for task acceptance or focused commits.
|
|
211
|
+
For final Reviewer findings in supported plan work, repeat Implementer resolution→Reviewer revalidation without QA reassignment.
|
|
212
|
+
Do not present earlier QA evidence as execution evidence for a subsequent fix. This exception does not omit separate unresolved QA failures.
|
|
213
|
+
|
|
214
|
+
Scope, document and approval change records do not overwrite history. Specifying `data.affectedTaskIds` invalidates task,
|
|
215
|
+
verification and acceptance evidence for those tasks and their dependency chain; omitting it holds all tasks. Final evidence also becomes stale.
|
|
216
|
+
Preserve evidence for unaffected independent tasks. Orchestrator determines semantic impact. Affected tasks require a new approval record
|
|
217
|
+
for the current scope and an updated task contract before preparation; earlier approvals cannot revive them. New checks/reviews and
|
|
218
|
+
finding revalidation are also required. Current evidence supersedes earlier failures without deleting them; acceptance, commits and final completion remain Orchestrator decisions.
|
|
219
|
+
|
|
220
|
+
### Task acceptance and focused commit reconciliation in the cooperative CLI
|
|
221
|
+
|
|
222
|
+
In the current plan mode, `prepare` supports `operation: "accept"` and `operation: "commit"`.
|
|
223
|
+
Acceptance is an Orchestrator attestation specifying `actor.role: "orchestrator"`, `taskId`, and, in `arguments`,
|
|
224
|
+
`messageRef`, the same `criteria` as the task, exact `checkIds` for current required QA, all task
|
|
225
|
+
`findingIds` and the current `changeFingerprint`. The latest QA result for each required descriptor must be
|
|
226
|
+
passed/proven, and findings must be closed through Implementer fixes and QA rechecks.
|
|
227
|
+
A successful attestation marks the task accepted; passing commands or Implementer reports alone do not constitute acceptance.
|
|
228
|
+
The provenance is `operator-attested`; the operator confirms semantic criterion satisfaction and actor identities.
|
|
229
|
+
|
|
230
|
+
At acceptance, the code pins the actual index tree, staged diff, paths and task fingerprint together. Orchestrator stages only
|
|
231
|
+
approved task paths beforehand and confirms required QA for that index state. Unrelated paths, changes from another registered
|
|
232
|
+
task, or unstaged/untracked changes within scope cause a hold. The code cannot automatically distinguish semantically unrelated
|
|
233
|
+
hunks within the same file; Orchestrator reads the actual diff to confirm them.
|
|
234
|
+
|
|
235
|
+
`operation: "commit"` in `prepare` references the exact acceptance through `arguments: {"acceptanceId": "acceptance requestId"}`.
|
|
236
|
+
The code checks that the current approval, task contract, QA, findings and index match acceptance, then persists a durable intent
|
|
237
|
+
with the expected parent, tree, paths and residual paths. The CLI does not stage or commit.
|
|
238
|
+
Orchestrator creates one focused implementation commit matching these expectations.
|
|
239
|
+
|
|
240
|
+
Then submit `intentId`, `actor.role: "orchestrator"`, and
|
|
241
|
+
`result: {"status": "succeeded", "messageRef": "actual result evidence", "data": {"commit": "full OID"}}`
|
|
242
|
+
through `reconcile` or result-form `result`. The CLI rereads the actual commit object, parent, tree, paths, HEAD, index and residual changes from local Git.
|
|
243
|
+
Only a complete match updates target HEAD and marks the task committed. Failure, unknown and mismatch observations and actual
|
|
244
|
+
history are preserved; the target is not updated arbitrarily. Reusing the same request or a completed intent does not authorize
|
|
245
|
+
a second effect. After a failure, read the actual state, resolve the cause and reconcile the existing intent.
|
|
246
|
+
|
|
247
|
+
Do not rewrite earlier QA fingerprints after a successful commit. Separate post-commit file/index observations detect subsequent
|
|
248
|
+
changes. Under the existing rules, final review requires current task evidence and the final fingerprint.
|
|
249
|
+
A changed runtimeHash follows the existing stale/hold rules; the stored version is not automatically updated.
|
|
250
|
+
|
|
158
251
|
[ARC role policy: contract begin]
|
|
159
252
|
Generated from lib/policy/role-policy.json; do not edit this managed section manually.
|
|
160
253
|
- [git.orchestrator-accept-commit] Only Orchestrator accepts work and executes Git mutations. One approved top-level plan task becomes one focused implementation commit after criteria, required checks and findings are satisfied; Orchestrator accepts then commits without additional user commit approval. Reports, passing checks and Reviewer opinions do not replace acceptance. Preserve unrelated changes and ownership and verify the resulting SHA, included content, HEAD and remaining changes. Existing small-task direct and plan-omission paths are unchanged.
|
|
161
|
-
- [review.significant-no-plan] For significant/high-risk work without a plan:
|
|
162
|
-
- [review.significant-plan] For significant/high-risk plan work: each task uses
|
|
163
|
-
- [review.final-plan-recheck] For final overall Reviewer findings on plan work, including behavior findings, use
|
|
254
|
+
- [review.significant-no-plan] For significant/high-risk work without a plan: Implementer → QA and required QA rechecks → Reviewer of the final full change → Orchestrator acceptance. MUST NOT omit Reviewer merely because no plan exists. This creates no new plan obligation.
|
|
255
|
+
- [review.significant-plan] For significant/high-risk plan work: each task uses Implementer → fresh QA as required → Orchestrator acceptance and focused commit. After all tasks are accepted and required QA is complete, Reviewer reviews the final full change once. Reviewer is NOT a per-task or per-commit required gate. Preserve required checks and necessary finding rechecks.
|
|
256
|
+
- [review.final-plan-recheck] For final overall Reviewer findings on plan work, including behavior findings, use Implementer → Reviewer without QA reassignment; repeat until resolved. This exception applies only at the final plan stage. Preserve required QA and QA failure rechecks before initial final review and outside this exception.
|
|
257
|
+
- [planning.plan-amend] During approved task execution, mechanical plan progress records need no new user approval; changed goals, scope, criteria, method, risk, dependencies or required verification require revised-version approval and preparation before affected work. In both cases Orchestrator amends the original planning-document commit at a safe boundary, without a separate document or fixup commit. Preserve actual approval chronology, recoverable old/new contents, hashes, versions and SHA mappings; never retroactively authorize earlier work. Rewrite only unpublished, unshared local linear history with clear ownership and no merges; stop on unknown publication, ownership, unexpected state or replay conflicts, without force push or a fallback document commit. Preserve implementation task boundaries and revalidate affected evidence. See planning, handoff-prep, commit and verification for the full contract.
|
|
164
258
|
- [platform.claude] Existing per-role tool allowlists reduce available tools; Bash and role contracts are not a filesystem sandbox. A role-scoped Git guard is a separate integration and is not supplied by these policy sections alone.
|
|
165
259
|
[ARC role policy: contract end]
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
## External operations and recovery in the cooperative CLI
|
|
263
|
+
|
|
264
|
+
The three phases support state, documents and assignment; scope, verification, acceptance and focused commits; and external approval, results and audit recovery.
|
|
265
|
+
Use `status.support` to inspect all nine areas and their limits. The supported mode is `plan` with spec+plan; no-plan and omission are unsupported. The CLI does not execute native/provider calls or push, merge, deploy or publish.
|
|
266
|
+
User approvals and execution results confirmed by the operator are `operator-attested`, with `nativeVerified: false` and
|
|
267
|
+
`remoteVerified: false`. Blocking direct calls outside the CLI and independent remote verification are not provided.
|
|
268
|
+
|
|
269
|
+
Orchestrator records an explicit approval it has already confirmed through `record` with
|
|
270
|
+
`evidence: {kind: "external-approval", messageRef, data: {operation, scope, descriptor}}`.
|
|
271
|
+
`scope` is an array of unique absolute paths within the checkout. Local commit approval does not authorize external operations.
|
|
272
|
+
Include the exact action, scope and target in the approval, and record every descriptor field below.
|
|
273
|
+
|
|
274
|
+
| operation | descriptor fields |
|
|
275
|
+
|---|---|
|
|
276
|
+
| push | repository, destination, refspec, sourceOid, expectedRemoteOid |
|
|
277
|
+
| merge | repository, changeRef, targetRef, expectedTargetOid |
|
|
278
|
+
| deploy | service, project, environment, artifactId, destination |
|
|
279
|
+
| publish | service, namespace, name, version, artifactHash, destination |
|
|
280
|
+
|
|
281
|
+
Git OIDs are full 40/64-character lowercase hex values; artifactHash is `sha256:<64-hex>`. Without a remote observation,
|
|
282
|
+
an OID is an expected value asserted by the user, not verified remote state. destination must be an identifier without secrets.
|
|
283
|
+
Do not submit URL userinfo, query or fragment components, or authentication information such as passwords, tokens or credentials.
|
|
284
|
+
The CLI rejects recognized credential inputs before persistence, but cannot determine whether every arbitrary string contains a secret.
|
|
285
|
+
|
|
286
|
+
Pass `{requestId, expectedRevision, actor: {id, role: "orchestrator"}, operation,
|
|
287
|
+
arguments: {approvalRef, scope, descriptor}}` to `prepare`. approvalRef matches the external approval messageRef.
|
|
288
|
+
An intent is persisted only when the exact approval, scope/target versions and runtime version match and no effect is unresolved.
|
|
289
|
+
After confirming `allow` and `persisted: true`, Orchestrator performs the external operation within its separately approved scope.
|
|
290
|
+
This CLI does not expand that execution authority.
|
|
291
|
+
|
|
292
|
+
`result`/`reconcile` accepts `{requestId, expectedRevision, actor, intentId,
|
|
293
|
+
result: {status, messageRef, data: {operation, scope, descriptor}}}`. intentId is the prepare requestId.
|
|
294
|
+
Target mismatches, unknown outcomes and stale results cause a hold while preserving earlier attestations. After an interruption,
|
|
295
|
+
use `status` to inspect the intent, `state.requests`, `state.audit` and `state.results`, and investigate whether the effect occurred.
|
|
296
|
+
Reconcile the investigation result against the same intent rather than preparing again or reusing the same approval to execute again.
|
|
297
|
+
Cancellation additionally requires a `notExecutedEvidence: {messageRef}` attestation that the operation was not executed.
|
|
298
|
+
The approval remains consumed after cancellation. Do not resolve version drift through automatic updates, migration or renewed permission.
|
|
299
|
+
Report the cause of the hold to Orchestrator.
|
|
300
|
+
|
|
301
|
+
Even succeeded results are operator attestations, not independent remote verification. `audit` retains the
|
|
302
|
+
request→decision→intent→result→resolution linkage, but is a locally editable record rather than tamper-proof security evidence.
|
|
303
|
+
Do not retry while the actual external outcome is uncertain.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import {fingerprintRequest} from './store.mjs';
|
|
3
|
+
import {validateGitPreflight,validateGitCommitResult} from './git-evidence.mjs';
|
|
4
|
+
import {within} from './scope.mjs';
|
|
5
|
+
const reconciliations=new WeakMap();
|
|
6
|
+
export function verifiedCooperativeReconciliation(decision,state){const proof=reconciliations.get(decision);return !!proof&&proof.before===fingerprintRequest(state)&&proof.after===fingerprintRequest(decision.proposedTransition);}
|
|
7
|
+
const completed=(state,id)=>state.tasks?.some(t=>t.id===id&&t.status==='committed'&&!t.invalidated)&&state.commits?.some(c=>c.taskId===id&&c.observationSource==='local-git'&&state.intents.some(i=>i.operation==='commit'&&i.requestId===c.requestId&&i.taskId===id&&i.status==='succeeded'));
|
|
8
|
+
const same=(a,b)=>JSON.stringify(a)===JSON.stringify(b);
|
|
9
|
+
const text=v=>typeof v==='string'&&v.length>0;
|
|
10
|
+
const list=v=>Array.isArray(v)&&v.every(text)&&new Set(v).size===v.length;
|
|
11
|
+
const exact=(a,b)=>list(a)&&list(b)&&same([...a].sort(),[...b].sort());
|
|
12
|
+
const fields=(v,keys)=>v&&typeof v==='object'&&!Array.isArray(v)&&Object.keys(v).every(k=>keys.includes(k));
|
|
13
|
+
const semanticLimit='Semantically unrelated hunks inside the same file require Orchestrator inspection; path and byte evidence cannot distinguish them automatically.';
|
|
14
|
+
const base=state=>({expectedRevision:state?.revision??0,coverage:{enforcement:'cooperative',provenance:'operator-attested',nativeVerified:false},semanticLimit,requiredEvidence:[],nextActions:[],proposedTransition:null});
|
|
15
|
+
const hold=(state,reason)=>({...base(state),decision:'hold',ruleIds:['cooperative.acceptance'],reason});
|
|
16
|
+
const allow=(state,transition)=>({...base(state),decision:'allow',ruleIds:['cooperative.acceptance'],proposedTransition:transition});
|
|
17
|
+
const approval=(state,id)=>state.records.filter(r=>r.kind==='approval'&&(!r.data.affectedTaskIds||r.data.affectedTaskIds.includes(id))).at(-1);
|
|
18
|
+
function authorized(state,task){const a=approval(state,task?.id);return state.mode==='plan'&&task&&!task.invalidated&&a?.source==='operator-attested'&&a.targetVersion===state.targetVersion&&task.targetVersion===state.targetVersion&&task.scopeVersion===a.scopeVersion&&task.approvalRef===a.messageRef&&task.approvalVersion===a.data.approvalVersion&&task.documentVersion===a.data.documentVersion;}
|
|
19
|
+
function checkEvidence(state,task,a,changes){
|
|
20
|
+
if(!same(a.criteria,task.criteria)||!task.criteria.length||!list(a.checkIds)||!list(a.findingIds)||a.changeFingerprint!==changes?.tasks?.[task.id])return false;
|
|
21
|
+
const checks=state.checks.filter(c=>c.scope==='task'&&c.taskId===task.id);
|
|
22
|
+
const latest=task.requiredChecks.map(d=>checks.filter(c=>same(c.descriptor,d)).at(-1));
|
|
23
|
+
if(!task.requiredChecks.length||latest.some(c=>!c||c.stale||c.status!=='passed'||c.verdict!=='proven'||!text(c.resultRef)||c.source!=='operator-attested'||c.verificationActor?.role!=='qa'||!text(c.verificationActor.id)||state.assignments.some(a=>a.agentId===c.verificationActor.id)||c.changeFingerprint!==a.changeFingerprint)||!exact(a.checkIds,latest.map(c=>c?.id)))return false;
|
|
24
|
+
const findings=state.findings.filter(f=>f.scope==='task'&&f.taskId===task.id);
|
|
25
|
+
return exact(a.findingIds,findings.map(f=>f.id))&&findings.every(f=>f.status==='closed'&&text(f.resolutionRef)&&text(f.recheckRef)&&f.resolutionActor?.role==='implementer'&&f.recheckActor?.role==='qa'&&f.changeFingerprint===a.changeFingerprint);
|
|
26
|
+
}
|
|
27
|
+
function waitingFor(state,task,predecessor){
|
|
28
|
+
if(task.status!=='pending'||state.intents.some(i=>i.taskId===task.id&&i.operation==='assign-agent'&&['prepared','unknown','mismatch','succeeded'].includes(i.status)))return false;
|
|
29
|
+
const seen=new Set(),queue=[...(task.dependencies??[])];while(queue.length){const id=queue.pop();if(id===predecessor)return true;if(seen.has(id))continue;seen.add(id);queue.push(...(state.tasks.find(t=>t.id===id)?.dependencies??[]));}return false;
|
|
30
|
+
}
|
|
31
|
+
function dirtyOtherTask(state,task,git){return git.stagedPaths?.some(name=>state.tasks.some(t=>t.id!==task.id&&!completed(state,t.id)&&!waitingFor(state,t,task.id)&&t.paths.some(p=>within(p,path.join(state.target.realpath,...name.split('/'))))));}
|
|
32
|
+
function freshAcceptance(state,task,acceptance,changes){return acceptance&&!acceptance.stale&&authorized(state,task)&&acceptance.taskFingerprint===fingerprintRequest({...task,status:'pending'})&&same(acceptance.approval,approval(state,task.id))&&same(acceptance.target,state.target)&&same(acceptance.versions,state.versions)&&checkEvidence(state,task,acceptance,changes);}
|
|
33
|
+
/** Operator attests semantic sufficiency; code binds exact current evidence only. */
|
|
34
|
+
export function evaluateCooperativeAcceptance({state,request,evidence}={}){
|
|
35
|
+
const task=state?.tasks?.find(t=>t.id===request?.taskId),a=request?.arguments,g=evidence?.git;
|
|
36
|
+
if(request?.expectedRevision!==state?.revision||request.actor?.role!=='orchestrator'||!authorized(state,task)||task.status!=='pending'||state.acceptances.some(v=>v.taskId===task.id&&!v.stale)||state.commits.some(v=>v.taskId===task.id))return hold(state,'Current pending approved task and Orchestrator acceptance required');
|
|
37
|
+
if(!fields(a,['messageRef','criteria','checkIds','findingIds','changeFingerprint'])||!text(a.messageRef)||!checkEvidence(state,task,a,evidence?.changes)||state.checks.some(c=>a.checkIds?.includes(c.id)&&c.verificationActor?.id===request.actor.id))return hold(state,'Exact criteria, current required QA checks and closed findings required');
|
|
38
|
+
const descriptor={kind:'task',parent:state.target.head,indexTree:g?.indexTree,fingerprint:g?.stagedFingerprint,paths:g?.stagedPaths};
|
|
39
|
+
const invalid=validateGitPreflight({target:state.target,descriptor,scope:task.paths,gitEvidence:g});
|
|
40
|
+
if(invalid||dirtyOtherTask(state,task,g))return hold(state,invalid??'Index includes another task changes');
|
|
41
|
+
return allow(state,{acceptance:{...structuredClone(a),id:request.requestId,taskId:task.id,actor:structuredClone(request.actor),source:'operator-attested',descriptor:structuredClone(descriptor),taskFingerprint:fingerprintRequest({...task,status:'pending'}),approval:structuredClone(approval(state,task.id)),target:structuredClone(state.target),versions:structuredClone(state.versions)}});
|
|
42
|
+
}
|
|
43
|
+
/** Prepares a durable intent; never stages or executes a commit. */
|
|
44
|
+
export function prepareCooperativeCommit({state,request,gitEvidence,evidence}={}){
|
|
45
|
+
const task=state?.tasks?.find(t=>t.id===request?.taskId),a=state?.acceptances?.find(a=>a.id===request?.arguments?.acceptanceId&&a.taskId===request.taskId);
|
|
46
|
+
if(request?.expectedRevision!==state?.revision||request.actor?.role!=='orchestrator'||!fields(request.arguments,['acceptanceId'])||task?.status!=='accepted'||!freshAcceptance(state,task,a,evidence?.changes)||state.commits.some(c=>c.taskId===task.id)||state.intents.some(i=>i.operation==='commit'&&i.taskId===task.id&&['prepared','unknown','mismatch'].includes(i.status)))return hold(state,'Exact current acceptance and no prior task commit or unresolved commit required');
|
|
47
|
+
const invalid=validateGitPreflight({target:state.target,descriptor:a.descriptor,scope:task.paths,gitEvidence});
|
|
48
|
+
if(invalid||dirtyOtherTask(state,task,gitEvidence))return hold(state,invalid??'Index includes another task changes');
|
|
49
|
+
const expected={parent:a.descriptor.parent,tree:a.descriptor.indexTree,paths:[...a.descriptor.paths],fingerprint:a.descriptor.fingerprint,remainingPaths:[...new Set([...gitEvidence.workingPaths,...gitEvidence.untrackedPaths])].sort()};
|
|
50
|
+
return allow(state,{intent:{requestId:request.requestId,operation:'commit',taskId:task.id,status:'prepared',acceptanceId:a.id,acceptanceFingerprint:fingerprintRequest(a),expected,target:structuredClone(state.target),versions:structuredClone(state.versions),fingerprint:fingerprintRequest(request),source:'operator-attested'}});
|
|
51
|
+
}
|
|
52
|
+
/** Results are local Git observations, correlated with an operator statement.
|
|
53
|
+
* Mismatch observations remain historical evidence and never rebind the target. */
|
|
54
|
+
export function reconcileCooperativeCommit({state,intent,result,gitEvidence}={}){
|
|
55
|
+
if(!intent||intent.operation!=='commit'||!['prepared','unknown','mismatch'].includes(intent.status)||state.commits.some(c=>c.taskId===intent.taskId))return hold(state,'Matching unresolved commit intent required; replay cannot authorize another effect');
|
|
56
|
+
const task=state.tasks.find(t=>t.id===intent.taskId),a=state.acceptances.find(a=>a.id===intent.acceptanceId),g=gitEvidence;
|
|
57
|
+
const observation=g?structuredClone(g):null;
|
|
58
|
+
const transition={observation,result:{...structuredClone(result),status:'mismatch',source:'operator-attested'}};
|
|
59
|
+
const reject=reason=>({...hold(state,reason),proposedTransition:transition});
|
|
60
|
+
if(!result||!text(result.messageRef)||!fields(result.data,['commit'])||!['succeeded','failed','unknown','mismatch'].includes(result.status))return reject('Exact commit result statement required');
|
|
61
|
+
if(result.status!=='succeeded'){transition.result.status=result.status;return reject('Execution did not establish a successful commit');}
|
|
62
|
+
if(task?.status!=='accepted'||!authorized(state,task)||a?.stale||!a||intent.acceptanceFingerprint!==fingerprintRequest(a)||a.taskFingerprint!==fingerprintRequest({...task,status:'pending'})||!same(a.approval,approval(state,task.id))||!checkEvidence(state,task,a,{tasks:{[task.id]:a.changeFingerprint}})||!same(intent.target,state.target)||!same(intent.versions,state.versions)||!g?.commit||result.data.commit!==g.commit.commit||g.stagedPaths?.length||g.indexTree!==g.commit.tree)return reject('Acceptance, observed commit or clean resulting index mismatch');
|
|
63
|
+
const actual={...g.commit,target:g.target,remainingPaths:[...new Set([...g.workingPaths??[],...g.untrackedPaths??[]])].sort()};
|
|
64
|
+
const invalid=validateGitCommitResult({target:state.target,expected:intent.expected,result:actual,scope:task.paths});
|
|
65
|
+
if(invalid)return reject(invalid);
|
|
66
|
+
transition.result.status='succeeded';transition.commit={...actual,taskId:task.id,requestId:intent.requestId,acceptanceId:a.id,source:'operator-attested',observationSource:'local-git',fingerprint:a.changeFingerprint};transition.target=structuredClone(g.target);
|
|
67
|
+
const decision=allow(state,transition);reconciliations.set(decision,{before:fingerprintRequest(state),after:fingerprintRequest(transition)});return decision;
|
|
68
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {fingerprintRequest} from './store.mjs';
|
|
2
|
+
import {absolute,within} from './scope.mjs';
|
|
3
|
+
const completed=(state,id)=>state.tasks?.some(t=>t.id===id&&t.status==='committed'&&!t.invalidated)&&state.commits?.some(c=>c.taskId===id&&c.observationSource==='local-git'&&state.intents.some(i=>i.operation==='commit'&&i.requestId===c.requestId&&i.taskId===id&&i.status==='succeeded'));
|
|
4
|
+
const same=(a,b)=>JSON.stringify(a)===JSON.stringify(b);
|
|
5
|
+
const text=value=>typeof value==='string'&&value.length>0;
|
|
6
|
+
const version=value=>Number.isSafeInteger(value)&&value>0;
|
|
7
|
+
const setEqual=(a,b)=>Array.isArray(a)&&Array.isArray(b)&&new Set(a).size===a.length&&new Set(b).size===b.length&&same([...a].sort(),[...b].sort());
|
|
8
|
+
const base=state=>({expectedRevision:state?.revision??0,coverage:{enforcement:'cooperative',provenance:'operator-attested',nativeVerified:false},requiredEvidence:[],nextActions:[],proposedTransition:null});
|
|
9
|
+
const hold=(state,id,reason)=>({...base(state),decision:'hold',ruleIds:['cooperative.'+id],reason});
|
|
10
|
+
/** Pure gate. observations are supplied by trusted local readers, never JSON input. */
|
|
11
|
+
export function prepareCooperativeAssignment({policy,state,request,observations}={}){
|
|
12
|
+
if(policy!==undefined&&policy.workflowKind!=='cooperative')return hold(state,'contract','Explicit cooperative contract required');
|
|
13
|
+
const args=request?.arguments;
|
|
14
|
+
if(state?.mode!=='plan'||request?.operation!=='assign-agent'||!args)return hold(state,'unsupported','Only explicit plan assignment is supported');
|
|
15
|
+
const allowed=['role','paths','operations','documents','approvalRef','approvalVersion','documentVersion','correlation'];
|
|
16
|
+
if(Object.keys(args).some(k=>!allowed.includes(k))||args.role!=='implementer'||!text(request.taskId)||!text(request.requestId)||!text(args.correlation)||!text(args.approvalRef)||!version(args.approvalVersion)||!version(args.documentVersion)||!Array.isArray(args.paths)||!args.paths.length||new Set(args.paths).size!==args.paths.length||args.paths.some(p=>!absolute(p)||!within(state.target.realpath,p))||!Array.isArray(args.operations)||!args.operations.length||args.operations.some(o=>o!=='edit'))return hold(state,'assignment','Invalid assignment or unsupported historical agent import');
|
|
17
|
+
if(!same(observations?.target,state.target)||!same(observations?.git?.target,state.target))return hold(state,'target','Re-observe target and renew approval after drift');
|
|
18
|
+
if(request.expectedRevision!==state.revision)return hold(state,'revision','Stale assignment request');
|
|
19
|
+
if(state.records.some(r=>r.data?.priorExecution===true)||state.assignments.some(a=>a.source!=='operator-attested'))return hold(state,'history','Earlier execution remains unverified; a late commit cannot authorize it');
|
|
20
|
+
if(state.intents.some(i=>i.operation==='assign-agent'&&['prepared','unknown','mismatch','succeeded'].includes(i.status)&&(i.taskId===request.taskId||i.correlation===args.correlation||!(i.status==='succeeded'&&completed(state,i.taskId))&&i.paths?.some(p=>args.paths.some(q=>within(p,q)||within(q,p))))))return hold(state,'assignment-active','Resolve the existing dispatch before preparing another');
|
|
21
|
+
const task=state.tasks?.find(t=>t.id===request.taskId);
|
|
22
|
+
if(task&&(task.invalidated||task.status==='held'||task.dependencies?.some(id=>{const predecessor=state.tasks.find(t=>t.id===id);return !predecessor||predecessor.invalidated||!['accepted','committed'].includes(predecessor.status);})))return hold(state,'task-stale','Affected task or predecessor requires renewed readiness and approval');
|
|
23
|
+
const scope=state.scopes?.findLast(s=>s.scopeVersion===state.scopeVersion&&(!s.data.affectedTaskIds||s.data.affectedTaskIds.includes(request.taskId)));
|
|
24
|
+
if(!task||!task.paths?.length||args.paths.some(p=>!task.paths.some(base=>within(base,p)))||scope&&args.paths.some(p=>!scope.data.paths?.some(base=>within(base,p))))return hold(state,'assignment-scope','Assignment must stay inside approved task and recorded scope');
|
|
25
|
+
const documents=args.documents,git=observations.git;
|
|
26
|
+
if(!Array.isArray(documents)||documents.length!==2||!setEqual(documents.map(d=>d.kind),['spec','plan'])||!git.docsCommit||!setEqual(git.docsCommit.paths,documents.map(d=>d.gitPath))||!same(git.docsCommit.documents,documents)||documents.some(d=>d.commit!==git.docsCommit.commit)||!Array.isArray(git.documents)||git.documents.length!==2||documents.some(d=>!git.documents.some(o=>o.path===d.path&&o.gitPath===d.gitPath&&o.kind===d.kind&&o.observedHash===d.contentHash&&o.currentHash===d.contentHash)))return hold(state,'documents','Exact committed spec and plan plus current bytes must match approval');
|
|
27
|
+
const approval=state.records.filter(r=>r.kind==='approval'&&(!r.data.affectedTaskIds||r.data.affectedTaskIds.includes(request.taskId))).at(-1);
|
|
28
|
+
if(task.approvalRef!==args.approvalRef||task.approvalVersion!==args.approvalVersion||task.documentVersion!==args.documentVersion||task.scopeVersion!==state.scopeVersion||task.targetVersion!==state.targetVersion||!approval||approval.source!=='operator-attested'||approval.messageRef!==args.approvalRef||approval.targetVersion!==state.targetVersion||approval.scopeVersion!==state.scopeVersion||approval.data.approvalVersion!==args.approvalVersion||approval.data.documentVersion!==args.documentVersion||!same(approval.data.documents,documents)||documents.some(d=>d.approvalRef!==args.approvalRef))return hold(state,'approval','Current document and approval versions must match');
|
|
29
|
+
const intent={requestId:request.requestId,taskId:request.taskId,operation:request.operation,status:'prepared',role:args.role,paths:[...args.paths],operations:[...args.operations],correlation:args.correlation,documents:structuredClone(documents),docsCommit:git.docsCommit.commit,approvalRef:args.approvalRef,approvalVersion:args.approvalVersion,documentVersion:args.documentVersion,target:structuredClone(state.target),targetVersion:state.targetVersion,scopeVersion:state.scopeVersion,revision:state.revision+1,fingerprint:fingerprintRequest(request),source:'operator-attested'};
|
|
30
|
+
return {...base(state),decision:'allow',ruleIds:['cooperative.assignment-prepared'],proposedTransition:{intent}};
|
|
31
|
+
}
|
|
32
|
+
/** A native response is an operator statement, not authenticated identity or compliance. */
|
|
33
|
+
export function recordCooperativeAssignmentResult({state,intent,result,observations}={}){
|
|
34
|
+
if(!intent||intent.operation!=='assign-agent')return hold(state,'intent','No matching assignment intent');
|
|
35
|
+
if(!['prepared','unknown','mismatch'].includes(intent.status))return hold(state,'assignment-terminal','Preserve the prior terminal native response');
|
|
36
|
+
if(!result||!['succeeded','failed','unknown','mismatch'].includes(result.status)||!text(result.messageRef)||!result.data)return hold(state,'assignment-result','Invalid native result statement');
|
|
37
|
+
if(result.status==='succeeded'&&(state.assignments.some(a=>a.agentId===result.data.agentId&&a.taskId!==intent.taskId)||state.intents?.some(i=>i.verificationActor?.id===result.data.agentId)||state.checks?.some(c=>c.verificationActor?.id===result.data.agentId)))return hold(state,'assignment-freshness','Implementer actor statements cannot cross tasks');
|
|
38
|
+
let status=result.status;
|
|
39
|
+
if(!same(intent.target,observations?.target)||result.data.correlation!==intent.correlation||result.data.taskId!==intent.taskId||status==='succeeded'&&!text(result.data.agentId))status='mismatch';
|
|
40
|
+
const entry={...structuredClone(result),status,requestId:intent.requestId,source:'operator-attested'};
|
|
41
|
+
return {...base(state),decision:['succeeded','failed'].includes(status)?'allow':'hold',ruleIds:['cooperative.assignment-'+status],proposedTransition:{result:entry}};
|
|
42
|
+
}
|