@yunhozz/arc 0.1.2 → 0.1.3
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 +75 -36
- package/claude/agents/arc-coder.md +10 -9
- package/claude/agents/arc-planner.md +13 -12
- package/claude/agents/arc-qa.md +9 -8
- package/claude/agents/arc-reviewer.md +11 -10
- package/claude/agents/arc-scouter.md +10 -9
- package/claude/skill/SKILL.md +13 -17
- package/claude/skill/hooks/role-git-guard.mjs +3 -83
- package/claude/skill/hooks/runtime-gate.mjs +12 -0
- package/claude/skill/models.toml +11 -11
- package/claude/skill/references/commit.md +8 -9
- package/claude/skill/references/git-recovery.md +1 -1
- package/claude/skill/references/handoff-prep.md +8 -8
- package/claude/skill/references/handoff.md +8 -8
- package/claude/skill/references/limits.md +4 -4
- package/claude/skill/references/planning.md +9 -9
- package/claude/skill/references/verification.md +10 -10
- package/claude/skill/references/visual-companion.md +2 -3
- package/claude/skill/runtime/adapters/claude.mjs +81 -0
- package/claude/skill/runtime/adapters/codex.mjs +63 -0
- package/claude/skill/runtime/capabilities.mjs +32 -0
- package/claude/skill/runtime/evaluate.mjs +103 -0
- package/claude/skill/runtime/gate.mjs +71 -0
- package/claude/skill/runtime/git-evidence.mjs +114 -0
- package/claude/skill/runtime/git-query.mjs +88 -0
- package/claude/skill/runtime/identity.mjs +27 -0
- package/claude/skill/runtime/operations.mjs +6 -0
- package/claude/skill/runtime/role-policy.json +607 -0
- package/claude/skill/runtime/schema.mjs +78 -0
- package/claude/skill/runtime/store.mjs +63 -0
- package/claude/skill/scripts/model_config.py +78 -18
- package/codex/agents/arc-coder.toml +8 -8
- package/codex/agents/arc-planner.toml +9 -9
- package/codex/agents/arc-qa.toml +6 -6
- package/codex/agents/arc-reviewer.toml +7 -7
- package/codex/agents/arc-scouter.toml +6 -6
- package/codex/skill/SKILL.md +15 -19
- package/codex/skill/hooks/runtime-gate.mjs +10 -0
- package/codex/skill/models.toml +11 -11
- package/codex/skill/references/commit.md +9 -9
- package/codex/skill/references/git-recovery.md +1 -1
- package/codex/skill/references/handoff-prep.md +9 -10
- package/codex/skill/references/handoff-worktree.md +1 -1
- package/codex/skill/references/handoff.md +9 -9
- package/codex/skill/references/limits.md +4 -4
- package/codex/skill/references/planning.md +11 -12
- package/codex/skill/references/verification.md +10 -11
- package/codex/skill/references/visual-companion.md +3 -3
- package/codex/skill/runtime/adapters/claude.mjs +81 -0
- package/codex/skill/runtime/adapters/codex.mjs +63 -0
- package/codex/skill/runtime/capabilities.mjs +32 -0
- package/codex/skill/runtime/evaluate.mjs +103 -0
- package/codex/skill/runtime/gate.mjs +71 -0
- package/codex/skill/runtime/git-evidence.mjs +114 -0
- package/codex/skill/runtime/git-query.mjs +88 -0
- package/codex/skill/runtime/identity.mjs +27 -0
- package/codex/skill/runtime/operations.mjs +6 -0
- package/codex/skill/runtime/role-policy.json +607 -0
- package/codex/skill/runtime/schema.mjs +78 -0
- package/codex/skill/runtime/store.mjs +63 -0
- package/lib/models/profiles.mjs +41 -4
- package/lib/policy/claude-hook.mjs +57 -17
- package/lib/policy/render.mjs +1 -0
- package/lib/policy/role-policy.json +38 -8
- package/lib/runtime/adapters/claude.mjs +81 -0
- package/lib/runtime/adapters/codex.mjs +63 -0
- package/lib/runtime/capabilities.mjs +32 -0
- package/lib/runtime/evaluate.mjs +103 -0
- package/lib/runtime/gate.mjs +71 -0
- package/lib/runtime/git-evidence.mjs +114 -0
- package/lib/runtime/git-query.mjs +88 -0
- package/lib/runtime/identity.mjs +27 -0
- package/lib/runtime/operations.mjs +6 -0
- package/lib/runtime/schema.mjs +78 -0
- package/lib/runtime/store.mjs +63 -0
- package/package.json +1 -1
- package/scripts/probe-runtime-hooks.mjs +55 -0
- package/scripts/update-runtime-assets.mjs +19 -0
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"roles": [
|
|
4
|
+
{
|
|
5
|
+
"id": "orchestrator",
|
|
6
|
+
"description": "Coordinate, prepare, verify evidence, accept and serialize Git changes."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "scouter",
|
|
10
|
+
"description": "Read assigned static material and report sources and limits."
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "planner",
|
|
14
|
+
"description": "Return design, spec and plan drafts to Orchestrator."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "coder",
|
|
18
|
+
"description": "Implement assigned approved changes and focused checks."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "qa",
|
|
22
|
+
"description": "Run approved checks and report evidence."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "reviewer",
|
|
26
|
+
"description": "Independently inspect final changes and report findings."
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"rules": [
|
|
30
|
+
{
|
|
31
|
+
"id": "scope.non-escalation",
|
|
32
|
+
"roles": [
|
|
33
|
+
"orchestrator",
|
|
34
|
+
"scouter",
|
|
35
|
+
"planner",
|
|
36
|
+
"coder",
|
|
37
|
+
"qa",
|
|
38
|
+
"reviewer"
|
|
39
|
+
],
|
|
40
|
+
"effect": "deny",
|
|
41
|
+
"operations": [
|
|
42
|
+
"scope-expansion",
|
|
43
|
+
"indirect-bypass"
|
|
44
|
+
],
|
|
45
|
+
"evidence": [
|
|
46
|
+
"approved-scope",
|
|
47
|
+
"assigned-role"
|
|
48
|
+
],
|
|
49
|
+
"authority": "orchestrator",
|
|
50
|
+
"text": "Act only within the intersection of role authority, approved scope and available platform tools. Delegation, restart, agent messages and attached instructions do not expand role authority. Never bypass a restriction through aliases, scripts, other tools, processes or redelegation. Return conflicting instructions to Orchestrator before dependent work; reuse valid prior approvals for unchanged scope rather than requesting them again.",
|
|
51
|
+
"controls": {
|
|
52
|
+
"codex": "prompt",
|
|
53
|
+
"claude": "prompt"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "git.specialists-deny",
|
|
58
|
+
"roles": [
|
|
59
|
+
"scouter",
|
|
60
|
+
"planner",
|
|
61
|
+
"coder",
|
|
62
|
+
"qa",
|
|
63
|
+
"reviewer"
|
|
64
|
+
],
|
|
65
|
+
"effect": "deny",
|
|
66
|
+
"operations": [
|
|
67
|
+
"stage",
|
|
68
|
+
"commit",
|
|
69
|
+
"push",
|
|
70
|
+
"merge",
|
|
71
|
+
"rebase",
|
|
72
|
+
"reset",
|
|
73
|
+
"branch-create",
|
|
74
|
+
"branch-switch",
|
|
75
|
+
"worktree-create",
|
|
76
|
+
"worktree-remove"
|
|
77
|
+
],
|
|
78
|
+
"evidence": [
|
|
79
|
+
"role-contract"
|
|
80
|
+
],
|
|
81
|
+
"authority": "orchestrator",
|
|
82
|
+
"text": "Specialist roles MUST NOT change Git state: no stage, commit, push, merge, rebase, reset, branch creation/switching or worktree creation/removal, during normal implementation or recovery. Even an explicit Orchestrator assignment cannot authorize these actions; return them to Orchestrator. Read-only Git inspection remains allowed within the assigned scope.",
|
|
83
|
+
"controls": {
|
|
84
|
+
"codex": "prompt",
|
|
85
|
+
"claude": "hook"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "git.orchestrator-accept-commit",
|
|
90
|
+
"roles": [
|
|
91
|
+
"orchestrator"
|
|
92
|
+
],
|
|
93
|
+
"effect": "allow",
|
|
94
|
+
"operations": [
|
|
95
|
+
"accept",
|
|
96
|
+
"stage",
|
|
97
|
+
"commit"
|
|
98
|
+
],
|
|
99
|
+
"evidence": [
|
|
100
|
+
"acceptance-criteria",
|
|
101
|
+
"required-checks",
|
|
102
|
+
"findings-disposition"
|
|
103
|
+
],
|
|
104
|
+
"authority": "orchestrator",
|
|
105
|
+
"text": "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.",
|
|
106
|
+
"controls": {
|
|
107
|
+
"codex": "prompt",
|
|
108
|
+
"claude": "prompt"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "external.explicit-user-authority",
|
|
113
|
+
"roles": [
|
|
114
|
+
"orchestrator",
|
|
115
|
+
"scouter",
|
|
116
|
+
"planner",
|
|
117
|
+
"coder",
|
|
118
|
+
"qa",
|
|
119
|
+
"reviewer"
|
|
120
|
+
],
|
|
121
|
+
"effect": "require",
|
|
122
|
+
"operations": [
|
|
123
|
+
"push",
|
|
124
|
+
"merge",
|
|
125
|
+
"deploy",
|
|
126
|
+
"publish",
|
|
127
|
+
"external-message"
|
|
128
|
+
],
|
|
129
|
+
"evidence": [
|
|
130
|
+
"explicit-user-authorization-for-action"
|
|
131
|
+
],
|
|
132
|
+
"authority": "user",
|
|
133
|
+
"text": "Push, merge, deploy, publish and external messages require explicit user authorization for that action, scope and target. Local commit authority does not grant external authority. Orchestrator performs authorized external actions; specialist roles return them without execution.",
|
|
134
|
+
"controls": {
|
|
135
|
+
"codex": "prompt",
|
|
136
|
+
"claude": "prompt"
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"id": "role.orchestrator-boundary",
|
|
141
|
+
"roles": [
|
|
142
|
+
"orchestrator"
|
|
143
|
+
],
|
|
144
|
+
"effect": "require",
|
|
145
|
+
"operations": [
|
|
146
|
+
"coordinate",
|
|
147
|
+
"accept"
|
|
148
|
+
],
|
|
149
|
+
"evidence": [
|
|
150
|
+
"role-ownership"
|
|
151
|
+
],
|
|
152
|
+
"authority": "orchestrator",
|
|
153
|
+
"text": "Assign design/spec/plan/brainstorming drafts ONLY to Planner and implementation/configuration/test edits to Coder. Orchestrator saves complete drafts and owns approval requests, preparation, scheduling, evidence, acceptance and completion. Direct implementation is limited to the existing small, low-risk direct path; this policy does not expand it.",
|
|
154
|
+
"controls": {
|
|
155
|
+
"codex": "prompt",
|
|
156
|
+
"claude": "prompt"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"id": "role.scouter-read-only",
|
|
161
|
+
"roles": [
|
|
162
|
+
"scouter"
|
|
163
|
+
],
|
|
164
|
+
"effect": "allow",
|
|
165
|
+
"operations": [
|
|
166
|
+
"static-research"
|
|
167
|
+
],
|
|
168
|
+
"evidence": [
|
|
169
|
+
"sources",
|
|
170
|
+
"limits"
|
|
171
|
+
],
|
|
172
|
+
"authority": "orchestrator",
|
|
173
|
+
"text": "Research assigned static sources and report findings, evidence and limits. Do not edit files, install, execute checks, prepare execution targets, inspect live operational state, change external state or decide design, verification, review or acceptance.",
|
|
174
|
+
"controls": {
|
|
175
|
+
"codex": "prompt",
|
|
176
|
+
"claude": "prompt"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"id": "role.planner-draft-only",
|
|
181
|
+
"roles": [
|
|
182
|
+
"planner"
|
|
183
|
+
],
|
|
184
|
+
"effect": "allow",
|
|
185
|
+
"operations": [
|
|
186
|
+
"draft-response"
|
|
187
|
+
],
|
|
188
|
+
"evidence": [
|
|
189
|
+
"prepared-target-evidence",
|
|
190
|
+
"approved-spec-before-dependent-plan"
|
|
191
|
+
],
|
|
192
|
+
"authority": "orchestrator",
|
|
193
|
+
"text": "Return design/spec/plan drafts and dependencies, criteria, hold conditions and verification needs in the response. Do not save documents, implement, run checks, prepare targets, request user approval or decide acceptance. Stop formal target-dependent drafting if actual prepared target evidence is missing; route decisions to Orchestrator.",
|
|
194
|
+
"controls": {
|
|
195
|
+
"codex": "prompt",
|
|
196
|
+
"claude": "prompt"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"id": "role.coder-implementation",
|
|
201
|
+
"roles": [
|
|
202
|
+
"coder"
|
|
203
|
+
],
|
|
204
|
+
"effect": "allow",
|
|
205
|
+
"operations": [
|
|
206
|
+
"assigned-edit",
|
|
207
|
+
"focused-check"
|
|
208
|
+
],
|
|
209
|
+
"evidence": [
|
|
210
|
+
"approved-brief",
|
|
211
|
+
"tdd-or-recorded-exception"
|
|
212
|
+
],
|
|
213
|
+
"authority": "orchestrator",
|
|
214
|
+
"text": "Implement only assigned approved files and focused checks under the existing TDD contract. Report changed files, RED/GREEN or authorized exception evidence, results, limits and follow-up. Do not plan, independently QA/review your own work, accept the task or declare overall completion. Git changes remain forbidden even when implementation succeeds.",
|
|
215
|
+
"controls": {
|
|
216
|
+
"codex": "prompt",
|
|
217
|
+
"claude": "prompt"
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"id": "role.qa-verification",
|
|
222
|
+
"roles": [
|
|
223
|
+
"qa"
|
|
224
|
+
],
|
|
225
|
+
"effect": "allow",
|
|
226
|
+
"operations": [
|
|
227
|
+
"approved-check",
|
|
228
|
+
"scoped-temporary-artifact"
|
|
229
|
+
],
|
|
230
|
+
"evidence": [
|
|
231
|
+
"commands",
|
|
232
|
+
"observations",
|
|
233
|
+
"criterion-evidence"
|
|
234
|
+
],
|
|
235
|
+
"authority": "orchestrator",
|
|
236
|
+
"text": "Run approved checks and report commands, observations, reproduction, evidence and limits. Create only essential temporary data/logs/reports in the brief-authorized location and lifetime. Do not edit product source, tests, fixtures or configuration to pass checks, deploy or accept work. Persistent product-state checks require explicit scope and cleanup ownership. Return failures for Coder correction and required QA recheck.",
|
|
237
|
+
"controls": {
|
|
238
|
+
"codex": "prompt",
|
|
239
|
+
"claude": "prompt"
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"id": "role.reviewer-independent",
|
|
244
|
+
"roles": [
|
|
245
|
+
"reviewer"
|
|
246
|
+
],
|
|
247
|
+
"effect": "allow",
|
|
248
|
+
"operations": [
|
|
249
|
+
"static-review"
|
|
250
|
+
],
|
|
251
|
+
"evidence": [
|
|
252
|
+
"assigned-final-diff",
|
|
253
|
+
"relevant-qa-evidence"
|
|
254
|
+
],
|
|
255
|
+
"authority": "orchestrator",
|
|
256
|
+
"text": "Independently inspect the assigned final changes and evidence and report actionable findings and limits. Remain read-only; do not execute QA tests, edit files, perform Git mutations or decide acceptance.",
|
|
257
|
+
"controls": {
|
|
258
|
+
"codex": "prompt",
|
|
259
|
+
"claude": "prompt"
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"id": "review.significant-no-plan",
|
|
264
|
+
"roles": [
|
|
265
|
+
"orchestrator",
|
|
266
|
+
"scouter",
|
|
267
|
+
"planner",
|
|
268
|
+
"coder",
|
|
269
|
+
"qa",
|
|
270
|
+
"reviewer"
|
|
271
|
+
],
|
|
272
|
+
"effect": "require",
|
|
273
|
+
"operations": [
|
|
274
|
+
"no-plan-final-review"
|
|
275
|
+
],
|
|
276
|
+
"evidence": [
|
|
277
|
+
"required-qa",
|
|
278
|
+
"qa-rechecks"
|
|
279
|
+
],
|
|
280
|
+
"authority": "orchestrator",
|
|
281
|
+
"text": "For significant/high-risk work without a plan: Coder \u2192 QA and required QA rechecks \u2192 Reviewer of the final full change \u2192 Orchestrator acceptance. Do not omit Reviewer merely because no plan exists. This creates no new plan obligation.",
|
|
282
|
+
"controls": {
|
|
283
|
+
"codex": "prompt",
|
|
284
|
+
"claude": "prompt"
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"id": "review.significant-plan",
|
|
289
|
+
"roles": [
|
|
290
|
+
"orchestrator",
|
|
291
|
+
"scouter",
|
|
292
|
+
"planner",
|
|
293
|
+
"coder",
|
|
294
|
+
"qa",
|
|
295
|
+
"reviewer"
|
|
296
|
+
],
|
|
297
|
+
"effect": "require",
|
|
298
|
+
"operations": [
|
|
299
|
+
"plan-final-review"
|
|
300
|
+
],
|
|
301
|
+
"evidence": [
|
|
302
|
+
"all-tasks-accepted",
|
|
303
|
+
"required-qa"
|
|
304
|
+
],
|
|
305
|
+
"authority": "orchestrator",
|
|
306
|
+
"text": "For significant/high-risk plan work: each task uses Coder \u2192 fresh QA as required \u2192 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.",
|
|
307
|
+
"controls": {
|
|
308
|
+
"codex": "prompt",
|
|
309
|
+
"claude": "prompt"
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"id": "review.final-plan-recheck",
|
|
314
|
+
"roles": [
|
|
315
|
+
"orchestrator",
|
|
316
|
+
"scouter",
|
|
317
|
+
"planner",
|
|
318
|
+
"coder",
|
|
319
|
+
"qa",
|
|
320
|
+
"reviewer"
|
|
321
|
+
],
|
|
322
|
+
"effect": "require",
|
|
323
|
+
"operations": [
|
|
324
|
+
"plan-finding-recheck"
|
|
325
|
+
],
|
|
326
|
+
"evidence": [
|
|
327
|
+
"reviewer-findings"
|
|
328
|
+
],
|
|
329
|
+
"authority": "orchestrator",
|
|
330
|
+
"text": "For final overall Reviewer findings on plan work, including behavior findings, use Coder \u2192 Reviewer without QA reassignment; repeat until resolved. This exception applies only to that final plan stage. Preserve required QA and QA failure rechecks before initial final review and outside this exception.",
|
|
331
|
+
"controls": {
|
|
332
|
+
"codex": "prompt",
|
|
333
|
+
"claude": "prompt"
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
],
|
|
337
|
+
"platforms": {
|
|
338
|
+
"codex": {
|
|
339
|
+
"level": "prompt",
|
|
340
|
+
"notice": "Role restrictions are prompt-level contracts, not a filesystem sandbox. No documented role-specific Git hook or generic per-agent tool allowlist is assumed. Existing shell capabilities are retained because static read access after shell reduction has not been verified; Coder and QA need shell for approved checks."
|
|
341
|
+
},
|
|
342
|
+
"claude": {
|
|
343
|
+
"level": "capability",
|
|
344
|
+
"notice": "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."
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"review": {
|
|
348
|
+
"noPlan": [
|
|
349
|
+
"coder",
|
|
350
|
+
"qa",
|
|
351
|
+
"reviewer",
|
|
352
|
+
"orchestrator-accept"
|
|
353
|
+
],
|
|
354
|
+
"planTask": [
|
|
355
|
+
"coder",
|
|
356
|
+
"fresh-qa",
|
|
357
|
+
"orchestrator-accept",
|
|
358
|
+
"orchestrator-commit"
|
|
359
|
+
],
|
|
360
|
+
"planFinal": [
|
|
361
|
+
"required-qa",
|
|
362
|
+
"reviewer"
|
|
363
|
+
],
|
|
364
|
+
"planFinding": [
|
|
365
|
+
"coder",
|
|
366
|
+
"reviewer"
|
|
367
|
+
]
|
|
368
|
+
},
|
|
369
|
+
"git": {
|
|
370
|
+
"schemaVersion": 1,
|
|
371
|
+
"globalValueOptions": [
|
|
372
|
+
"-C",
|
|
373
|
+
"--git-dir",
|
|
374
|
+
"--work-tree"
|
|
375
|
+
],
|
|
376
|
+
"globalFlags": [
|
|
377
|
+
"--no-pager",
|
|
378
|
+
"-P",
|
|
379
|
+
"--literal-pathspecs"
|
|
380
|
+
],
|
|
381
|
+
"commands": {
|
|
382
|
+
"status": {
|
|
383
|
+
"flags": [
|
|
384
|
+
"--short",
|
|
385
|
+
"-s",
|
|
386
|
+
"--branch",
|
|
387
|
+
"-b",
|
|
388
|
+
"--porcelain",
|
|
389
|
+
"--porcelain=v1",
|
|
390
|
+
"--porcelain=v2",
|
|
391
|
+
"--untracked-files=no",
|
|
392
|
+
"--untracked-files=all"
|
|
393
|
+
],
|
|
394
|
+
"values": [],
|
|
395
|
+
"positionals": "any"
|
|
396
|
+
},
|
|
397
|
+
"diff": {
|
|
398
|
+
"flags": [
|
|
399
|
+
"--stat",
|
|
400
|
+
"--numstat",
|
|
401
|
+
"--shortstat",
|
|
402
|
+
"--name-only",
|
|
403
|
+
"--name-status",
|
|
404
|
+
"--oneline",
|
|
405
|
+
"--no-color",
|
|
406
|
+
"--color=never",
|
|
407
|
+
"--no-ext-diff",
|
|
408
|
+
"--no-textconv",
|
|
409
|
+
"--raw",
|
|
410
|
+
"--patch",
|
|
411
|
+
"-p",
|
|
412
|
+
"--summary",
|
|
413
|
+
"--exit-code",
|
|
414
|
+
"--quiet",
|
|
415
|
+
"--check",
|
|
416
|
+
"--cached",
|
|
417
|
+
"--staged",
|
|
418
|
+
"--relative",
|
|
419
|
+
"--no-index"
|
|
420
|
+
],
|
|
421
|
+
"values": [],
|
|
422
|
+
"positionals": "any"
|
|
423
|
+
},
|
|
424
|
+
"log": {
|
|
425
|
+
"flags": [
|
|
426
|
+
"--stat",
|
|
427
|
+
"--numstat",
|
|
428
|
+
"--shortstat",
|
|
429
|
+
"--name-only",
|
|
430
|
+
"--name-status",
|
|
431
|
+
"--oneline",
|
|
432
|
+
"--no-color",
|
|
433
|
+
"--color=never",
|
|
434
|
+
"--no-ext-diff",
|
|
435
|
+
"--no-textconv",
|
|
436
|
+
"--raw",
|
|
437
|
+
"--patch",
|
|
438
|
+
"-p",
|
|
439
|
+
"--summary",
|
|
440
|
+
"--exit-code",
|
|
441
|
+
"--quiet",
|
|
442
|
+
"-<count>",
|
|
443
|
+
"--all",
|
|
444
|
+
"--decorate",
|
|
445
|
+
"--no-decorate",
|
|
446
|
+
"--graph"
|
|
447
|
+
],
|
|
448
|
+
"values": [
|
|
449
|
+
"-n",
|
|
450
|
+
"--max-count",
|
|
451
|
+
"--format",
|
|
452
|
+
"--pretty"
|
|
453
|
+
],
|
|
454
|
+
"positionals": "any"
|
|
455
|
+
},
|
|
456
|
+
"show": {
|
|
457
|
+
"flags": [
|
|
458
|
+
"--stat",
|
|
459
|
+
"--numstat",
|
|
460
|
+
"--shortstat",
|
|
461
|
+
"--name-only",
|
|
462
|
+
"--name-status",
|
|
463
|
+
"--oneline",
|
|
464
|
+
"--no-color",
|
|
465
|
+
"--color=never",
|
|
466
|
+
"--no-ext-diff",
|
|
467
|
+
"--no-textconv",
|
|
468
|
+
"--raw",
|
|
469
|
+
"--patch",
|
|
470
|
+
"-p",
|
|
471
|
+
"--summary",
|
|
472
|
+
"--exit-code",
|
|
473
|
+
"--quiet",
|
|
474
|
+
"--no-patch",
|
|
475
|
+
"-s"
|
|
476
|
+
],
|
|
477
|
+
"values": [
|
|
478
|
+
"--format",
|
|
479
|
+
"--pretty"
|
|
480
|
+
],
|
|
481
|
+
"positionals": "any"
|
|
482
|
+
},
|
|
483
|
+
"rev-parse": {
|
|
484
|
+
"flags": [
|
|
485
|
+
"--show-toplevel",
|
|
486
|
+
"--git-common-dir",
|
|
487
|
+
"--absolute-git-dir",
|
|
488
|
+
"--git-dir",
|
|
489
|
+
"--verify",
|
|
490
|
+
"--short",
|
|
491
|
+
"--is-inside-work-tree",
|
|
492
|
+
"--abbrev-ref",
|
|
493
|
+
"--path-format=absolute"
|
|
494
|
+
],
|
|
495
|
+
"values": [],
|
|
496
|
+
"positionals": "any"
|
|
497
|
+
},
|
|
498
|
+
"ls-files": {
|
|
499
|
+
"flags": [
|
|
500
|
+
"--stage",
|
|
501
|
+
"-s",
|
|
502
|
+
"--cached",
|
|
503
|
+
"--others",
|
|
504
|
+
"--exclude-standard",
|
|
505
|
+
"--deleted",
|
|
506
|
+
"--modified"
|
|
507
|
+
],
|
|
508
|
+
"values": [],
|
|
509
|
+
"positionals": "any"
|
|
510
|
+
},
|
|
511
|
+
"ls-tree": {
|
|
512
|
+
"flags": [
|
|
513
|
+
"-r",
|
|
514
|
+
"--name-only",
|
|
515
|
+
"-l"
|
|
516
|
+
],
|
|
517
|
+
"values": [],
|
|
518
|
+
"positionals": "any"
|
|
519
|
+
},
|
|
520
|
+
"branch": {
|
|
521
|
+
"flags": [
|
|
522
|
+
"--list",
|
|
523
|
+
"--all",
|
|
524
|
+
"-a",
|
|
525
|
+
"--remotes",
|
|
526
|
+
"-r",
|
|
527
|
+
"--show-current",
|
|
528
|
+
"-v",
|
|
529
|
+
"-vv"
|
|
530
|
+
],
|
|
531
|
+
"values": [],
|
|
532
|
+
"positionals": "list"
|
|
533
|
+
},
|
|
534
|
+
"config": {
|
|
535
|
+
"flags": [
|
|
536
|
+
"--get",
|
|
537
|
+
"--get-all",
|
|
538
|
+
"--get-regexp",
|
|
539
|
+
"--list",
|
|
540
|
+
"-l",
|
|
541
|
+
"--show-origin",
|
|
542
|
+
"--show-scope",
|
|
543
|
+
"--local",
|
|
544
|
+
"--global",
|
|
545
|
+
"--system"
|
|
546
|
+
],
|
|
547
|
+
"values": [],
|
|
548
|
+
"positionals": "query"
|
|
549
|
+
},
|
|
550
|
+
"worktree list": {
|
|
551
|
+
"flags": [
|
|
552
|
+
"--porcelain",
|
|
553
|
+
"-z",
|
|
554
|
+
"-v"
|
|
555
|
+
],
|
|
556
|
+
"values": [],
|
|
557
|
+
"positionals": "none"
|
|
558
|
+
},
|
|
559
|
+
"remote": {
|
|
560
|
+
"flags": [
|
|
561
|
+
"-v",
|
|
562
|
+
"--verbose"
|
|
563
|
+
],
|
|
564
|
+
"values": [],
|
|
565
|
+
"positionals": "none"
|
|
566
|
+
},
|
|
567
|
+
"remote get-url": {
|
|
568
|
+
"flags": [
|
|
569
|
+
"--all",
|
|
570
|
+
"--push"
|
|
571
|
+
],
|
|
572
|
+
"values": [],
|
|
573
|
+
"positionals": "any"
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
},
|
|
577
|
+
"runtime": {
|
|
578
|
+
"schemaVersion": 1,
|
|
579
|
+
"roles": [
|
|
580
|
+
"orchestrator",
|
|
581
|
+
"scouter",
|
|
582
|
+
"planner",
|
|
583
|
+
"coder",
|
|
584
|
+
"qa",
|
|
585
|
+
"reviewer"
|
|
586
|
+
],
|
|
587
|
+
"requiredEvidence": [
|
|
588
|
+
"platform-identity",
|
|
589
|
+
"user-approval",
|
|
590
|
+
"current-target-versions",
|
|
591
|
+
"resolved-paths"
|
|
592
|
+
],
|
|
593
|
+
"ruleIds": [
|
|
594
|
+
"runtime.schema",
|
|
595
|
+
"runtime.policy",
|
|
596
|
+
"runtime.identity",
|
|
597
|
+
"runtime.target",
|
|
598
|
+
"runtime.assignment",
|
|
599
|
+
"runtime.approval",
|
|
600
|
+
"runtime.paths",
|
|
601
|
+
"runtime.docs-commit",
|
|
602
|
+
"runtime.mode",
|
|
603
|
+
"runtime.transition"
|
|
604
|
+
],
|
|
605
|
+
"status": "decision-only"
|
|
606
|
+
}
|
|
607
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} WorkflowState
|
|
3
|
+
* @property {1} schemaVersion
|
|
4
|
+
* @property {string} workflowId
|
|
5
|
+
* @property {number} revision
|
|
6
|
+
* @property {object} versions
|
|
7
|
+
* @property {object} target
|
|
8
|
+
* @property {Array<object>} tasks
|
|
9
|
+
* @property {Array<object>} assignments
|
|
10
|
+
* @property {Array<object>} identities
|
|
11
|
+
* @property {Array<object>} leases
|
|
12
|
+
* @typedef {object} NormalizedRequest
|
|
13
|
+
* @property {string} requestId
|
|
14
|
+
* @property {'codex'|'claude'} platform
|
|
15
|
+
* @property {string} operation
|
|
16
|
+
* @property {string} actorRef
|
|
17
|
+
* @property {string} taskId
|
|
18
|
+
* @property {string} cwd
|
|
19
|
+
* @property {string} toolName
|
|
20
|
+
* @property {object} arguments
|
|
21
|
+
* @property {string[]} paths
|
|
22
|
+
* @property {object} descriptor
|
|
23
|
+
* @typedef {object} EvidenceBundle
|
|
24
|
+
* @property {Array<object>} provenance Provider-observed references, never raw tool arguments.
|
|
25
|
+
* @property {Array<object>} [facts] Provider-confirmed facts tied to state and source references.
|
|
26
|
+
*/
|
|
27
|
+
import path from 'node:path';
|
|
28
|
+
import {ROLES, OPERATIONS} from './operations.mjs';
|
|
29
|
+
const fail = message => {throw new Error(`Runtime schema: ${message}`);};
|
|
30
|
+
export const object = value => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
31
|
+
export const text = value => typeof value === 'string' && value.length > 0;
|
|
32
|
+
const hash = value => typeof value === 'string' && /^sha256:[a-f0-9]{64}$/.test(value);
|
|
33
|
+
const strings = value => Array.isArray(value) && value.every(text) && new Set(value).size === value.length;
|
|
34
|
+
const absolute = value => text(value) && path.isAbsolute(value) && path.normalize(value) === value;
|
|
35
|
+
const unique = (items,key) => items.every(x=>object(x)&&text(x[key])) && new Set(items.map(x=>x[key])).size===items.length;
|
|
36
|
+
function approval(a){return object(a)&&text(a.id)&&['user-message','human-confirmation'].includes(a.source)&&text(a.messageRef)&&hash(a.contentHash)&&object(a.scope)&&text(a.scope.taskId)&&absolute(a.scope.target)&&strings(a.scope.operations)&&a.scope.operations.every(op=>OPERATIONS.includes(op))&&strings(a.scope.paths)&&a.scope.paths.every(absolute);}
|
|
37
|
+
/** Validate stored workflow data. Observed provenance must still be checked by evaluate. */
|
|
38
|
+
export function validateWorkflowState(s){
|
|
39
|
+
if(!object(s)||s.schemaVersion!==1||!text(s.workflowId)||!Number.isSafeInteger(s.revision)||s.revision<0)fail('version or identity');
|
|
40
|
+
if(!object(s.versions)||['policy','runtime','adapter','policyHash','runtimeHash','adapterHash'].some(k=>!text(s.versions[k])))fail('versions');
|
|
41
|
+
if(['policyHash','runtimeHash','adapterHash'].some(k=>!hash(s.versions[k])))fail('hash algorithm');
|
|
42
|
+
if(!object(s.target)||!absolute(s.target.realpath)||['repository','worktree','baseHead','head'].some(k=>!text(s.target[k]))||!(s.target.branch===null||text(s.target.branch)))fail('target');
|
|
43
|
+
if(!['plan','small-task','no-plan'].includes(s.mode))fail('mode');
|
|
44
|
+
for(const k of ['documents','approvals','tasks','assignments','identities','leases','checks','findings','acceptances','commits','audit','capabilities','requests'])if(!Array.isArray(s[k]))fail(k);
|
|
45
|
+
if(!unique(s.tasks,'id')||s.tasks.some(t=>!['pending','assigned','rework','verification','accepted','committed'].includes(t.status)||!strings(t.paths)||t.paths.some(p=>!absolute(p))||!strings(t.dependencies)||!text(t.baseCommit)||!strings(t.criteria)||!strings(t.requiredChecks)))fail('tasks');
|
|
46
|
+
if(!unique(s.approvals,'id')||s.approvals.some(a=>!approval(a)))fail('approval provenance');
|
|
47
|
+
if(!unique(s.identities,'actorRef')||s.identities.some(i=>!ROLES.includes(i.role)||!text(i.taskId)||!text(i.observationRef)))fail('identity');
|
|
48
|
+
if(!unique(s.leases,'actorRef')||s.leases.some(l=>!text(l.taskId)||!['active','suspended','retired'].includes(l.status)))fail('lease');
|
|
49
|
+
if(s.assignments.some(a=>!object(a)||!((a.status==='pending'&&a.actorRef===null&&text(a.assignmentId)&&text(a.correlationRef)&&text(a.requestId)&&text(a.requestedBy)&&['codex','claude'].includes(a.platform))||text(a.actorRef))||!text(a.taskId)||!ROLES.includes(a.role)||!strings(a.paths)||a.paths.some(p=>!absolute(p))||!strings(a.operations)||a.operations.some(op=>!OPERATIONS.includes(op))||!text(a.approvalRef)))fail('assignment');
|
|
50
|
+
for(const a of s.assignments){
|
|
51
|
+
if(a.checks!==undefined&&(!Array.isArray(a.checks)||a.checks.some(c=>!object(c)||!absolute(c.executable)||!Array.isArray(c.args)||!c.args.every(x=>typeof x==='string')||!absolute(c.cwd)||!object(c.env)||!strings(c.outputs)||c.outputs.some(p=>!absolute(p)))))fail('check descriptor');
|
|
52
|
+
if(a.temporary!==undefined&&(!object(a.temporary)||!strings(a.temporary.paths)||a.temporary.paths.some(p=>!absolute(p))||!text(a.temporary.cleanupOwner)||!Number.isFinite(Date.parse(a.temporary.expiresAt))))fail('temporary assignment');
|
|
53
|
+
}
|
|
54
|
+
if(new Set(s.assignments.map(a=>a.status==='pending'?'pending:'+a.assignmentId:'actor:'+a.actorRef)).size!==s.assignments.length)fail('ambiguous assignment');
|
|
55
|
+
if(s.documents.some(d=>!object(d)||!['spec','plan'].includes(d.kind)||!absolute(d.path)||!text(d.gitPath)||path.isAbsolute(d.gitPath)||d.gitPath.split('/').includes('..')||!hash(d.contentHash)||!text(d.approvalRef)))fail('document');
|
|
56
|
+
if(s.checks.some(c=>!object(c)||!text(c.id)||!text(c.taskId)||!['passed','failed','pending','unknown'].includes(c.status)||!text(c.fingerprint)||!text(c.actorRef)||!text(c.resultRef)))fail('checks');
|
|
57
|
+
if(s.findings.some(f=>!object(f)||!text(f.id)||!text(f.taskId)))fail('findings');
|
|
58
|
+
if(s.acceptances.some(a=>!object(a)||!text(a.taskId)||!text(a.actorRef)||!text(a.fingerprint)||!strings(a.criteria)||!strings(a.checkIds)||!strings(a.findingIds)))fail('acceptances');
|
|
59
|
+
if(s.commits.some(c=>!object(c)||!text(c.purpose)||!text(c.taskId)||!text(c.expectedParent)||!text(c.expectedTree)))fail('commits');
|
|
60
|
+
if(s.requests.some(r=>!object(r)||!text(r.requestId)||!hash(r.requestFingerprint)||!object(r.decision))||new Set(s.requests.map(r=>r.requestId)).size!==s.requests.length)fail('request replay');
|
|
61
|
+
return s;
|
|
62
|
+
}
|
|
63
|
+
export function validateRequest(r){
|
|
64
|
+
if(!object(r)||['requestId','actorRef','taskId','toolName'].some(k=>!text(r[k]))||!['codex','claude'].includes(r.platform)||!OPERATIONS.includes(r.operation)||!absolute(r.cwd)||!object(r.arguments)||!object(r.descriptor)||!strings(r.paths)||r.paths.some(p=>!absolute(p)))fail('request');
|
|
65
|
+
return r;
|
|
66
|
+
}
|
|
67
|
+
export function validateEvidence(e){
|
|
68
|
+
if(!object(e)||!Array.isArray(e.provenance)||!unique(e.provenance,'id'))fail('evidence');
|
|
69
|
+
if(e.resolvedPaths!==undefined&&(!Array.isArray(e.resolvedPaths)||e.resolvedPaths.some(p=>!object(p)||!absolute(p.path)||!absolute(p.realpath))))fail('resolved paths');
|
|
70
|
+
if(e.facts!==undefined&&(!Array.isArray(e.facts)||e.facts.some(f=>!object(f)||!text(f.kind)||!text(f.workflowId)||!Number.isSafeInteger(f.revision)||!object(f.target)||!hash(f.policyHash)||!text(f.sourceRef)||!object(f.data))))fail('facts');
|
|
71
|
+
for(const p of e.provenance){
|
|
72
|
+
if(!['platform-event','user-message','human-confirmation'].includes(p.source))fail('provenance source');
|
|
73
|
+
if(p.source==='platform-event'&&(!text(p.eventRef)||!text(p.actorRef)||!['codex','claude'].includes(p.platform)))fail('platform provenance');
|
|
74
|
+
if(p.source!=='platform-event'&&(!text(p.messageRef)||!hash(p.contentHash)))fail('approval provenance');
|
|
75
|
+
if(!object(p.verification)||p.verification.status!=='verified'||!text(p.verification.verifierRef)||!text(p.verification.sourceRef))fail('unverified provenance');
|
|
76
|
+
}
|
|
77
|
+
return e;
|
|
78
|
+
}
|