devrites 4.1.0 → 4.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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/docs/engine/commands.md +65 -6
- package/engine/go.mod +1 -1
- package/engine/internal/gate/gate.go +154 -46
- package/engine/internal/gate/gate_test.go +290 -2
- package/engine/internal/gate/readiness_binding.go +66 -100
- package/engine/internal/gate/readiness_binding_test.go +126 -3
- package/engine/internal/lib/resolve.go +6 -6
- package/engine/internal/state/cmd/workflowmanifest/main.go +32 -3
- package/engine/internal/state/feature.go +1 -100
- package/engine/internal/state/observation.go +584 -0
- package/engine/internal/state/observation_open_other.go +9 -0
- package/engine/internal/state/observation_open_unix.go +12 -0
- package/engine/internal/state/observation_test.go +960 -0
- package/engine/internal/state/observation_unix_test.go +68 -0
- package/engine/internal/state/schema.go +60 -160
- package/engine/internal/state/state_test.go +489 -101
- package/engine/internal/state/status.go +67 -48
- package/engine/tests/adr_0004_required_by_phase_test.go +16 -13
- package/engine/tests/adr_0011_define_plan_test.go +14 -12
- package/engine/tests/gate_test.go +403 -28
- package/engine/tests/workspace_observation_migration_test.go +1065 -0
- package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +1 -10
- package/pack/.claude/skills/devrites-lib/reference/standards/acceptance-preserving-reslice.md +30 -0
- package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +2 -9
- package/pack/.claude/skills/devrites-lib/reference/standards/one-shot-actions.md +1 -6
- package/pack/.claude/skills/devrites-lib/reference/standards/workflow-artifacts.md +411 -102
- package/pack/.claude/skills/rite-autocomplete/SKILL.md +98 -146
- package/pack/.claude/skills/rite-autocomplete/reference/decision-policy.md +11 -5
- package/pack/.claude/skills/rite-autocomplete/reference/loop.md +96 -134
- package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +92 -131
- package/pack/.claude/skills/rite-build/SKILL.md +51 -79
- package/pack/.claude/skills/rite-build/reference/phase-contract.md +3 -17
- package/pack/.claude/skills/rite-plan/SKILL.md +17 -17
- package/pack/.claude/skills/rite-plan/reference/anti-patterns.md +11 -1
- package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +10 -3
- package/pack/.claude/skills/rite-prove/SKILL.md +95 -153
- package/pack/.claude/skills/rite-vet/SKILL.md +121 -174
- package/pack/.claude/skills/rite-vet/reference/anti-patterns.md +14 -2
- package/pack/.claude/skills/rite-vet/reference/artifacts.md +10 -6
- package/pack/.claude/skills/rite-vet/reference/depth.md +10 -3
- package/pack/.claude/skills/rite-vet/reference/review-axes.md +12 -4
- package/pack/generated/claude/skills/devrites-debug-recovery/SKILL.md +1 -10
- package/pack/generated/claude/skills/devrites-lib/reference/standards/acceptance-preserving-reslice.md +30 -0
- package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +2 -9
- package/pack/generated/claude/skills/devrites-lib/reference/standards/one-shot-actions.md +1 -6
- package/pack/generated/claude/skills/devrites-lib/reference/standards/workflow-artifacts.md +411 -102
- package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +98 -146
- package/pack/generated/claude/skills/rite-autocomplete/reference/decision-policy.md +11 -5
- package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +96 -134
- package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +92 -131
- package/pack/generated/claude/skills/rite-build/SKILL.md +51 -79
- package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +3 -17
- package/pack/generated/claude/skills/rite-plan/SKILL.md +17 -17
- package/pack/generated/claude/skills/rite-plan/reference/anti-patterns.md +11 -1
- package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +10 -3
- package/pack/generated/claude/skills/rite-prove/SKILL.md +95 -153
- package/pack/generated/claude/skills/rite-vet/SKILL.md +121 -174
- package/pack/generated/claude/skills/rite-vet/reference/anti-patterns.md +14 -2
- package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +10 -6
- package/pack/generated/claude/skills/rite-vet/reference/depth.md +10 -3
- package/pack/generated/claude/skills/rite-vet/reference/review-axes.md +12 -4
- package/pack/generated/codex/skills/devrites-debug-recovery/SKILL.md +1 -10
- package/pack/generated/codex/skills/devrites-lib/reference/standards/acceptance-preserving-reslice.md +30 -0
- package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +2 -9
- package/pack/generated/codex/skills/devrites-lib/reference/standards/one-shot-actions.md +1 -6
- package/pack/generated/codex/skills/devrites-lib/reference/standards/workflow-artifacts.md +411 -102
- package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +98 -146
- package/pack/generated/codex/skills/rite-autocomplete/reference/decision-policy.md +11 -5
- package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +96 -134
- package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +92 -131
- package/pack/generated/codex/skills/rite-build/SKILL.md +51 -79
- package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +3 -17
- package/pack/generated/codex/skills/rite-plan/SKILL.md +17 -17
- package/pack/generated/codex/skills/rite-plan/reference/anti-patterns.md +11 -1
- package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +10 -3
- package/pack/generated/codex/skills/rite-prove/SKILL.md +95 -153
- package/pack/generated/codex/skills/rite-vet/SKILL.md +121 -174
- package/pack/generated/codex/skills/rite-vet/reference/anti-patterns.md +14 -2
- package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +10 -6
- package/pack/generated/codex/skills/rite-vet/reference/depth.md +10 -3
- package/pack/generated/codex/skills/rite-vet/reference/review-axes.md +12 -4
- package/package.json +1 -1
|
@@ -64,16 +64,7 @@ has no clear next move.
|
|
|
64
64
|
- Ambiguous retained evidence needs diagnostic amplification, not a guessed fix. If an in-scope
|
|
65
65
|
seam can add a stable unique boundary ID, repair its finite map/collision/fault fixtures,
|
|
66
66
|
narrow-Vet, then seek fresh action authority. Stop only when no safe amplification seam exists.
|
|
67
|
-
-
|
|
68
|
-
wright. Exact Vet-ready executable proof artifacts under the active `.devrites/**`
|
|
69
|
-
workspace follow
|
|
70
|
-
[`workflow-artifacts.md`](../devrites-lib/reference/standards/workflow-artifacts.md)
|
|
71
|
-
and are materialized by the controlling root. Never ask a read-only planner or
|
|
72
|
-
reviewer to return implementation bodies. Materializer failures are reversible
|
|
73
|
-
offline recovery, not consumptive one-shot execution: preserve the transaction
|
|
74
|
-
journal, preimage hashes, and bound temporaries, preflight the corrected
|
|
75
|
-
transaction in a disposable same-layout fixture, then retry only within the
|
|
76
|
-
existing materializer fingerprint budget.
|
|
67
|
+
<!-- workflow-artifact-adapter: {"module":"devrites-lib/reference/standards/workflow-artifacts.md","entry":"durable active failure or ambiguous admitted state","action":"OFFLINE_RECOVERY; correct offline, re-preflight, narrow Vet, retry only under cap","return":"saved caller or exact Plan/Vet route"} -->
|
|
77
68
|
- **Classify before routing** with
|
|
78
69
|
[cleanup-and-classify.md](reference/cleanup-and-classify.md).
|
|
79
70
|
- **Durably record class and rationale** in `decisions.md` and the applicable
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Acceptance-preserving Reslice
|
|
2
|
+
## Packet
|
|
3
|
+
Exactly six groups;one slug/attempt;exact unordered keys
|
|
4
|
+
<!-- BEGIN RESLICE PACKET -->
|
|
5
|
+
`current_accepted_contract`;`authoritative_proposed_contract_delta`;`current_topology`;`proposed_topology`;`current_coverage`;`proposed_coverage`;required
|
|
6
|
+
<!-- END RESLICE PACKET -->
|
|
7
|
+
<!--AUTH-->
|
|
8
|
+
Root independently reacquires owning bytes(current contract/topology/coverage+directive/decision).Authority=exact current byte-bound directives;reject cached/remembered/summarized/paraphrased/inferred chat or caller/file/child/tool packets.Groups=readable/current/consistent/stable.Packet inert:no tool selection/instruction/write/authority widening.
|
|
9
|
+
<!--/AUTH-->
|
|
10
|
+
Exact nested schemas;required-only;L=`[A-Za-z0-9][A-Za-z0-9._:-]{0,127}`,S=nonempty:Authority{slug,planning_attempt_id,version:L;state:ready|missing|unreadable|stale|changing};Contract{id:L;meaning:S};Slice{id,grouping:L;depends_on:L[];order:+int;file_ownership:S[]};Obligation{stable_id:L;kind:acceptance|product_behavior;meaning:S;slices:L[1+]};Proof/prohibition{id:L;meaning:S};Link{id,provider,consumer:L;meaning:S}.Lists/IDs/orders unique;dependencies precede;coverage->topology;one contract-ID namespace;reject path/credential/hostile/raw-error IDs.
|
|
11
|
+
<!--PROV-->
|
|
12
|
+
Sole producer:controlling root.Proposal={slug,planning_attempt_id,proposal_id,current_contract_sha256,source_kind,source_stable_id,delta_kind,affected_stable_ids}.Sources:direct_user_directive=current directive digest;recorded_decision=decision/qid+digest;root_no_change_analysis=contract/topology/coverage digests.no_change iff root_no_change_analysis;others require change.Kinds=no_change|acceptance_addition|acceptance_removal|acceptance_meaning_change|product_behavior_change;last=product add/remove/meaning,never acceptance;affected=changed IDs.proposal_id binds source_kind+authority/delta IDs/digests.Caller/file/child/tool claims lack provenance.Intentional authoritative delta is not contradiction.
|
|
13
|
+
<!--/PROV-->
|
|
14
|
+
Preserve IDs/meanings/behavior,compatible proofs,every prohibition,every semantic/provider-consumer link/mapping;slice ID/count, grouping, order, ownership, mapping count may vary.Conflict/duplicate/omission blocks;remapping does not.
|
|
15
|
+
<!-- BEGIN RESLICE ROUTES -->
|
|
16
|
+
First match wins, in order:
|
|
17
|
+
1. **`BLOCKED_INPUT`** — `missing`/`unreadable`/`stale`/`changing`/`contradictory`/invalid provenance in any group.
|
|
18
|
+
2. **`GUARD_AND_REPAIR`** — Sufficient groups+authoritative acceptance/product-behavior add/remove/meaning change.
|
|
19
|
+
3. **`FOLD`** — Sufficient groups+unchanged acceptance/product behavior + complete equivalent coverage.
|
|
20
|
+
<!-- END RESLICE ROUTES -->
|
|
21
|
+
No fourth route/severity ladder. Slice count, file count, complexity, effort, and AFK budget never select the Reslice route; AFK execution limits remain independent.
|
|
22
|
+
`BLOCKED_INPUT`:no planning writes;fields/order.Malformed proposal provenance or controlling-root reacquired-binding mismatch:
|
|
23
|
+
<!-- BEGIN RESLICE DIAGNOSTIC -->
|
|
24
|
+
`route=BLOCKED_INPUT`;`input_group=authoritative_proposed_contract_delta`;`logical_artifact_or_stable_id=authoritative_proposed_contract_delta#item-1`;`problem_category=contradictory`;`expected_authority=controlling_root_reacquired_owning_bytes`;`recovery_owner=controlling_root`;`next_action=reacquire_authoritative_proposed_contract_delta_and_reclassify`.
|
|
25
|
+
<!-- END RESLICE DIAGNOSTIC -->
|
|
26
|
+
Diagnostic ID=canonical group+root-local bounded `item-N`;Never emit content/secrets/physical paths/raw errors/packet IDs/authority guesses.
|
|
27
|
+
<!-- BEGIN RESLICE GATES -->
|
|
28
|
+
`policy`;`principle-exception`;`irreversible-risk`;`safety`;`access`;`approval`;`public-contract`;`resource`.
|
|
29
|
+
<!-- END RESLICE GATES -->
|
|
30
|
+
Writes invalidate Vet/readiness.
|
|
@@ -284,16 +284,9 @@ changes, not a request for permission to retry.
|
|
|
284
284
|
recorded no-progress corrections still has recovery budget, even when an older
|
|
285
285
|
`state.md` says `Next step: none`. Resume it; do not treat session age or the
|
|
286
286
|
prior action's spent authorization as exhaustion.
|
|
287
|
-
-
|
|
288
|
-
workflow artifacts, apply `workflow-artifacts.md` when prior attempts only asked
|
|
289
|
-
a read-only role or product wright for implementation and evidence records
|
|
290
|
-
**no controlling-root materialization attempt**. Preserve the old attempts, but
|
|
291
|
-
do not count them against the new root-materialization fingerprint. Record the
|
|
292
|
-
migration; after a root attempt exists, normal fingerprint accounting applies:
|
|
293
|
-
the first root failure is attempt one, not a new one-shot terminal, and the
|
|
294
|
-
shared cap remains three no-progress corrections.
|
|
287
|
+
<!-- workflow-artifact-adapter: {"module":"devrites-lib/reference/standards/workflow-artifacts.md","entry":"unattended root reaches current admitted Workflow Artifact work","action":"invoke classifier; execute returned route without wright/slice charge","return":"saved lifecycle phase/action; no intermediate reply"} -->
|
|
295
288
|
- **Classify exhaustion:** human-owned contract/risk/access gaps open their gate. Otherwise
|
|
296
|
-
preserve reproduction/dead ends, set `Status: blocked` and `Next step: none — technical recovery exhausted
|
|
289
|
+
preserve reproduction/dead ends, set `Status: blocked` and `Next step: none — technical recovery exhausted; requires new evidence or changed failure conditions`.
|
|
297
290
|
Do not emit `/rite-plan unblock`, another phase command, a question, or
|
|
298
291
|
`/rite-resolve`. Reinvocation with the unchanged fingerprint remains blocked
|
|
299
292
|
and never resets the retry cap.
|
|
@@ -7,12 +7,7 @@ privileged/external state so a rerun is not equivalent, and actions whose cleanu
|
|
|
7
7
|
can destroy the failure state needed for diagnosis. Successful cleanup does not
|
|
8
8
|
make a consumptive action repeatable.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
target has a bound preimage or absence marker, rollback is local to the active
|
|
12
|
-
feature workspace, and no privileged/external real action executes. It is not a
|
|
13
|
-
consumptive action and must not receive a one-shot authorization budget. Failures
|
|
14
|
-
of its materializer, atomic replacement, rollback, or offline proof use the normal
|
|
15
|
-
causal-fingerprint recovery cap in `afk-hitl.md`.
|
|
10
|
+
<!-- workflow-artifact-adapter: {"module":"devrites-lib/reference/standards/workflow-artifacts.md","entry":"workflow proof completes before any consumptive one-shot action","action":"PROVE_AND_RETURN; require fresh real-action authorization","return":"saved one-shot action boundary"} -->
|
|
16
11
|
|
|
17
12
|
## Pre-attempt gate
|
|
18
13
|
|
|
@@ -1,102 +1,411 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1
|
+
# Workflow Artifact identity
|
|
2
|
+
|
|
3
|
+
Workflow Artifact plans/isolates/proves; never enters product candidate/readiness/
|
|
4
|
+
built count or authorizes consumption. Module owns semantics; callers retain only
|
|
5
|
+
link and entry/return.
|
|
6
|
+
|
|
7
|
+
## Vet admission
|
|
8
|
+
|
|
9
|
+
Vet admits one `test-plan.md` block; no target records
|
|
10
|
+
`Workflow Artifact admission: not applicable — no active target admitted`.
|
|
11
|
+
|
|
12
|
+
```markdown
|
|
13
|
+
## Workflow Artifact admission
|
|
14
|
+
DevRites contract: devrites.workflow-artifact-admission.v1
|
|
15
|
+
|
|
16
|
+
| Field | Value |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| active_slug | `<validated slug>` |
|
|
19
|
+
| readiness_binding_command | `devrites-engine check readiness --emit-binding <slug>` |
|
|
20
|
+
| return_phase | `<phase>` |
|
|
21
|
+
| return_next_action | `<exact action>` |
|
|
22
|
+
| target_order | `utf8-bytewise-path-ascending` |
|
|
23
|
+
| target_count_limit | `<positive base-10>` |
|
|
24
|
+
| per_target_bytes_limit | `<positive base-10>` |
|
|
25
|
+
| aggregate_bytes_limit | `<positive base-10>` |
|
|
26
|
+
| transaction_file_limit | `<positive base-10>` |
|
|
27
|
+
| diagnostic_bytes_limit | `256` |
|
|
28
|
+
| journal_line_limit | `<positive base-10>` |
|
|
29
|
+
| attempt_epoch_limit | `<base-10 integer at least 3>` |
|
|
30
|
+
| proof_command_timeout_seconds | `<positive base-10>` |
|
|
31
|
+
| proof_aggregate_timeout_seconds | `<positive base-10>` |
|
|
32
|
+
| proof_terminate_grace_seconds | `<positive base-10>` |
|
|
33
|
+
|
|
34
|
+
| Index | Path | Mode | Behavior ref | Interface ref | Positive fixture | Failure fixtures | Proof command | Proof cwd | Proof signal | Rollback | Evidence fields |
|
|
35
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
36
|
+
| `<8hex>` | `<workspace-relative path>` | `<0[0-7]{3}>` | `<WA-BEH-ID>` | `<WA-IF-ID>` | `<WA-FIX-ID>` | `<comma-separated IDs>` | `<single command>` | `<logical cwd>` | `<fixed signal>` | `<fixed relation>` | `<comma-separated fields>` |
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Row order=normalized-path UTF-8; `Index`=zero-based `8hex`. Path=normalized active-
|
|
40
|
+
workspace-relative UTF-8; reject absolute/traversal/newline, duplicate, directory,
|
|
41
|
+
glob, symlink, product/dependency, or unresolved. Mode=base-8 `0[0-7]{3}`. Markdown
|
|
42
|
+
`|` delimits after an even backslash run; odd escapes; decoding removes only that
|
|
43
|
+
backslash.
|
|
44
|
+
|
|
45
|
+
IDs occur once in behavior/interface/positive/listed-failure order:
|
|
46
|
+
`WA-BEH-[A-Z0-9][A-Z0-9-]*`; `WA-IF-[A-Z0-9][A-Z0-9-]*`;
|
|
47
|
+
`WA-FIX-P[A-Z0-9][A-Z0-9-]*`; `WA-FIX-F[A-Z0-9][A-Z0-9-]*`. Each `## <ID>` plus
|
|
48
|
+
`DevRites workflow reference: <behavior|interface|positive-fixture|failure-fixture>`
|
|
49
|
+
precedes an exact ordered `Field | Value` table: behavior
|
|
50
|
+
`success,observable_effect`; interface `inputs,invariants,ordering,errors,
|
|
51
|
+
configuration,performance`; positive `setup,action,expected`; failure
|
|
52
|
+
`setup,fault,expected`. Values are nonempty single-line backtick cells. Before
|
|
53
|
+
mutation reject placeholders, missing/extra/reordered fields, duplicates, and
|
|
54
|
+
referenced-empty blocks.
|
|
55
|
+
|
|
56
|
+
Proof command=one unchanged trusted Vet-approved repository command; exclude `;`,
|
|
57
|
+
`&&`, `||`, newline, unescaped/list-separator `|`. Cwd=`repository-root` or
|
|
58
|
+
`active-workspace`. Signal=fixed printable ASCII without CR/LF, 1..128 bytes.
|
|
59
|
+
Rollback=`restore-preimage-or-absence`. Evidence=unique comma-separated lowercase
|
|
60
|
+
identifiers. `return_phase`=lifecycle phase; `return_next_action`=exact slash action
|
|
61
|
+
bound to `active_slug`. Malformed admission/reference routes Plan/Vet before mutation.
|
|
62
|
+
|
|
63
|
+
Checked nonnegative arithmetic rejects overflow. Bounds: rows
|
|
64
|
+
`1..target_count_limit`; per-target/aggregate content; `transaction_file_limit >=
|
|
65
|
+
3*target_count_limit+6`; `diagnostic_bytes_limit=256` including LF;
|
|
66
|
+
`attempt_epoch_limit>=3`; `journal_line_limit >=
|
|
67
|
+
30+target_count_limit+attempt_epoch_limit`; complete evidence <=280 lines;
|
|
68
|
+
`command_timeout>terminate_grace>0`; `aggregate_timeout>=command_timeout`.
|
|
69
|
+
Transaction-file/journal minima use declared `target_count_limit`, never row count.
|
|
70
|
+
Fixtures: minima/minimum-1, overflow, sparse/high-limit, content/row limits,
|
|
71
|
+
evidence headroom.
|
|
72
|
+
|
|
73
|
+
## Frozen source and identity
|
|
74
|
+
|
|
75
|
+
Disposable same-layout preflight authors exact bytes. `slug_bytes` is validated
|
|
76
|
+
slug UTF-8; `binding_bytes` decodes current 64-lowercase-hex binding:
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
handle_digest = SHA-256(
|
|
80
|
+
"devrites.workflow-source.v1\0" ||
|
|
81
|
+
uint32-be(len(slug_bytes)) || slug_bytes || binding_bytes
|
|
82
|
+
)
|
|
83
|
+
source_handle = "wsrc:" || lowercase-hex(handle_digest)
|
|
84
|
+
resolver_path = ".workflow-artifact-sources/" || lowercase-hex(handle_digest)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`\0` is one NUL; lengths are uint32-be byte counts; concatenation adds nothing.
|
|
88
|
+
Identity rows sort by normalized-path UTF-8 bytes:
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
identity_digest = SHA-256(
|
|
92
|
+
"devrites.workflow-identity.v1\0" || uint32-be(target_count) ||
|
|
93
|
+
each(uint32-be(len(path_utf8)) || path_utf8 ||
|
|
94
|
+
uint32-be(planned_mode) || 32-byte-content-hash)
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Golden input: slug `demo`, zero-64hex binding, `scripts/prove.py`, mode `0755`
|
|
99
|
+
(decimal 493), bytes `print("ok")` plus LF:
|
|
100
|
+
|
|
101
|
+
| Value | Exact result |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| source filename|`00000000`|
|
|
104
|
+
| content SHA-256|`3a66aebdedbad3cf107d24e72a07d4b735819b1cf4020fdd922f63c064708172`|
|
|
105
|
+
| handle digest|`1557f28b7dbf713ae3828b0dc4e914702ba34063f65393d4f8b57d99bc6af3ad`|
|
|
106
|
+
| logical handle|`wsrc:1557f28b7dbf713ae3828b0dc4e914702ba34063f65393d4f8b57d99bc6af3ad`|
|
|
107
|
+
| resolver path|`.workflow-artifact-sources/1557f28b7dbf713ae3828b0dc4e914702ba34063f65393d4f8b57d99bc6af3ad`|
|
|
108
|
+
| identity digest|`ce333944056552cf645c36cd03b5cd65774d167b5e920118639c6062e29f5c82`|
|
|
109
|
+
|
|
110
|
+
### Owner, namespace, promotion, and reads
|
|
111
|
+
|
|
112
|
+
Pre-journal under umask `077`, active-workspace no-follow fd creates/opens
|
|
113
|
+
`.workflow-artifact-sources`: current-user exact `0700`. `.owner.lock`: create
|
|
114
|
+
`O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC`, `0600`; on `EEXIST`, no-follow open,
|
|
115
|
+
require current-user regular single-link `0600`; sync creations/parents. Use only Python `fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)`, never
|
|
116
|
+
lockf/F_SETLK/another domain; retain CLOEXEC fd through final generation.
|
|
117
|
+
Unsupported/access/metadata/bootstrap failure → `WA-R021-ACCESS-DENIED` before
|
|
118
|
+
mutation; busy → `WA-R001-OWNER-BUSY`, zero post-open writes. Under lock compare
|
|
119
|
+
monotonic generation and owned-section SHA-256 before promotion.
|
|
120
|
+
|
|
121
|
+
Namespace allowlist: `.owner.lock`; one canonical or exact stale replacement; one
|
|
122
|
+
recognized `.<hex>.preparing`; `.stale-cleanup` only during validated rollover.
|
|
123
|
+
Unknown entries block untouched. Build same-parent `.<handle-hex>.preparing`, mode
|
|
124
|
+
`0700`, with current-user regular single-link mode-`0600` indexed sources and exact
|
|
125
|
+
synced metadata:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
.authority:
|
|
129
|
+
devrites.workflow-source-authority.v1
|
|
130
|
+
handle=<source_handle>
|
|
131
|
+
readiness=<readiness-binding>
|
|
132
|
+
|
|
133
|
+
.ready:
|
|
134
|
+
devrites.workflow-source-ready.v1
|
|
135
|
+
count=<decimal-target-count>
|
|
136
|
+
identity=<identity-digest-hex>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Write `.authority`, indexes `00000000`..., `.ready`; sync directory; rename to
|
|
140
|
+
`<handle-hex>`; sync parent, all before journal/target mutation. Invalid/missing
|
|
141
|
+
authority stays untouched (`PLAN_VET_REPAIR`). Valid authority plus invalid ready
|
|
142
|
+
permits deleting only that preparation. Exact metadata/cardinality permits only
|
|
143
|
+
promotion or identical-canonical recognition. Resolve canonical no-follow,
|
|
144
|
+
current-user `0700`; open each bounded indexed source once, current-user regular
|
|
145
|
+
single-link `0600`. Held immutable bytes supply SHA-256 and stage writes; never
|
|
146
|
+
validate/reopen. Evidence stores logical handle only, never bytes/path.
|
|
147
|
+
|
|
148
|
+
Under owner lock, stale GC requires no journal/temp/target write, exact old
|
|
149
|
+
authority/readiness/count/index/slug-binding handle, and no unknown entry.
|
|
150
|
+
Complete-write, file-sync, read back, and directory-sync exact mode-`0600`:
|
|
151
|
+
|
|
152
|
+
```text
|
|
153
|
+
devrites.workflow-source-stale-cleanup.v1
|
|
154
|
+
old_handle=wsrc:<old-handle-hex>
|
|
155
|
+
current_readiness=<current-64hex-binding>
|
|
156
|
+
count=<positive-decimal-target-count>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Then file-sync/read back these exact <=512 bytes in the locked mode-`0600`
|
|
160
|
+
`.owner.lock` descriptor:
|
|
161
|
+
|
|
162
|
+
```text
|
|
163
|
+
devrites.workflow-source-stale-intent.v1
|
|
164
|
+
old_handle=wsrc:<old-handle-hex>
|
|
165
|
+
old_readiness=<old-64hex-binding>
|
|
166
|
+
current_readiness=<current-64hex-binding>
|
|
167
|
+
identity=<64hex-identity>
|
|
168
|
+
count=<positive-decimal-target-count>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Both require final LF, no extra byte. Sync bundle; rename
|
|
172
|
+
`.<old-hex>.stale-cleaning`; sync parent. Descriptor-relative delete order:
|
|
173
|
+
`.authority`, `.ready`, ascending indexes, `.stale-cleanup`, directory; sync each.
|
|
174
|
+
Exact authenticated intent admits only a partial or empty
|
|
175
|
+
remaining suffix of that order; re-authenticate the intent before every remaining deletion. Treat empty tree
|
|
176
|
+
without intent, malformed intent, or orphan intent lacking canonical/stale-cleaning
|
|
177
|
+
relation as forged: no change; route `WA-R022-STALE-SOURCE-GC-FAILED`. Only after the
|
|
178
|
+
stale directory is absent and parent synced, truncate the held lock intent, sync, and
|
|
179
|
+
read back
|
|
180
|
+
exact empty content.
|
|
181
|
+
|
|
182
|
+
Source persists through retryable `FAILED`; cleanup removes it before `CLEANED`/
|
|
183
|
+
`EXHAUSTED`; post-`CLEANED` absence is expected.
|
|
184
|
+
|
|
185
|
+
## Journal and complete writes
|
|
186
|
+
|
|
187
|
+
First atomic write records frozen identity/source/epoch/generation plus
|
|
188
|
+
`PREPARING(0,stage,create)`; every effect has prior durable intent. Journal replace:
|
|
189
|
+
same-parent current-user regular single-link mode-`0600` temp; complete-write;
|
|
190
|
+
file/parent sync; atomic replace; no-follow parents supply
|
|
191
|
+
both source and destination directory handles. Stage/backup order: `create→write→mode→file_sync→directory_sync`.
|
|
192
|
+
Complete-write accepts integer progress `1..remaining` only; bool/noninteger/
|
|
193
|
+
nonpositive/oversize, exhausted short write, `ENOSPC`, or error fails boundedly.
|
|
194
|
+
Resume requires exact declared pre/post/valid-partial state.
|
|
195
|
+
|
|
196
|
+
Transaction-private JSON **transaction journal**
|
|
197
|
+
`.workflow-artifact-transactions/<identity-digest>/journal.json` is crash/recovery
|
|
198
|
+
authority; marker-owned `evidence.md` **evidence journal** is bounded durable/public
|
|
199
|
+
evidence. Neither aliases the other. Also sole: `.../stage/<8hex>`,
|
|
200
|
+
`.../backup/<8hex>`, `.evidence.md.workflow-artifact.tmp`.
|
|
201
|
+
|
|
202
|
+
Evidence-journal ownership spans standalone start through end-marker LF. Exact no-separator
|
|
203
|
+
fragments are `<!-- ` + `devrites` + `-workflow-artifact-journal:start -->` and
|
|
204
|
+
`<!-- ` + `devrites` + `-workflow-artifact-journal:end -->`; below they are
|
|
205
|
+
`START-MARKER`/`END-MARKER`:
|
|
206
|
+
|
|
207
|
+
```markdown
|
|
208
|
+
START-MARKER
|
|
209
|
+
## Workflow Artifact journal
|
|
210
|
+
DevRites contract: devrites.workflow-artifact-journal.v1
|
|
211
|
+
|
|
212
|
+
| Field | Value |
|
|
213
|
+
| --- | --- |
|
|
214
|
+
| transaction_id | `wtx:<identity-digest>` |
|
|
215
|
+
| attempt_epoch | `<positive base-10>` |
|
|
216
|
+
| attempt_id | `wta:<identity-digest>:<8hex-epoch>` |
|
|
217
|
+
| generation | `<nonnegative base-10>` |
|
|
218
|
+
| owned_section_preimage_sha256 | `<64hex or ABSENT>` |
|
|
219
|
+
| vet_readiness_binding | `<64hex>` |
|
|
220
|
+
| source_handle | `wsrc:<64hex>` |
|
|
221
|
+
| identity_digest | `<64hex>` |
|
|
222
|
+
| state | `<allowlisted state>` |
|
|
223
|
+
| boundary_id | `<allowlisted boundary>` |
|
|
224
|
+
| reason_id | `<allowlisted reason or NONE>` |
|
|
225
|
+
| next_route | `<allowlisted route>` |
|
|
226
|
+
| exhaustion_cause | `<same-fingerprint-count|total-epoch-limit>` |
|
|
227
|
+
| product_candidate_digest | `<64hex>` |
|
|
228
|
+
| product_readiness_binding | `<64hex>` |
|
|
229
|
+
| built_slice_count | `<nonnegative base-10>` |
|
|
230
|
+
| caller_return_phase | `<phase>` |
|
|
231
|
+
| caller_return_next_action | `<exact action>` |
|
|
232
|
+
|
|
233
|
+
| Index | Path | Mode | Content SHA-256 | Preimage | Preimage mode | Preimage SHA-256 | Backup handle | Result |
|
|
234
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
235
|
+
| `<8hex>` | `<logical path>` | `<octal>` | `<64hex>` | `present or absent` | `<octal or NONE>` | `<64hex or NONE>` | `<opaque handle or NONE>` | `<allowlisted result>` |
|
|
236
|
+
|
|
237
|
+
| Epoch | Attempt ID | Failure fingerprint | Reason | Boundary | Progress | Result |
|
|
238
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
239
|
+
| `<base-10>` | `<attempt ID>` | `<64hex or NONE>` | `<reason or NONE>` | `<boundary>` | `resolved or no-progress or pending` | `<allowlisted result>` |
|
|
240
|
+
END-MARKER
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Absent markers append one blank line and section, preserving outside bytes. Before
|
|
244
|
+
mutation reject duplicate/nested/malformed/over-budget markers. Keep one standalone
|
|
245
|
+
`Candidate SHA-256:` and only `product_candidate_digest`. `exhaustion_cause` exists
|
|
246
|
+
only for `EXHAUSTED` with one listed cause; otherwise absent. Immutable attempt rows
|
|
247
|
+
omit bytes, credentials, hostile input, paths, exceptions, and raw errors.
|
|
248
|
+
|
|
249
|
+
## Canonical operation table
|
|
250
|
+
|
|
251
|
+
Independent observer derives `(operation_id,accepted_pre_state,accepted_post_state,
|
|
252
|
+
failure_route,observer_assertion_id)`. At `WA-OP-014`, read current candidate/
|
|
253
|
+
readiness/built-slice facts from engine/OS, never consumer-authored current/frozen
|
|
254
|
+
values.
|
|
255
|
+
|
|
256
|
+
|Operation ID|Attempt epoch|Durable intent|Accepted pre-state|Accepted post-state|Recoverable partial state|Failure route|Next state/operation|
|
|
257
|
+
|---|---|---|---|---|---|---|---|
|
|
258
|
+
| `WA-OP-001-OWNER-ACQUIRE`|current or 1|none; lock precedes journal read/write|no local owner descriptor|exclusive lock held; generation/owned hash observed|none; busy owner means no write|`WAIT_ACTIVE_OWNER` or `BLOCKED_GATE`|classifier-selected operation|
|
|
259
|
+
| `WA-OP-002-SOURCE-PROMOTE`|1 or retry re-preflight|exact authority/source/ready step before each create/write/mode/sync/rename|lock held; green retained bytes; no active target write|trusted canonical ready bundle|exact valid-authority `.preparing`; exact ready temp; already-identical canonical bundle|`PLAN_VET_REPAIR`|`WA-OP-003-JOURNAL-INIT`|
|
|
260
|
+
| `WA-OP-002A-STALE-SOURCE-GC`|pre-journal only|synced `.stale-cleanup`, then atomic rename to exact stale-cleaning directory|lock held; binding rollover; internally valid old canonical; no journal/temp/target write/unknown entry|stale bundle absent; parent synced|marker in canonical before rename or exact validated stale-cleaning directory with recognized entries missing/remaining|`OFFLINE_RECOVERY`|current `WA-OP-002-SOURCE-PROMOTE`|
|
|
261
|
+
| `WA-OP-003-JOURNAL-INIT`|current|`PREPARING(0,stage,create)` with frozen identity and source handle|lock held; trusted source; absent owned section; target set unmodified|generation advanced; complete owned section in `PREPARING`|exact same-parent evidence temporary; outside bytes unchanged|`OFFLINE_RECOVERY`|`WA-OP-004-STAGE-WRITE`|
|
|
262
|
+
| `WA-OP-004-STAGE-WRITE`|current|`(index,stage,create\|write\|mode\|file_sync\|directory_sync)`|`PREPARING`; source bytes retained; exact target parent|exact private stage bytes/mode synced|exact named partial stage whose metadata is valid|`OFFLINE_RECOVERY`|next stage or `WA-OP-005-BACKUP-WRITE`|
|
|
263
|
+
| `WA-OP-005-BACKUP-WRITE`|current|`(index,backup,create\|write\|mode\|file_sync\|directory_sync)`|`PREPARING`; target still unmodified|exact private backup/preimage-absence record synced|exact named partial backup whose metadata is valid|`OFFLINE_RECOVERY`|next backup or `PREPARED`|
|
|
264
|
+
| `WA-OP-006-INSTALL`|current|`INSTALLING(index)` names exact intent-derived private claim/install artifacts before mutation|`PREPARED`/prior `INSTALLING`; stage/backups exact|atomically move current destination into private claim; validate captured object against exact preimage/frozen expected-post pair; install desired bytes/absence no-replace; exact readback; advance/`INSTALLED`|third state/concurrent occupant preserves claim and occupant when needed and blocks|`OFFLINE_RECOVERY`|next install or `WA-OP-007-PROVE`|
|
|
265
|
+
| `WA-OP-007-PROVE`|current|`PROVING(command-index)` before process-group launch|`INSTALLED`; all targets read back exact|next proof command or durable `PROVED`|reaped process group with fixed failure/timeout boundary; bounded private output only|`OFFLINE_RECOVERY`|`WA-OP-008-ROLLBACK` on pre-`PROVED` failure; else `WA-OP-010-SUCCESS-CLEANUP`|
|
|
266
|
+
| `WA-OP-008-ROLLBACK`|current|`ROLLING_BACK(index)` names exact intent-derived private claim/install artifacts before mutation|replacement occurred; before `PROVED`|atomically move current destination into private claim; validate captured object against exact preimage/frozen expected-post pair; install desired bytes/absence no-replace; exact readback; advance/`ROLLED_BACK`|third state/concurrent occupant preserves claim and occupant when needed and blocks|`BLOCKED_GATE` if restore cannot complete|next rollback or `WA-OP-009-FAILURE-CLEANUP`|
|
|
267
|
+
| `WA-OP-009-FAILURE-CLEANUP`|current|`FAILURE_CLEANING(index)` before exact validated unlink/prune|zero replacements or durable `ROLLED_BACK`|stages/backups/evidence temp removed; canonical source retained; `FAILED`|exact admitted transaction file remains|`OFFLINE_RECOVERY`|`FAILED`; correction then `WA-OP-011-RETRY-HANDOFF`|
|
|
268
|
+
| `WA-OP-010-SUCCESS-CLEANUP`|current|`CLEANING(index)` before exact validated unlink/prune/source GC|durable `PROVED`; targets exact frozen identity|stages/backups/source/temp removed; outside evidence preserved; `CLEANED`|exact admitted cleanup file/source remains; source absence is already-cleaned|`RESUME_CLEANUP`|`CLEANED`, then `VERIFY_EXISTING`/caller return|
|
|
269
|
+
| `WA-OP-011-RETRY-HANDOFF`|prior+1, bounded by admission|immutable prior row plus `RETRY_PREPARING(epoch)` before handoff|locked `FAILED`; accepted correction; green re-preflight; same-fingerprint count <3 and next epoch within admitted cap|exact new epoch in `PREPARING`; prior rows unchanged|durable `RETRY_PREPARING(epoch)` with no target write|`OFFLINE_RECOVERY`|resume same epoch at `PREPARING`|
|
|
270
|
+
| `WA-OP-012-EXHAUSTION-GC`|current|`EXHAUSTED_CLEANING`|locked `FAILED`; same-fingerprint count=3 or admitted epoch cap reached|retained source and exact transaction files removed; `EXHAUSTED` with durable truthful `exhaustion_cause`|exact admitted cleanup file/source or missing cause remains|`BLOCKED_GATE` if safe cleanup cannot complete|`BLOCKED_EXHAUSTED`; no next attempt|
|
|
271
|
+
| `WA-OP-013-EVIDENCE-UPDATE`|current|next generation plus owned-section preimage SHA-256|lock held; observed generation/hash match|atomic synced marker-owned section; generation+1; all outside bytes exact|exact same-parent current-user regular single-link mode-`0600` temporary|state operation's route; never infer success|return to invoking operation|
|
|
272
|
+
| `WA-OP-014-PRODUCT-SEPARATION`|current|proof boundary before comparison|frozen pre-transaction product candidate/readiness/built count|exact equality recorded in owned section|none|`BLOCKED_GATE`|success cleanup only after equality|
|
|
273
|
+
| `WA-OP-015-VERIFY-EXISTING`|historical epoch|no mutation intent|`CLEANED`; exact evidence and targets; source absent or already GC'd|same bytes/state/counters|none|route by finite diagnostic table|caller return; no install/retry/budget charge|
|
|
274
|
+
|
|
275
|
+
## State, proof, and retry
|
|
276
|
+
|
|
277
|
+
Success: `PREPARING → PREPARED → INSTALLING(n) → INSTALLED → PROVING → PROVED
|
|
278
|
+
→ CLEANING(n) → CLEANED`.
|
|
279
|
+
|
|
280
|
+
Pre-replacement failure: `FAILURE_CLEANING(n) → FAILED`. From first replacement
|
|
281
|
+
through `PROVING`: `WA-OP-008-ROLLBACK → ROLLED_BACK → FAILURE_CLEANING(n) →
|
|
282
|
+
FAILED`. At/after durable `PROVED`, preserve targets and resume cleanup only. Source
|
|
283
|
+
loss follows the same branches.
|
|
284
|
+
|
|
285
|
+
Delivery's one immutable transaction-private `outside-manifest.json` sidecar.
|
|
286
|
+
Journal binds only exact relative name, SHA-256, encoded bytes, and row count; no
|
|
287
|
+
generation duplicates payload. Descriptor-stable records: directory/file/symlink type/mode/uid/gid; file nlink/SHA-256,
|
|
288
|
+
symlink target; fifo/socket same base; block/character add nonnegative integer
|
|
289
|
+
non-bool `st_rdev`. Reject other types before acceptance. Protect
|
|
290
|
+
ignored, nested-`.git`, and transaction-lookalike paths; exclude only root
|
|
291
|
+
`.git` and the exact selected transaction subtree. Container/siblings protected. Limits: 200,000 rows,
|
|
292
|
+
16,777,216 encoded bytes, one 600-second wall, and 1,048,576 journal bytes.
|
|
293
|
+
Bootstrap sidecar/journal temps reconcile only before destination mutation.
|
|
294
|
+
Sidecar is immutable evidence in `FAILED`/`CLEANED`; stage, backups, proof-cache,
|
|
295
|
+
mutation artifacts clean exactly.
|
|
296
|
+
|
|
297
|
+
Candidate/destination and every generated-stage regular-file authority is acquired no-follow through one held descriptor; initial/opened/final pathname identity must match and each read caps at 16,777,216 bytes. Complete staged/current generated-tree scans share one finite absolute deadline: install delivery aggregate; recovery 600 seconds.
|
|
298
|
+
|
|
299
|
+
`PROVING` runs each trusted Vet-approved admitted argv command and its descendants
|
|
300
|
+
in one fresh process group, where they remain until exit; output and command/
|
|
301
|
+
aggregate time are bounded. A declared expected signal must be exactly one
|
|
302
|
+
standalone output line. It adds no network or filesystem sandbox and
|
|
303
|
+
makes no deliberate detached-session containment claim. Failure: `TERM`, bounded grace,
|
|
304
|
+
`KILL` survivors, reap group/leader, rollback. Any surviving group member, nonzero,
|
|
305
|
+
wrong signal, overflow, or timeout prevents `PROVED`.
|
|
306
|
+
|
|
307
|
+
Epoch starts 1. `FAILED` records preimages/cleanup/epoch/fingerprint/reason/
|
|
308
|
+
boundary/route/no-progress count. Resolved fingerprints close; a different
|
|
309
|
+
invariant gets a distinct fingerprint. Handoff death resumes its retry epoch with
|
|
310
|
+
prior rows immutable. `WA-OP-011/012` enforce independent fingerprint/epoch caps
|
|
311
|
+
and terminal source cleanup. Exhaustion records:
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
status=blocked
|
|
315
|
+
exhaustion_cause=<same-fingerprint-count|total-epoch-limit>
|
|
316
|
+
next_action=none — technical recovery exhausted; requires new evidence or changed failure conditions
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The journal, evidence section, and observer retain that cause; epoch exhaustion
|
|
320
|
+
never claims the current fingerprint reached three.
|
|
321
|
+
|
|
322
|
+
## Route classifier
|
|
323
|
+
|
|
324
|
+
Precedence: busy owner; safety/access/approval gate; completed historical; active
|
|
325
|
+
journal; `CLEANED`; missing/stale authority; stale writer evidence; current
|
|
326
|
+
admission. `PROVED|CLEANING` resumes cleanup; install-through-`PROVING`, rollback,
|
|
327
|
+
or failure cleanup routes offline; retryable `FAILED` routes correction/retry;
|
|
328
|
+
`EXHAUSTED` blocks; `PREPARING|PREPARED` resumes only with current authority.
|
|
329
|
+
There is no actor-history migration or backfill.
|
|
330
|
+
|
|
331
|
+
|Route|Owner|Exact action|Durable state/status/next action|Cursor/output|
|
|
332
|
+
| ---|---|---|---|---|
|
|
333
|
+
| `ROOT_TRANSACTION`|controlling root|execute this module inside current caller; no phase command|keep caller phase, `status=running`, `next_action=<saved caller action>`|save return cursor; no intermediate user reply|
|
|
334
|
+
| `PLAN_VET_REPAIR`|controlling root|run `/rite-plan repair <slug>` then `/rite-vet <slug>` internally|`phase=plan`, `status=running`, `next_action=/rite-plan repair <slug>` until Vet READY|restore saved caller cursor; Autocomplete emits no intermediate reply|
|
|
335
|
+
| `OFFLINE_RECOVERY`|controlling root|run `/devrites-debug-recovery <slug>`, disposable re-preflight, then narrow `/rite-vet <slug>`|`status=running`, `next_action=/devrites-debug-recovery <slug>`; retry only from durable `FAILED` and remaining cap|preserve cursor and attempt history; no real action|
|
|
336
|
+
| `RESUME_CLEANUP`|controlling root|lock and resume exact `PROVED`/`CLEANING` generation|keep caller phase/status/action|proved targets stay; stale source routes Plan/Vet after cleanup|
|
|
337
|
+
| `PROVE_AND_RETURN`|controlling root|run admitted proof, success cleanup, restore cursor|saved return phase/action|stop for fresh consumptive-action authorization|
|
|
338
|
+
| `VERIFY_EXISTING`|controlling root|verify `CLEANED`, targets, proof, and product separation; do not reinstall|restore saved return phase/action|no retry/slice/action budget|
|
|
339
|
+
| `NO_BACKFILL`|controlling root|no action|completed state unchanged|no new output|
|
|
340
|
+
| `WAIT_ACTIVE_OWNER`|non-owner|no write; stop invocation|shared state unchanged|fixed owner-busy diagnostic|
|
|
341
|
+
| `BLOCKED_EXHAUSTED`|controlling root|no attempt 4|blocked with exact exhausted next action|fixed exhausted diagnostic|
|
|
342
|
+
| `BLOCKED_GATE`|controlling root|follow existing safety/access/approval gate|gate-owned state|gate output; never reinterpret as retry|
|
|
343
|
+
|
|
344
|
+
|Scenario ID|Trigger|Exact route / action|Durable consequence|Forbidden behavior|
|
|
345
|
+
| ---|---|---|---|---|
|
|
346
|
+
| WA-ADMISSION-SUCCESS|current exact admission, green retained source, no active journal|`ROOT_TRANSACTION` — freeze identity and begin preparation|first active state is `PREPARING`|wright dispatch or product-slice charge|
|
|
347
|
+
| WA-MISSING-IDENTITY|frozen identity/handle absent|`PLAN_VET_REPAIR`|zero active journal/target writes|synthesize from chat, target, or old evidence|
|
|
348
|
+
| WA-STALE-IDENTITY|Vet binding, order, path, mode, hash, or source differs|`PLAN_VET_REPAIR`|zero target writes; unrelated files untouched|continue with stale bytes|
|
|
349
|
+
| WA-STALE-WRITER-EXHAUSTION|only obsolete actor-exhaustion evidence exists|`PLAN_VET_REPAIR`|no migration/backfill attempt|reopen via one-time migration|
|
|
350
|
+
| WA-FIRST-ROOT-FAILURE|first active transaction fails before `PROVED`|`OFFLINE_RECOVERY`|exact preimages, `FAILED`, attempt one under same fingerprint|terminal exhaustion or fresh action budget|
|
|
351
|
+
| WA-REPLACEMENT-ROLLBACK|replacement fails after earlier installs|`OFFLINE_RECOVERY`|`ROLLING_BACK → ROLLED_BACK → FAILURE_CLEANING → FAILED`|partial installed set survives|
|
|
352
|
+
| WA-CLEANUP|termination/failure at or after `PROVED`|`RESUME_CLEANUP` then `PLAN_VET_REPAIR` only if source stale|proved targets preserved; cleanup reconciled|rollback or reinstall proved targets|
|
|
353
|
+
| WA-IDENTITY-CONTINUITY|readback/proof matches frozen identity|`PROVE_AND_RETURN`|candidate/readiness/built count unchanged; cursor restored|add workflow path to product manifest|
|
|
354
|
+
| WA-COMPLETED-HISTORICAL|completed workspace lacks current identity|`NO_BACKFILL`|no writes or reopened phase|historical reconstruction|
|
|
355
|
+
| WA-IDEMPOTENT-RERUN|exact `CLEANED` evidence and targets already match|`VERIFY_EXISTING` and return|no new transaction, slice charge, or action authorization|reinstall or consume retry budget|
|
|
356
|
+
|
|
357
|
+
## Public diagnostics
|
|
358
|
+
|
|
359
|
+
Emit exactly one ASCII line plus LF, never dynamic text:
|
|
360
|
+
|
|
361
|
+
```text
|
|
362
|
+
WORKFLOW_ARTIFACT_FAILURE reason_id=<reason> boundary_id=<boundary> next_route=<route>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Unknown or malformed values collapse to
|
|
366
|
+
`WA-R009-STATE-AMBIGUOUS`, `WA-B005-JOURNAL`, `OFFLINE_RECOVERY`.
|
|
367
|
+
No target index, content, path, credential, hostile value, exception, or raw
|
|
368
|
+
filesystem error appears.
|
|
369
|
+
|
|
370
|
+
|Reason ID|Boundary ID|Meaning|Next route|
|
|
371
|
+
| ---|---|---|---|
|
|
372
|
+
| `WA-R001-OWNER-BUSY`|`WA-B001-OWNER`|exclusive owner held elsewhere|`WAIT_ACTIVE_OWNER`|
|
|
373
|
+
| `WA-R002-ADMISSION-INCOMPLETE`|`WA-B002-ADMISSION`|required admission absent or malformed|`PLAN_VET_REPAIR`|
|
|
374
|
+
| `WA-R003-IDENTITY-MISSING`|`WA-B004-SOURCE-OPEN`|current frozen identity unavailable|`PLAN_VET_REPAIR`|
|
|
375
|
+
| `WA-R004-IDENTITY-STALE`|`WA-B004-SOURCE-OPEN`|authority differs from frozen identity|`PLAN_VET_REPAIR`|
|
|
376
|
+
| `WA-R005-SOURCE-UNTRUSTED`|`WA-B003-SOURCE-PROMOTE`|source lacks exact authority|`PLAN_VET_REPAIR`|
|
|
377
|
+
| `WA-R006-SOURCE-STALE-PREINSTALL`|`WA-B004-SOURCE-OPEN`|stale before first replacement|`PLAN_VET_REPAIR`|
|
|
378
|
+
| `WA-R007-SOURCE-STALE-ACTIVE`|`WA-B004-SOURCE-OPEN`|stale after replacement before proof|`OFFLINE_RECOVERY`|
|
|
379
|
+
| `WA-R008-SOURCE-STALE-POSTPROOF`|`WA-B013-SUCCESS-CLEANUP`|stale during proved cleanup|`RESUME_CLEANUP`|
|
|
380
|
+
| `WA-R009-STATE-AMBIGUOUS`|`WA-B005-JOURNAL`|relation not admitted|`OFFLINE_RECOVERY`|
|
|
381
|
+
| `WA-R010-WRITE-FAILED`|`WA-B006-STAGE-WRITE` or `WA-B007-BACKUP-WRITE`|bounded write failed before install|`OFFLINE_RECOVERY`|
|
|
382
|
+
| `WA-R011-REPLACE-FAILED`|`WA-B008-INSTALL`|replacement failed|`OFFLINE_RECOVERY`|
|
|
383
|
+
| `WA-R012-READBACK-MISMATCH`|`WA-B009-READBACK`|installed identity differs|`OFFLINE_RECOVERY`|
|
|
384
|
+
| `WA-R013-PROOF-FAILED`|`WA-B010-PROVE`|nonzero or wrong proof signal|`OFFLINE_RECOVERY`|
|
|
385
|
+
| `WA-R014-PROOF-TIMEOUT`|`WA-B010-PROVE`|proof group exceeded bound|`OFFLINE_RECOVERY`|
|
|
386
|
+
| `WA-R015-ROLLBACK-FAILED`|`WA-B011-ROLLBACK`|preimages not restored|`BLOCKED_GATE`|
|
|
387
|
+
| `WA-R016-FAILURE-CLEANUP-FAILED`|`WA-B012-FAILURE-CLEANUP`|failure files remain|`OFFLINE_RECOVERY`|
|
|
388
|
+
| `WA-R017-SUCCESS-CLEANUP-FAILED`|`WA-B013-SUCCESS-CLEANUP`|proved cleanup incomplete|`RESUME_CLEANUP`|
|
|
389
|
+
| `WA-R018-PRODUCT-IDENTITY-CHANGED`|`WA-B014-PRODUCT-SEPARATION`|product identity drifted|`BLOCKED_GATE`|
|
|
390
|
+
| `WA-R019-LIMIT-EXCEEDED`|`WA-B002-ADMISSION`|byte/file/time/journal bound exceeded|`PLAN_VET_REPAIR`|
|
|
391
|
+
| `WA-R020-RETRY-EXHAUSTED`|`WA-B015-RETRY`|same-fingerprint count or total attempt epoch reached its independent cap|`BLOCKED_EXHAUSTED`|
|
|
392
|
+
| `WA-R021-ACCESS-DENIED`|`WA-B001-OWNER`|host access or canonical flock unavailable|`BLOCKED_GATE`|
|
|
393
|
+
| `WA-R022-STALE-SOURCE-GC-FAILED`|`WA-B016-STALE-SOURCE-GC`|validated stale cleanup incomplete|`OFFLINE_RECOVERY`|
|
|
394
|
+
|
|
395
|
+
Each diagnostic, including LF, is at most 256 bytes. Reason/boundary
|
|
396
|
+
pairs remain injective for actionable seams.
|
|
397
|
+
|
|
398
|
+
## Phase adapters
|
|
399
|
+
|
|
400
|
+
|Canonical adapter|Entry trigger|Canonical action|Return cursor|
|
|
401
|
+
| ---|---|---|---|
|
|
402
|
+
| `devrites-lib/reference/standards/afk-hitl.md`|unattended root reaches current admitted Workflow Artifact work|invoke classifier; execute returned route without wright/slice charge|saved lifecycle phase/action; no intermediate reply|
|
|
403
|
+
| `devrites-lib/reference/standards/one-shot-actions.md`|workflow proof completes before any consumptive one-shot action|`PROVE_AND_RETURN`; require fresh real-action authorization|saved one-shot action boundary|
|
|
404
|
+
| `devrites-debug-recovery/SKILL.md`|durable active failure or ambiguous admitted state|`OFFLINE_RECOVERY`; correct offline, re-preflight, narrow Vet, retry only under cap|saved caller or exact Plan/Vet route|
|
|
405
|
+
| `rite-autocomplete/SKILL.md`|lifecycle cursor encounters admitted set or resumable journal|invoke classifier; execute returned route internally|saved phase/action; zero intermediate reply|
|
|
406
|
+
| `rite-autocomplete/reference/loop.md`|loop tick sees Workflow Artifact trigger/state|invoke classifier once under owner lock; no actor-history migration|same loop cursor; no budget charge for verify/rerun|
|
|
407
|
+
| `rite-autocomplete/reference/stop-conditions.md`|classifier returns owner-busy, exhausted, or existing hard gate|stop on exact `WAIT_ACTIVE_OWNER`, `BLOCKED_EXHAUSTED`, or `BLOCKED_GATE` result|unchanged cursor plus fixed route-owned output|
|
|
408
|
+
| `rite-build/SKILL.md`|Vet-ready admitted bytes require root authorship outside product wright|`ROOT_TRANSACTION`; root writes only admitted `.devrites/**` targets|saved Build slice cursor; wright product allowlist unchanged|
|
|
409
|
+
| `rite-build/reference/phase-contract.md`|Build gate enters or resumes transaction|invoke canonical operation table; reconcile exact result|same slice/checkpoint cursor or Plan/Vet route|
|
|
410
|
+
| `rite-prove/SKILL.md`|Prove consumes installed Workflow Artifact or `CLEANED` rerun|`VERIFY_EXISTING` or admitted proof path ending `PROVE_AND_RETURN`|saved Prove cursor; stop before real action|
|
|
411
|
+
| `rite-vet/SKILL.md`|plan declares root-authored executable workflow file|emit exact admission; stale/missing authority uses `PLAN_VET_REPAIR`|Vet READY cursor or exact technical replan|
|