@awak-app/simy-cli 0.5.12 → 0.5.13
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/package.json +1 -1
- package/src/cli-contract.js +1 -1
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/SKILL.md +43 -21
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/acceptance-evidence.md +12 -0
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/delivery-levels.md +21 -7
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/minimum-completion.md +2 -2
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/shared-system-specifications.md +30 -21
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/state-and-receipts.md +9 -2
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/scripts/check-minimum-completion.mjs +2 -0
- package/src/codex-plugins/simy/skills/agentic-delivery-loop/scripts/production-contract.mjs +158 -0
- package/src/orchestrator/completion-contract.js +5 -1
- package/src/orchestrator/independent-audit.js +3 -0
- package/src/orchestrator/instruction.js +3 -0
package/package.json
CHANGED
package/src/cli-contract.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "./durable-local-task-steps-contract.js";
|
|
14
14
|
import { buildExecutionCapabilityContract } from "./execution-capability-contract.js";
|
|
15
15
|
|
|
16
|
-
export const CLI_VERSION = "0.5.
|
|
16
|
+
export const CLI_VERSION = "0.5.13";
|
|
17
17
|
export const CLI_API_CONTRACT_VERSION = 10;
|
|
18
18
|
|
|
19
19
|
export function withCliContract(
|
|
@@ -53,6 +53,11 @@ Before material action, record:
|
|
|
53
53
|
the exact user journey;
|
|
54
54
|
- required evidence, applicable change boundaries, risk tier, and the few
|
|
55
55
|
critical invariants that must block integration;
|
|
56
|
+
- for every production-relevant experience ID, outcome and guardrail measures
|
|
57
|
+
with signal, independent source, observation window, threshold, decision and
|
|
58
|
+
owner; if no production outcome is in scope, record that once with a reason;
|
|
59
|
+
- when release is in scope, staged exposure and deterministic promote, hold,
|
|
60
|
+
abort and rollback criteria, rollback mechanism, kill switch and owner;
|
|
56
61
|
- requested and effective delivery levels, the risk-based safety ceiling, and
|
|
57
62
|
the chat confirmation receipt;
|
|
58
63
|
- exclusions and authority boundaries, especially commit, push, Draft PR
|
|
@@ -77,19 +82,20 @@ shared source, not twelve new task-local copies. Unaffected views retain their
|
|
|
77
82
|
version; unknown As-Is facts remain unknown. Review changes through the team's
|
|
78
83
|
normal version control and preserve concurrent work.
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
Freeze and follow the risk-proportionate review plan from the selected delivery
|
|
86
|
+
level. Level 3 may consolidate design, implementation-to-To-Be, affected-view and
|
|
87
|
+
final evidence review into one independent final-candidate review. Inspect changed
|
|
88
|
+
views and their dependency links; retain unrelated views by exact revision. Fix
|
|
89
|
+
findings and independently re-review the affected behavior. A changed bound input
|
|
84
90
|
invalidates affected approval; do not rewrite To-Be to disguise a failed result.
|
|
85
91
|
|
|
86
|
-
|
|
87
|
-
reference. Announce
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
that historical failures cannot recur.
|
|
92
|
+
When SQM is explicitly opted in, apply the identity-aware SQM plan described in
|
|
93
|
+
the reference. Announce its applicability when starting Delivery Loop. Reuse a
|
|
94
|
+
verifiable proof only for exactly unchanged bound inputs; rerun for changed identity
|
|
95
|
+
or newly applicable PR-only checks. If required access is absent, retain the unmet
|
|
96
|
+
gate and continue independent work. Ordinary PR work outside Delivery Loop does
|
|
97
|
+
not activate SQM. Record known and unknown incident coverage separately; zero
|
|
98
|
+
applicable rules do not prove that historical failures cannot recur.
|
|
93
99
|
|
|
94
100
|
## Maintain the acceptance checklist outside the conversation
|
|
95
101
|
|
|
@@ -290,10 +296,11 @@ Run focused regression tests first, then formatting, lint, type checking, unit
|
|
|
290
296
|
tests, and the actual affected runtime. Apply only the relevant lanes from
|
|
291
297
|
[the change-boundary matrix](references/change-boundary-matrix.md).
|
|
292
298
|
|
|
293
|
-
After local verification
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
299
|
+
After local verification, execute the frozen review plan for the effective level
|
|
300
|
+
and governing repository. The independent reviewer compares the implementation
|
|
301
|
+
and observed outcomes to the frozen To-Be and original request, including affected
|
|
302
|
+
cross-view links, omissions and applicable historical regressions. Fix findings
|
|
303
|
+
narrowly and independently re-review the affected behavior.
|
|
297
304
|
|
|
298
305
|
Give the independent verifier the acceptance sources and raw evidence, not just
|
|
299
306
|
the implementer's summary. Use a separate session/agent for every review; another model can help but model count is not quality evidence.
|
|
@@ -308,11 +315,14 @@ production configuration, and CI or security-policy changes.
|
|
|
308
315
|
|
|
309
316
|
### 4. Coordinate through Draft PR and integration state
|
|
310
317
|
|
|
311
|
-
Before creating a PR, pass the independent To-Be review and pre-PR SQM loop.
|
|
312
318
|
After authority for the required remote changes exists, record reproduction,
|
|
313
319
|
tests, evidence, companion revisions, skipped checks, and remaining gates in the
|
|
314
|
-
Draft PR
|
|
315
|
-
|
|
320
|
+
Draft PR so the exact remote candidate can be inspected. Before Ready or merge,
|
|
321
|
+
pass the reviews and explicitly opted-in SQM gates required by the frozen plan.
|
|
322
|
+
Rerun a review or SQM gate only when its bound head,
|
|
323
|
+
base, diff, specification, policy, evidence, environment or SQM bundle changed,
|
|
324
|
+
or when a PR-only check became applicable. Otherwise retain the verified receipt
|
|
325
|
+
and record its exact identity instead of duplicating ceremony.
|
|
316
326
|
Before Ready or merge, combine the latest base with required companion
|
|
317
327
|
and parallel changes, rerun the affected path, and confirm current CI and
|
|
318
328
|
mergeability. Without combined-state proof, report `pr_only_verified`, not
|
|
@@ -342,6 +352,13 @@ remote merge result. Wait until the target environment reports the exact merge
|
|
|
342
352
|
revision or a verifiably derived image digest. Confirm health and runtime
|
|
343
353
|
identity before live verification.
|
|
344
354
|
|
|
355
|
+
For a production-impacting change, release through the frozen stages. At each
|
|
356
|
+
stage observe the named outcome and guardrail signals for the frozen window, then
|
|
357
|
+
apply the deterministic decision: promote only when all promotion thresholds pass;
|
|
358
|
+
hold when evidence is incomplete; abort or rollback when a halt threshold fires.
|
|
359
|
+
Verify the rollback mechanism and kill switch before exposure. Record the owner
|
|
360
|
+
and a receipt for every decision. A release plan is not evidence that a stage ran.
|
|
361
|
+
|
|
345
362
|
### 7. Verify the deployed user journey
|
|
346
363
|
|
|
347
364
|
Repeat the relevant Chrome journey against the deployed environment. Include
|
|
@@ -354,6 +371,10 @@ history or claim `done`. Save the exact revision, environment, input, Run ID,
|
|
|
354
371
|
timestamps, visible state, network evidence, and logs, then add a boundary
|
|
355
372
|
regression before re-entering implementation.
|
|
356
373
|
|
|
374
|
+
After the frozen observation window, evaluate the production outcome and guardrail
|
|
375
|
+
measures for the same experience IDs. A functioning deployment is not successful
|
|
376
|
+
delivery when the intended outcome misses its threshold or a guardrail is breached.
|
|
377
|
+
|
|
357
378
|
### Feed repaired delivery failures back into SQM
|
|
358
379
|
|
|
359
380
|
When an observed failure was repaired, prepare one bounded `delivery.json` record
|
|
@@ -374,10 +395,11 @@ and validation ordering still require Delivery Loop execution controls.
|
|
|
374
395
|
|
|
375
396
|
Remove scoped fixtures and prove the residual count is zero. Deliver a compact
|
|
376
397
|
completion receipt containing shared-spec baseline/To-Be revisions and status,
|
|
377
|
-
|
|
378
|
-
coverage gaps, repository revisions, PR and CI, independent
|
|
398
|
+
the frozen review plan and identity-bound review results, applicable SQM proofs
|
|
399
|
+
and their reuse/rerun decision, historical coverage gaps, repository revisions, PR and CI, independent
|
|
379
400
|
review, container/runtime results, local Chrome evidence, merge and deployment
|
|
380
|
-
identity,
|
|
401
|
+
identity, rollout-stage and outcome/guardrail results, deployed Chrome evidence,
|
|
402
|
+
artifacts, cleanup, skipped gates, and
|
|
381
403
|
residual risk. Convert recurring findings into the smallest maintainable rule,
|
|
382
404
|
test, static check, or source-of-truth update selected by the five-response
|
|
383
405
|
comparison. Bound debt cleanup by scope, change size, and completion criteria;
|
package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/acceptance-evidence.md
CHANGED
|
@@ -24,6 +24,13 @@ together for the beneficiary to succeed, include an end-to-end criterion in
|
|
|
24
24
|
addition to narrower diagnostic criteria. Independent coverage review compares
|
|
25
25
|
the experience contract and original request to the frozen rows before coding.
|
|
26
26
|
|
|
27
|
+
For production-relevant experience IDs, extend the same charter with outcome and
|
|
28
|
+
guardrail measures. Each measure names the signal, independent source,
|
|
29
|
+
observation window, threshold, resulting decision and owner. A rollout policy
|
|
30
|
+
references those measure IDs for promotion and halt decisions. These fields are
|
|
31
|
+
part of the same acceptance source and readable results view, not a second
|
|
32
|
+
success checklist.
|
|
33
|
+
|
|
27
34
|
Each criterion has two layers:
|
|
28
35
|
|
|
29
36
|
- `user`: a goal-driven user journey with visible interactions and evidence of the
|
|
@@ -64,6 +71,11 @@ After every evaluated action (test, repair, review or changed inputs):
|
|
|
64
71
|
All rows, including pending/failed ones, stay visible. A green matrix cannot advance
|
|
65
72
|
an unrelated gate or prove merge/deployment. Validate again for the final environment.
|
|
66
73
|
|
|
74
|
+
During staged release, append the stage, exposure, observed window, measure
|
|
75
|
+
results and deterministic `promote`, `hold`, `abort` or `rollback` decision to
|
|
76
|
+
the current results and receipt. Planned thresholds are not observations. A
|
|
77
|
+
healthy deployment cannot replace a missed outcome or breached guardrail.
|
|
78
|
+
|
|
67
79
|
After the exact candidate is built in a production-like local environment, run
|
|
68
80
|
the complete experience and regenerate `checklist.md` for that same revision,
|
|
69
81
|
environment, fixture, and input. Read the user and system rows together as a
|
|
@@ -37,11 +37,11 @@ messages.
|
|
|
37
37
|
|
|
38
38
|
| Level | Name | Intended work | Verification and review policy |
|
|
39
39
|
| --- | --- | --- | --- |
|
|
40
|
-
| 1 | Maximum assurance | Authentication, payments, destructive or irreversible changes, production security/configuration, sensitive data, and risky migrations | Exercise all affected and adjacent invariants, failure/recovery and rollback paths
|
|
41
|
-
| 2 | Protected | Persistence, permissions, shared contracts, external side effects, cross-repository changes, and medium-risk migrations | Verify both evidence layers
|
|
42
|
-
| 3 | Balanced (default) | Normal features and bug fixes with bounded, reversible impact | Run focused regressions, applicable static checks, the real affected runtime and main user journey
|
|
43
|
-
| 4 | Fast | Small, isolated, reversible UI or implementation changes | Run the direct regression and real affected path
|
|
44
|
-
| 5 | Fastest | Copy, documentation, comments, metadata, or similarly trivial changes with no runtime/data/security effect | Verify the
|
|
40
|
+
| 1 | Maximum assurance | Authentication, payments, destructive or irreversible changes, production security/configuration, sensitive data, and risky migrations | Exercise all affected and adjacent invariants, failure/recovery and rollback paths. Use separate independent design, implementation-boundary, and final PR/evidence reviews plus every repository gate. |
|
|
41
|
+
| 2 | Protected | Persistence, permissions, shared contracts, external side effects, cross-repository changes, and medium-risk migrations | Verify both evidence layers, shared boundaries, retry/idempotency, staged rollout and recovery. Require independent boundary/design and final candidate/integration review; combine them only when the reviewed inputs are exactly identical. |
|
|
42
|
+
| 3 | Balanced (default) | Normal features and bug fixes with bounded, reversible impact | Run focused regressions, applicable static checks, the real affected runtime and main user journey. One independent final-candidate review may cover design, implementation, affected views and evidence; repeat only when its bound identity changes. |
|
|
43
|
+
| 4 | Fast | Small, isolated, reversible UI or implementation changes | Run the direct regression and real affected path, adding shared-boundary checks only when touched. Use a scoped independent diff/actual-path review when repository policy or material ambiguity requires it. |
|
|
44
|
+
| 5 | Fastest | Copy, documentation, comments, metadata, or similarly trivial changes with no runtime/data/security effect | Verify the artifact, final diff, packaging/link integrity and repository-mandated checks. Independent review is needed only when governing policy requires it or material ambiguity remains. |
|
|
45
45
|
|
|
46
46
|
Level 3 is the recommendation when no task-specific signal favors another level.
|
|
47
47
|
Faster levels reduce work only by declaring genuinely unaffected lanes not
|
|
@@ -69,8 +69,9 @@ always choose a lower numbered, safer level.
|
|
|
69
69
|
Every level preserves:
|
|
70
70
|
|
|
71
71
|
- frozen success criteria and independent acceptance sources;
|
|
72
|
-
- shared system As-Is/To-Be
|
|
73
|
-
-
|
|
72
|
+
- shared system As-Is/To-Be and consistency of affected cross-view links;
|
|
73
|
+
- the frozen risk-proportionate review plan and every governing repository review;
|
|
74
|
+
- SQM only under explicit opt-in, with identity-bound proof and historical coverage reported;
|
|
74
75
|
- honest state transitions and current revision/context binding;
|
|
75
76
|
- required user/system evidence for applicable outcomes;
|
|
76
77
|
- protection of user work, secrets, data integrity, and tenant boundaries;
|
|
@@ -78,3 +79,16 @@ Every level preserves:
|
|
|
78
79
|
- repository-required tests, reviews, CI, and approval/authority boundaries.
|
|
79
80
|
|
|
80
81
|
All levels retain the [minimum functional floor](minimum-completion.md): requirement mapping, actual operation/result, and independent postcondition/integration observations. Persistence requires reload and stored-state checks. Non-runtime work verifies its real consumer/artifact; no imaginary DB or API checks are added. The minimum checker has no level-based bypass.
|
|
82
|
+
|
|
83
|
+
## Reuse instead of duplicate ceremony
|
|
84
|
+
|
|
85
|
+
Freeze the review and SQM plan in the charter. Reuse a passing review or SQM
|
|
86
|
+
proof only when its repository, head, base, working-tree/diff, specification,
|
|
87
|
+
policy, knowledge bundle, evidence and relevant environment identities are exactly
|
|
88
|
+
unchanged and the proof remains verifiable. A PR URL alone is not a changed input.
|
|
89
|
+
Rerun the affected review or SQM phase when any bound identity changes or when a
|
|
90
|
+
PR-only scanner, policy or integration check first becomes applicable.
|
|
91
|
+
|
|
92
|
+
Do not reopen or re-attest every shared view. Inspect the changed views and their
|
|
93
|
+
declared dependency links; retain unchanged views by exact revision. Do not turn a
|
|
94
|
+
failed, unavailable or applicable gate into `not_applicable` to save time.
|
package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/minimum-completion.md
CHANGED
|
@@ -139,8 +139,8 @@ external provider calls are introduced.
|
|
|
139
139
|
|
|
140
140
|
The floor's stable criterion rows trace back to requirement IDs in the team's shared
|
|
141
141
|
As-Is/To-Be specification. Follow [shared system specifications](shared-system-specifications.md)
|
|
142
|
-
for purpose, user experience, cross-view consistency, independent
|
|
143
|
-
|
|
142
|
+
for purpose, user experience, cross-view consistency, risk-proportionate independent
|
|
143
|
+
reviews and explicitly opted-in, identity-aware SQM. These are controller workflow obligations, not fields magically
|
|
144
144
|
validated by the minimum checker. The CLI gate verifies minimum structured evidence;
|
|
145
145
|
it does not launch every design review or SQM phase on its own. Standalone hosts
|
|
146
146
|
remain responsible for executing this skill and cannot claim an enforced host hook.
|
|
@@ -34,9 +34,11 @@ At the start of each run:
|
|
|
34
34
|
5. Link each experience ID to workflow, screen/control, state/sequence, API/event,
|
|
35
35
|
data/relationship, permission and runtime boundaries as applicable. Map these
|
|
36
36
|
stable system IDs to the run's criterion rows and implementation/evidence locations.
|
|
37
|
-
6.
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
6. Freeze the delivery-level review plan. At levels that require a separate
|
|
38
|
+
design review, obtain it before implementation; at level 3 the independent
|
|
39
|
+
final-candidate review may cover design, implementation and evidence together.
|
|
40
|
+
Supply the original request, shared baseline, To-Be and affected links. Missing
|
|
41
|
+
evidence or contradictory views remains pending/failed, never silently accepted.
|
|
40
42
|
|
|
41
43
|
After the exact local candidate is built, update the existing acceptance matrix
|
|
42
44
|
and its readable table for those same experience IDs. Compare expected experience,
|
|
@@ -68,13 +70,15 @@ interface views; do not invent application screens, APIs, tables or infrastructu
|
|
|
68
70
|
|
|
69
71
|
## Review evidence and neutral agents
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
Required reviews use independent agents/sessions; an agent must not approve work
|
|
74
|
+
it authored. Follow the risk-proportionate plan in `delivery-levels.md` instead of
|
|
75
|
+
creating design, cross-view, implementation and PR reviews by default. A reviewer
|
|
76
|
+
may cover several review kinds in one receipt when the candidate inputs are the
|
|
77
|
+
same, and can re-review fixes it did not implement. Supply raw sources, not desired
|
|
78
|
+
answers; require inspected references, discrepancies, uncertainty and a reasoned
|
|
79
|
+
verdict. Use the repository-required model (gpt-5.5 / xhigh where mandated and
|
|
80
|
+
available). If a required independent review is unavailable, report that gate as
|
|
81
|
+
blocked.
|
|
78
82
|
|
|
79
83
|
Persist a compact review receipt: reviewer/session identity, review kind, original
|
|
80
84
|
request and shared baseline/To-Be references, candidate revisions, inspected views
|
|
@@ -122,17 +126,22 @@ Use concrete regressions for relevant uncovered incidents and have an independen
|
|
|
122
126
|
reviewer assess coverage; keep missing incident history or untested boundaries
|
|
123
127
|
visible. No finite test promises absence of all future bugs.
|
|
124
128
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
129
|
+
Draft creation: after authority and local regressions, publish a Draft so the exact
|
|
130
|
+
remote candidate can be inspected. Draft existence is not gate approval.
|
|
131
|
+
|
|
132
|
+
Before Ready or merge, pass the frozen review plan. When the explicitly opted-in
|
|
133
|
+
plan requires SQM, run it against the final candidate; repair findings within the
|
|
134
|
+
bounded loop and rerun affected gates. On an unavailable/failed required proof,
|
|
135
|
+
retain Draft/not-ready and report the exact blocker while continuing independent
|
|
136
|
+
authorized preparation.
|
|
137
|
+
|
|
138
|
+
Post-PR: fetch and verify the actual PR head/base and current CI. Reuse the pre-PR
|
|
139
|
+
SQM proof only when repository, head, base, working-tree/diff, specification,
|
|
140
|
+
policy, knowledge bundle, evidence and relevant environment identities are exactly
|
|
141
|
+
unchanged and the signed proof verifies. Rerun into a new path when any identity
|
|
142
|
+
changed or a PR-only scanner/policy becomes applicable. Apply the same rule to
|
|
143
|
+
independent review. If a required gate fails, retain the PR as draft/not-ready,
|
|
144
|
+
repair and rerun affected gates. Preserve superseded receipts as history.
|
|
136
145
|
Promote Ready only with current required gates, including applicable combined-state
|
|
137
146
|
verification. Merge and deployment still require their own authority and evidence.
|
|
138
147
|
|
package/src/codex-plugins/simy/skills/agentic-delivery-loop/references/state-and-receipts.md
CHANGED
|
@@ -22,7 +22,8 @@ Persist one controller-owned snapshot with at least:
|
|
|
22
22
|
- frozen acceptance charter digest, current matrix/table paths and digests,
|
|
23
23
|
superseded matrix snapshots, and the acceptance validator result for each gate;
|
|
24
24
|
- verification-boundary changes, deferred-debt references, and applicable
|
|
25
|
-
outcome and guardrail measures
|
|
25
|
+
outcome and guardrail measures, rollout policy, current rollout stage and
|
|
26
|
+
latest deterministic release decision;
|
|
26
27
|
- attempt number, retry/time/cost budgets, and failure fingerprints;
|
|
27
28
|
- append-only receipt IDs, evidence references, timestamps, and cleanup state.
|
|
28
29
|
|
|
@@ -46,6 +47,8 @@ Use the smallest applicable receipts rather than free-form completion claims:
|
|
|
46
47
|
- `ChromeUserJourneyReceipt`
|
|
47
48
|
- `MergeReceipt`
|
|
48
49
|
- `DeploymentIdentityReceipt`
|
|
50
|
+
- `RolloutStageReceipt`
|
|
51
|
+
- `OutcomeEvaluationReceipt`
|
|
49
52
|
- `HealthReceipt`
|
|
50
53
|
- `LiveEvidenceReceipt`
|
|
51
54
|
- `CleanupReceipt`
|
|
@@ -108,6 +111,8 @@ Evidence is revision-bound:
|
|
|
108
111
|
| Merge SHA changes | Deployment identity and live evidence |
|
|
109
112
|
| Deployed revision changes | Health and live evidence |
|
|
110
113
|
| Browser profile, tenant, or fixture changes | Affected user-journey evidence |
|
|
114
|
+
| Outcome/guardrail signal, source, window, threshold, decision, or owner changes | Affected release and outcome evidence |
|
|
115
|
+
| Rollout stage, exposure, recovery control, or kill switch changes | Affected rollout and later live evidence |
|
|
111
116
|
|
|
112
117
|
Do not discard historical receipts; mark them superseded for the current gate.
|
|
113
118
|
|
|
@@ -146,11 +151,13 @@ done =
|
|
|
146
151
|
&& deployed_exact_revision
|
|
147
152
|
&& health_verified
|
|
148
153
|
&& live_verified
|
|
154
|
+
&& production_outcome_evaluated
|
|
149
155
|
&& cleanup_verified
|
|
150
156
|
&& completion_receipt_created
|
|
151
157
|
```
|
|
152
158
|
|
|
153
|
-
Remove only genuinely non-applicable terms and record why
|
|
159
|
+
Remove only genuinely non-applicable terms and record why; production outcome
|
|
160
|
+
evaluation is non-applicable when no production-impacting release is in scope. If merge or deploy
|
|
154
161
|
is outside current authority, stop at the highest proven pre-authority state.
|
|
155
162
|
|
|
156
163
|
Acceptance evidence must cover every applicable criterion for the target gate,
|
package/src/codex-plugins/simy/skills/agentic-delivery-loop/scripts/check-minimum-completion.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { lstat, readFile, realpath } from "node:fs/promises";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { isDeepStrictEqual } from "node:util";
|
|
7
|
+
import { normalizeProductionContract } from "./production-contract.mjs";
|
|
7
8
|
import {
|
|
8
9
|
checkAcceptance,
|
|
9
10
|
contextDigest,
|
|
@@ -49,6 +50,7 @@ export function minimumCharter(charter) {
|
|
|
49
50
|
run_id: charter.id,
|
|
50
51
|
source,
|
|
51
52
|
experience,
|
|
53
|
+
...normalizeProductionContract(charter.completion_contract, ids),
|
|
52
54
|
criteria: charter.acceptance_criteria.map((outcome, index) => ({
|
|
53
55
|
id: ids[index],
|
|
54
56
|
outcome,
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// Shared by the CLI and the independently installed skill. Keep this module
|
|
2
|
+
// self-contained so validation never depends on the repository checkout.
|
|
3
|
+
const cleanString = value => typeof value === "string" ? value.trim() : "";
|
|
4
|
+
const record = value => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5
|
+
const uniqueStrings = value => [...new Set(Array.isArray(value) ? value.map(cleanString).filter(Boolean) : [])];
|
|
6
|
+
const criterionIdPattern = /^[A-Za-z][A-Za-z0-9]*(?:[-_.][A-Za-z0-9]+)*$/;
|
|
7
|
+
|
|
8
|
+
export function normalizeProductionContract(source, ids) {
|
|
9
|
+
const outcome_contract = normalizeOutcomeContract(source.outcome_contract, ids);
|
|
10
|
+
return { outcome_contract, rollout_policy: normalizeRolloutPolicy(source.rollout_policy, outcome_contract) };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function normalizeOutcomeContract(value, criterionIds) {
|
|
14
|
+
const source = record(value);
|
|
15
|
+
const criteria = new Set(criterionIds);
|
|
16
|
+
const outcomeMeasures = normalizeMeasures(
|
|
17
|
+
source.outcome_measures,
|
|
18
|
+
criteria,
|
|
19
|
+
new Set(["promote", "hold"]),
|
|
20
|
+
"outcome",
|
|
21
|
+
);
|
|
22
|
+
const guardrailMeasures = normalizeMeasures(
|
|
23
|
+
source.guardrail_measures,
|
|
24
|
+
criteria,
|
|
25
|
+
new Set(["hold", "abort", "rollback"]),
|
|
26
|
+
"guardrail",
|
|
27
|
+
);
|
|
28
|
+
const allIds = [
|
|
29
|
+
...outcomeMeasures.map((measure) => measure.id),
|
|
30
|
+
...guardrailMeasures.map((measure) => measure.id),
|
|
31
|
+
];
|
|
32
|
+
if (new Set(allIds).size !== allIds.length) {
|
|
33
|
+
throw new Error("Duplicate outcome or guardrail measure IDs");
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
outcome_measures: outcomeMeasures,
|
|
37
|
+
guardrail_measures: guardrailMeasures,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function normalizeMeasures(value, criterionIds, allowedDecisions, kind) {
|
|
42
|
+
if (value === undefined || value === null) return [];
|
|
43
|
+
if (!Array.isArray(value)) throw new Error(`Invalid ${kind} measures`);
|
|
44
|
+
const measures = value.map((item) => {
|
|
45
|
+
const source = record(item);
|
|
46
|
+
const measure = {
|
|
47
|
+
id: cleanString(source.id),
|
|
48
|
+
criterion_id: cleanString(source.criterion_id),
|
|
49
|
+
signal: cleanString(source.signal),
|
|
50
|
+
source: cleanString(source.source),
|
|
51
|
+
window: cleanString(source.window),
|
|
52
|
+
threshold: cleanString(source.threshold),
|
|
53
|
+
decision: cleanString(source.decision).toLowerCase(),
|
|
54
|
+
owner: cleanString(source.owner),
|
|
55
|
+
};
|
|
56
|
+
if (
|
|
57
|
+
!criterionIdPattern.test(measure.id) ||
|
|
58
|
+
!criterionIds.has(measure.criterion_id) ||
|
|
59
|
+
!measure.signal ||
|
|
60
|
+
!measure.source ||
|
|
61
|
+
!measure.window ||
|
|
62
|
+
!measure.threshold ||
|
|
63
|
+
!allowedDecisions.has(measure.decision) ||
|
|
64
|
+
!measure.owner
|
|
65
|
+
) {
|
|
66
|
+
throw new Error(`Invalid ${kind} measure`);
|
|
67
|
+
}
|
|
68
|
+
return measure;
|
|
69
|
+
});
|
|
70
|
+
if (new Set(measures.map((measure) => measure.id)).size !== measures.length) {
|
|
71
|
+
throw new Error(`Duplicate ${kind} measure IDs`);
|
|
72
|
+
}
|
|
73
|
+
return measures;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function normalizeRolloutPolicy(value, outcomeContract) {
|
|
77
|
+
const source = record(value);
|
|
78
|
+
const required = source.required === true;
|
|
79
|
+
if (!required) {
|
|
80
|
+
return {
|
|
81
|
+
required: false,
|
|
82
|
+
reason: cleanString(source.reason) || "No production rollout is in scope",
|
|
83
|
+
stages: [],
|
|
84
|
+
promotion_requires: [],
|
|
85
|
+
halt_on: [],
|
|
86
|
+
rollback: null,
|
|
87
|
+
kill_switch: null,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const stages = normalizeRolloutStages(source.stages);
|
|
91
|
+
const outcomeIds = new Set(
|
|
92
|
+
outcomeContract.outcome_measures.map((measure) => measure.id),
|
|
93
|
+
);
|
|
94
|
+
const guardrailIds = new Set(
|
|
95
|
+
outcomeContract.guardrail_measures.map((measure) => measure.id),
|
|
96
|
+
);
|
|
97
|
+
const promotionRequires = uniqueStrings(source.promotion_requires);
|
|
98
|
+
const haltOn = uniqueStrings(source.halt_on);
|
|
99
|
+
const rollback = normalizeRecoveryControl(source.rollback, "rollback");
|
|
100
|
+
const killSwitch = normalizeRecoveryControl(source.kill_switch, "kill switch");
|
|
101
|
+
if (
|
|
102
|
+
stages.length < 2 ||
|
|
103
|
+
outcomeIds.size === 0 ||
|
|
104
|
+
promotionRequires.length !== outcomeIds.size ||
|
|
105
|
+
promotionRequires.some((id) => !outcomeIds.has(id)) ||
|
|
106
|
+
guardrailIds.size === 0 ||
|
|
107
|
+
haltOn.length !== guardrailIds.size ||
|
|
108
|
+
haltOn.some((id) => !guardrailIds.has(id))
|
|
109
|
+
) {
|
|
110
|
+
throw new Error("Invalid progressive rollout policy");
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
required: true,
|
|
114
|
+
reason: cleanString(source.reason) || "Production impact requires progressive exposure",
|
|
115
|
+
stages,
|
|
116
|
+
promotion_requires: promotionRequires,
|
|
117
|
+
halt_on: haltOn,
|
|
118
|
+
rollback,
|
|
119
|
+
kill_switch: killSwitch,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function normalizeRolloutStages(value) {
|
|
124
|
+
if (!Array.isArray(value)) throw new Error("Invalid rollout stages");
|
|
125
|
+
const stages = value.map((item) => {
|
|
126
|
+
const source = record(item);
|
|
127
|
+
const stage = {
|
|
128
|
+
id: cleanString(source.id),
|
|
129
|
+
exposure: cleanString(source.exposure),
|
|
130
|
+
observation_window: cleanString(source.observation_window),
|
|
131
|
+
};
|
|
132
|
+
if (
|
|
133
|
+
!criterionIdPattern.test(stage.id) ||
|
|
134
|
+
!stage.exposure ||
|
|
135
|
+
!stage.observation_window
|
|
136
|
+
) {
|
|
137
|
+
throw new Error("Invalid rollout stage");
|
|
138
|
+
}
|
|
139
|
+
return stage;
|
|
140
|
+
});
|
|
141
|
+
if (new Set(stages.map((stage) => stage.id)).size !== stages.length) {
|
|
142
|
+
throw new Error("Duplicate rollout stage IDs");
|
|
143
|
+
}
|
|
144
|
+
return stages;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function normalizeRecoveryControl(value, label) {
|
|
148
|
+
const source = record(value);
|
|
149
|
+
const control = {
|
|
150
|
+
mechanism: cleanString(source.mechanism),
|
|
151
|
+
owner: cleanString(source.owner),
|
|
152
|
+
};
|
|
153
|
+
if (!control.mechanism || !control.owner) {
|
|
154
|
+
throw new Error(`Invalid ${label} control`);
|
|
155
|
+
}
|
|
156
|
+
return control;
|
|
157
|
+
}
|
|
158
|
+
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeProductionContract } from "../codex-plugins/simy/skills/agentic-delivery-loop/scripts/production-contract.mjs";
|
|
1
2
|
import { cleanString, stringArray } from "./shared.js";
|
|
2
3
|
|
|
3
4
|
export const COMPLETION_CONTRACT_VERSION = 2;
|
|
@@ -15,13 +16,16 @@ export function buildCompletionContract({
|
|
|
15
16
|
const proofRequired = stringArray(source.proof_required);
|
|
16
17
|
const criteria = stringArray(acceptanceCriteria);
|
|
17
18
|
const userOutcome = cleanString(source.user_outcome) || cleanString(requirement);
|
|
19
|
+
const ids = criterionIds(source.criterion_ids, criteria.length);
|
|
20
|
+
const productionContract = normalizeProductionContract(source, ids);
|
|
18
21
|
return {
|
|
19
22
|
version: COMPLETION_CONTRACT_VERSION,
|
|
20
23
|
user_outcome: userOutcome,
|
|
21
24
|
minimum_scope:
|
|
22
25
|
minimumScope.length > 0 ? minimumScope : criteria,
|
|
23
|
-
criterion_ids:
|
|
26
|
+
criterion_ids: ids,
|
|
24
27
|
experience: normalizeExperience(source.experience, userOutcome),
|
|
28
|
+
...productionContract,
|
|
25
29
|
non_goals: stringArray(nonGoals),
|
|
26
30
|
proof_required: uniqueStrings([
|
|
27
31
|
"criterion_evidence",
|
|
@@ -65,6 +65,9 @@ export function buildIndependentAuditInstruction(charter, attempt) {
|
|
|
65
65
|
"Treat executor claims as untrusted until supported by repository evidence.",
|
|
66
66
|
"Compare the original request and frozen experience to the complete stable criterion-ID list and implementation mapping. Report forgotten features, dead controls, unsaved results and broken integration. Open the raw minimum evidence, verify its oracle and actual runtime observations; matching expected/actual JSON and hashes alone do not prove truth. Check reload/session return and persisted values/ownership when saving is required.",
|
|
67
67
|
"For every stable criterion ID, return a criterion_results entry only after directly checking its cited proof and observed outcome.",
|
|
68
|
+
"For production-relevant criteria, verify that each outcome and guardrail measure names its signal, independent source, observation window, threshold, decision, owner, and criterion ID.",
|
|
69
|
+
"When rollout_policy.required=true, verify that staged exposure and deterministic promote, hold, abort, rollback, and kill-switch controls are frozen before release. Do not treat a rollout plan as deployed evidence.",
|
|
70
|
+
"Apply the frozen delivery-level review plan: reuse a prior review only when its exact head, base, specification, policy, evidence, and environment identities are unchanged; otherwise review the affected boundary again.",
|
|
68
71
|
charter.evidence_policy?.browser_required
|
|
69
72
|
? "Open and inspect the actual local screenshots or videos. Return visual_review.inspected=true only after checking their visible content against the acceptance criteria."
|
|
70
73
|
: "Do not require visual evidence when the Charter does not require browser evidence.",
|
|
@@ -43,6 +43,9 @@ export function buildCodingInstruction(
|
|
|
43
43
|
`Usable outcome: ${charter.completion_contract?.experience?.usable_outcome || "not recorded"}`,
|
|
44
44
|
`Recovery experience: ${charter.completion_contract?.experience?.recovery || "not recorded"}`,
|
|
45
45
|
`Forbidden experiences:\n${bullets(charter.completion_contract?.experience?.forbidden_experiences || [])}`,
|
|
46
|
+
`Outcome measures: ${JSON.stringify(charter.completion_contract?.outcome_contract?.outcome_measures || [])}`,
|
|
47
|
+
`Guardrail measures: ${JSON.stringify(charter.completion_contract?.outcome_contract?.guardrail_measures || [])}`,
|
|
48
|
+
`Progressive rollout policy: ${JSON.stringify(charter.completion_contract?.rollout_policy || { required: false })}`,
|
|
46
49
|
`Minimum scope:\n${bullets(charter.completion_contract?.minimum_scope || charter.acceptance_criteria)}`,
|
|
47
50
|
`Non-goals:\n${bullets(charter.completion_contract?.non_goals || charter.thread_state.non_goals)}`,
|
|
48
51
|
`Proof required:\n${bullets(charter.completion_contract?.proof_required || [])}`,
|