owlrunkit 0.19.1 → 0.19.2
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 +37 -0
- package/README.md +71 -0
- package/docs/architecture/OWLCODA_RUNKIT_0191_PROFILE_RECONCILE_PATCH_PRODUCT_DECISION_20260813.md +11 -5
- package/docs/architecture/OWLCODA_RUNKIT_0192_FORMAL_USABILITY_PRODUCT_DECISION_20260813.md +141 -0
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +50 -7
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
- package/package.json +1 -1
- package/packages/attest/distribution-manifest-v1.json +5 -0
- package/packages/attest/src/quick.mjs +37 -4
- package/registry-release-policy-v1.json +5 -5
- package/sbom.spdx.json +5 -5
- package/scripts/runkit-contract/core-contract.mjs +35 -2
- package/scripts/runkit-contract/efficiency-metrics.mjs +9 -7
- package/scripts/runkit-contract/formal-preflight.mjs +352 -0
- package/scripts/runkit-contract/formal-supplemental-evidence.mjs +713 -0
- package/scripts/runkit-contract/formal-workflow.mjs +529 -59
- package/scripts/runkit-contract/onboarding-doctor.mjs +32 -13
- package/scripts/runkit-contract/project-cli-resolver.mjs +30 -3
- package/scripts/runkit-contract/project-external-delivery.mjs +16 -9
- package/scripts/runkit-contract/quick-attest.mjs +24 -0
- package/scripts/runkit-contract/runkit-cli.mjs +365 -49
- package/scripts/runkit-contract/schemas/formal-check-v2.schema.json +231 -0
- package/scripts/runkit-contract/schemas/formal-envelope-preflight-v1.schema.json +212 -0
- package/scripts/runkit-contract/schemas/formal-evidence-summary-v1.schema.json +114 -0
- package/scripts/runkit-contract/schemas/formal-supplemental-evidence-v1.schema.json +103 -0
- package/scripts/runkit-contract/schemas/team-project-event-v5.schema.json +89 -0
- package/scripts/runkit-contract/schemas/team-project-status-v3.schema.json +173 -0
- package/scripts/runkit-contract/snapshot.mjs +125 -5
- package/scripts/runkit-contract/source-candidate.mjs +271 -69
- package/scripts/runkit-contract/sync-release-identity.mjs +39 -4
- package/scripts/runkit-contract/team-project-successor.mjs +7 -4
- package/scripts/runkit-contract/team-project.mjs +440 -28
- package/scripts/runkit-contract/usage-mode.mjs +9 -3
- package/scripts/runkit-contract/verification-envelope.mjs +425 -37
|
@@ -63,12 +63,21 @@ import {
|
|
|
63
63
|
runHighLevelVerify,
|
|
64
64
|
} from "./lifecycle-orchestration.mjs";
|
|
65
65
|
import {
|
|
66
|
-
|
|
66
|
+
finalizeFormalChecksWithinControlTransaction,
|
|
67
67
|
recordFormalCheckV1,
|
|
68
68
|
recordFormalEnvelopeCheckV1,
|
|
69
69
|
resumeCompletedFormalFinishV1,
|
|
70
70
|
validateLegacyVerificationSideEffectsV1,
|
|
71
71
|
} from "./formal-workflow.mjs";
|
|
72
|
+
import {
|
|
73
|
+
formatFormalEnvelopePreflightHumanV1,
|
|
74
|
+
preflightFormalEnvelopeV1,
|
|
75
|
+
} from "./formal-preflight.mjs";
|
|
76
|
+
import {
|
|
77
|
+
attachFormalSupplementalEvidenceV1,
|
|
78
|
+
reattestFormalEvidenceSummaryV1,
|
|
79
|
+
summarizeFormalEvidenceWithinControlTransaction,
|
|
80
|
+
} from "./formal-supplemental-evidence.mjs";
|
|
72
81
|
import {
|
|
73
82
|
freezeSourceCandidateV1,
|
|
74
83
|
freezeSourceCandidateV2,
|
|
@@ -162,7 +171,7 @@ import { OFFICIAL_NPM_REGISTRY } from "./registry-adoption-gate.mjs";
|
|
|
162
171
|
import {
|
|
163
172
|
appendTeamProjectEventV1,
|
|
164
173
|
assignTeamProjectV1,
|
|
165
|
-
|
|
174
|
+
buildTeamProjectTakeoverV3,
|
|
166
175
|
checkpointTeamProjectV1,
|
|
167
176
|
closeTeamProjectVerificationV1,
|
|
168
177
|
deferTeamProjectVerificationV1,
|
|
@@ -173,9 +182,11 @@ import {
|
|
|
173
182
|
integrateTeamProjectV1,
|
|
174
183
|
openTeamProjectDecisionV1,
|
|
175
184
|
readTeamProjectStatusV2,
|
|
185
|
+
readTeamProjectStatusV3,
|
|
176
186
|
rejectAndReturnTeamProjectV1,
|
|
177
187
|
reopenUpstreamTeamProjectV1,
|
|
178
188
|
resolveTeamProjectDecisionV1,
|
|
189
|
+
reviseTeamProjectWorkItemScopeV1,
|
|
179
190
|
transferTeamProjectV1,
|
|
180
191
|
} from "./team-project.mjs";
|
|
181
192
|
import {
|
|
@@ -205,7 +216,7 @@ Quick Verification
|
|
|
205
216
|
Low-risk, source-bound reusable evidence without writer leases or acceptance.
|
|
206
217
|
|
|
207
218
|
Formal Delivery
|
|
208
|
-
npx --no-install owlrunkit formal <start|check|finish> --workspace . --run-id <id> [...]
|
|
219
|
+
npx --no-install owlrunkit formal <start|preflight|check|attach-evidence|finish> --workspace . --run-id <id> [...]
|
|
209
220
|
Use for multi-writer, permissions, security, funds, irreversible change,
|
|
210
221
|
uncertain rollback, schema/data migration, or explicit Formal acceptance.
|
|
211
222
|
Frozen dirty source
|
|
@@ -222,7 +233,7 @@ Fleet and status
|
|
|
222
233
|
npx --no-install owlrunkit fleet discover; npx --no-install owlrunkit status --workspace .
|
|
223
234
|
|
|
224
235
|
Agent team projects
|
|
225
|
-
npx --no-install owlrunkit project <init|assign|checkpoint|handoff|reject-and-return|reopen-upstream|transfer|decision|verification|capture|target-snapshot|import-delivery|status|takeover|successor> [options]
|
|
236
|
+
npx --no-install owlrunkit project <init|assign|checkpoint|handoff|reject-and-return|reopen-upstream|transfer|work-item revise-scope|decision|verification|capture|target-snapshot|import-delivery|status|takeover|successor> [options]
|
|
226
237
|
Durable Agent work, dependencies, decisions, gates, progress, and handoffs.
|
|
227
238
|
Core successor
|
|
228
239
|
npx --no-install owlrunkit core-successor <plan|apply|resume> --workspace . [...]
|
|
@@ -431,7 +442,9 @@ high-confidence unambiguous profile.
|
|
|
431
442
|
`,
|
|
432
443
|
formal: `Usage:
|
|
433
444
|
npx --no-install owlrunkit formal start --workspace <directory> --run-id <id> [...]
|
|
445
|
+
npx --no-install owlrunkit formal preflight --workspace <directory> --envelope <file>
|
|
434
446
|
npx --no-install owlrunkit formal check --workspace <directory> --run-id <id> -- <command>
|
|
447
|
+
npx --no-install owlrunkit formal attach-evidence --workspace <directory> --run-id <id> [...]
|
|
435
448
|
npx --no-install owlrunkit formal finish --workspace <directory> --run-id <id>
|
|
436
449
|
`,
|
|
437
450
|
"formal start": `Usage:
|
|
@@ -439,18 +452,38 @@ high-confidence unambiguous profile.
|
|
|
439
452
|
--goal <goal.json> --work-item <id> --owned-path <path>
|
|
440
453
|
|
|
441
454
|
Creates the execution and exact writer lease.
|
|
455
|
+
`,
|
|
456
|
+
"formal preflight": `Usage:
|
|
457
|
+
npx --no-install owlrunkit formal preflight --workspace <directory>
|
|
458
|
+
--envelope <verification-envelope.json> [--json]
|
|
459
|
+
|
|
460
|
+
Reads the envelope, enforcement backend, known subprocess requirements, temporary
|
|
461
|
+
directory needs, and protected RunKit runtime scan conflicts without executing
|
|
462
|
+
the command or writing Formal evidence. It grants no authorization.
|
|
442
463
|
`,
|
|
443
464
|
"formal check": `Usage:
|
|
444
465
|
npx --no-install owlrunkit formal check --workspace <directory> --run-id <id>
|
|
445
|
-
--work-item <id> --
|
|
466
|
+
(--work-item <id> | --from-lease <id>) --check-id <id>
|
|
467
|
+
--envelope <verification-envelope.json>
|
|
446
468
|
npx --no-install owlrunkit formal check --workspace <directory> --run-id <id>
|
|
447
|
-
--work-item <id> --
|
|
469
|
+
(--work-item <id> | --from-lease <id>) --check-id <id>
|
|
470
|
+
--cwd <directory> -- <built-in-command> [args...]
|
|
448
471
|
|
|
449
472
|
Verification Envelopes admit real project commands only when file, network,
|
|
450
473
|
process, environment, output, timeout, and cleanup constraints are enforced.
|
|
474
|
+
`,
|
|
475
|
+
"formal attach-evidence": `Usage:
|
|
476
|
+
npx --no-install owlrunkit formal attach-evidence --workspace <directory>
|
|
477
|
+
--run-id <id> --evidence-id <id> --kind supplemental-local|networked
|
|
478
|
+
--receipt <quick-receipt.json> [--json]
|
|
479
|
+
|
|
480
|
+
Attests one passing Quick receipt and binds it to the current Formal source
|
|
481
|
+
candidate as non-gating supplemental evidence. It cannot replace a Formal check
|
|
482
|
+
or grant Git, release, deployment, production, or business authorization.
|
|
451
483
|
`,
|
|
452
484
|
"formal finish": `Usage:
|
|
453
485
|
npx --no-install owlrunkit formal finish --workspace <directory> --run-id <id>
|
|
486
|
+
[--decision accepted|rejected|blocked] [--finalize-id <id>]
|
|
454
487
|
|
|
455
488
|
Runs the final source, evidence, permission, closeout, and lease-release path.
|
|
456
489
|
`,
|
|
@@ -579,6 +612,13 @@ No self-reported percentage is accepted.
|
|
|
579
612
|
Measured WorkItems require --completed-units on every checkpoint. A completed
|
|
580
613
|
checkpoint must use the WorkItem's declared total. Example:
|
|
581
614
|
npx --no-install owlrunkit project checkpoint --workspace . --checkpoint-id checkpoint-x --at 2026-08-11T00:00:00.000Z --assignment-id assign-x --work-item x --state completed --summary 'Completed x.' --completed-units 5 --evidence receipt:quick
|
|
615
|
+
`,
|
|
616
|
+
"project init": `Usage:
|
|
617
|
+
npx --no-install owlrunkit project init --workspace <directory>
|
|
618
|
+
--definition <project-definition.json> [--json]
|
|
619
|
+
|
|
620
|
+
Creates one project-owned definition and empty immutable event journal. It does
|
|
621
|
+
not grant Git, release, deployment, production, or business authorization.
|
|
582
622
|
`,
|
|
583
623
|
"project assign": `Usage:
|
|
584
624
|
npx --no-install owlrunkit project assign --workspace <directory>
|
|
@@ -588,6 +628,55 @@ checkpoint must use the WorkItem's declared total. Example:
|
|
|
588
628
|
|
|
589
629
|
Assigns one current WorkItem owner without granting Git, release, deployment,
|
|
590
630
|
production, business, or other authorization.
|
|
631
|
+
`,
|
|
632
|
+
"project handoff": `Usage:
|
|
633
|
+
npx --no-install owlrunkit project handoff --workspace <directory>
|
|
634
|
+
--handoff-id <id> --at <ISO-UTC> --assignment-id <current>
|
|
635
|
+
--work-item <id> --from-agent <id> --to-agent <id>
|
|
636
|
+
--summary <text> --next <text> --evidence <ref> [--evidence <ref> ...] [--json]
|
|
637
|
+
|
|
638
|
+
Records an immutable handoff without assigning successor authority or granting
|
|
639
|
+
Git, release, deployment, production, or business authorization.
|
|
640
|
+
`,
|
|
641
|
+
"project decision": `Usage:
|
|
642
|
+
npx --no-install owlrunkit project decision --workspace <directory>
|
|
643
|
+
--open --decision-id <id> --at <ISO-UTC> --title <text> --question <text>
|
|
644
|
+
--owner-agent <id> [--blocking-work-item <id> ...]
|
|
645
|
+
--option <text> [--option <text> ...] [--json]
|
|
646
|
+
npx --no-install owlrunkit project decision --workspace <directory>
|
|
647
|
+
--resolve --decision-id <id> --at <ISO-UTC> --resolution <text>
|
|
648
|
+
--rationale <text> --evidence <ref> [--evidence <ref> ...] [--json]
|
|
649
|
+
|
|
650
|
+
Opens or resolves one durable project decision. Resolution records truth but
|
|
651
|
+
does not grant Git, release, deployment, production, or business authorization.
|
|
652
|
+
`,
|
|
653
|
+
"project verification": `Usage:
|
|
654
|
+
npx --no-install owlrunkit project verification --workspace <directory>
|
|
655
|
+
--defer --verification-id <id> --at <ISO-UTC> --work-item <id>
|
|
656
|
+
--owner-agent <id> --check <check-id> [--check <check-id> ...]
|
|
657
|
+
--reason <text> --due-gate <gate-id> [--json]
|
|
658
|
+
npx --no-install owlrunkit project verification --workspace <directory>
|
|
659
|
+
--close --verification-id <id> --at <ISO-UTC>
|
|
660
|
+
--disposition <verified|no_longer_required> --summary <text>
|
|
661
|
+
[--evidence <ref> ...] [--decision <resolved-decision-id> ...] [--json]
|
|
662
|
+
|
|
663
|
+
Records an intentionally deferred check or closes it with evidence. It does not
|
|
664
|
+
execute the check and grants no additional authorization.
|
|
665
|
+
`,
|
|
666
|
+
"project integrate": `Usage:
|
|
667
|
+
npx --no-install owlrunkit project integrate --workspace <directory>
|
|
668
|
+
--gate <gate-id> --at <ISO-UTC> --summary <text>
|
|
669
|
+
--evidence <ref> [--evidence <ref> ...] [--json]
|
|
670
|
+
|
|
671
|
+
Records one passed integration gate after its dependencies and deferred checks
|
|
672
|
+
are satisfied. It does not perform Git integration or grant release authority.
|
|
673
|
+
`,
|
|
674
|
+
"project capture": `Usage:
|
|
675
|
+
npx --no-install owlrunkit project capture --workspace <directory>
|
|
676
|
+
--request <legacy-event.json> [--json]
|
|
677
|
+
|
|
678
|
+
Compatibility-only raw event capture. External source delivery must use
|
|
679
|
+
project import-delivery. This action grants no repository or business authority.
|
|
591
680
|
`,
|
|
592
681
|
"project reject-and-return": `Usage:
|
|
593
682
|
npx --no-install owlrunkit project reject-and-return --workspace <directory> --rework-id <id> --at <ISO-UTC>
|
|
@@ -622,6 +711,19 @@ authority is granted.
|
|
|
622
711
|
Atomically records checkpoint, handoff, and successor-assignment facts inside one
|
|
623
712
|
immutable Event V4 envelope. Terminal WorkItems cannot transfer. No Git, release,
|
|
624
713
|
deployment, production, or business authority is granted.
|
|
714
|
+
`,
|
|
715
|
+
"project work-item revise-scope": `Usage:
|
|
716
|
+
npx --no-install owlrunkit project work-item revise-scope --workspace <directory>
|
|
717
|
+
--revision-id <id> --at <ISO-UTC> --assignment-id <current>
|
|
718
|
+
--work-item <id> --owner-agent <current-owner>
|
|
719
|
+
[--owned-path <path> ...]
|
|
720
|
+
[--measurable-unit <unit> --measurable-total <positive-int> | --unmeasured]
|
|
721
|
+
--reason <text> [--evidence <ref> ...] [--json]
|
|
722
|
+
|
|
723
|
+
Records an immutable Event V5 that supersedes the WorkItem's prior scope. Omitted
|
|
724
|
+
ownedPaths or measurable fields retain their current values. The event never
|
|
725
|
+
rewrites the project definition and grants no Git, release, deployment,
|
|
726
|
+
production, or business authority.
|
|
625
727
|
`,
|
|
626
728
|
"project target-snapshot": `Usage:
|
|
627
729
|
npx --no-install owlrunkit project target-snapshot --workspace <controller>
|
|
@@ -843,7 +945,7 @@ function formatTeamProjectIntegrationHuman(result) {
|
|
|
843
945
|
: String(result.nextAction).replace(/\s+/gu, " ").trim();
|
|
844
946
|
return [
|
|
845
947
|
`${disposition} project integration gate ${result.gateId}.`,
|
|
846
|
-
`
|
|
948
|
+
`Work ledger: ${result.overall}; delivery: ${result.deliveryDisposition}; next: ${nextAction}${result.nextActorId ? ` (owner ${result.nextActorId})` : ""}`,
|
|
847
949
|
"Git/release not performed.",
|
|
848
950
|
"",
|
|
849
951
|
].join("\n");
|
|
@@ -857,6 +959,9 @@ function formatTeamProjectCheckpointHuman(result) {
|
|
|
857
959
|
return [
|
|
858
960
|
`${disposition} checkpoint ${result.checkpointId} for WorkItem ${result.workItemId}: ${result.state}.`,
|
|
859
961
|
`Project state: ${result.overall}; next: ${nextAction}${result.nextActorId ? ` (owner ${result.nextActorId})` : ""}`,
|
|
962
|
+
...(result.warnings?.length > 0
|
|
963
|
+
? [`Warning: ${result.warnings.map(row => row.code).join(", ")}.`]
|
|
964
|
+
: []),
|
|
860
965
|
"",
|
|
861
966
|
].join("\n");
|
|
862
967
|
}
|
|
@@ -1912,7 +2017,7 @@ function inspect(options) {
|
|
|
1912
2017
|
const onboarding = onboardingProjection(root, recovery);
|
|
1913
2018
|
const projectDefinitionPath = runtimePath(root, "project", "definition.json");
|
|
1914
2019
|
const projectDriver = pathEntryExists(projectDefinitionPath)
|
|
1915
|
-
?
|
|
2020
|
+
? readTeamProjectStatusV3({ workspaceRoot: root })
|
|
1916
2021
|
: null;
|
|
1917
2022
|
const summary = buildInspectSummary(result, {
|
|
1918
2023
|
maintenanceNextAction: onboarding.maintenanceNextAction ?? null,
|
|
@@ -2014,6 +2119,20 @@ function closeout(options) {
|
|
|
2014
2119
|
releasedLeaseIds,
|
|
2015
2120
|
};
|
|
2016
2121
|
}
|
|
2122
|
+
const formalEvidenceSummary = options["formal-evidence-summary"] ?? null;
|
|
2123
|
+
if (
|
|
2124
|
+
formalEvidenceSummary !== null
|
|
2125
|
+
&& (
|
|
2126
|
+
decision !== "accepted"
|
|
2127
|
+
|| formalEvidenceSummary.status !== "formal_evidence_summarized"
|
|
2128
|
+
|| typeof formalEvidenceSummary.evidenceSummaryPath !== "string"
|
|
2129
|
+
|| !/^[a-f0-9]{64}$/u.test(
|
|
2130
|
+
formalEvidenceSummary.evidenceSummarySha256 ?? "",
|
|
2131
|
+
)
|
|
2132
|
+
)
|
|
2133
|
+
) {
|
|
2134
|
+
throw new Error("Formal evidence summary binding is invalid for closeout.");
|
|
2135
|
+
}
|
|
2017
2136
|
const created = createCoreArtifact({
|
|
2018
2137
|
core: pin,
|
|
2019
2138
|
producer: { adapterKind: "codex", adapterVersion: "0.1.0" },
|
|
@@ -2023,7 +2142,24 @@ function closeout(options) {
|
|
|
2023
2142
|
authorizationGranted: false,
|
|
2024
2143
|
...(acceptedVerification ? { verification: acceptedVerification } : {}),
|
|
2025
2144
|
},
|
|
2026
|
-
extensions: {
|
|
2145
|
+
extensions: {
|
|
2146
|
+
"dev.owlcoda.adapter.codex": {},
|
|
2147
|
+
...(formalEvidenceSummary === null
|
|
2148
|
+
? {}
|
|
2149
|
+
: {
|
|
2150
|
+
"dev.owlcoda.formal-evidence": {
|
|
2151
|
+
schemaVersion: "OwlCodaRunKitFormalEvidenceCloseoutBindingV1",
|
|
2152
|
+
summaryPath: formalEvidenceSummary.evidenceSummaryPath,
|
|
2153
|
+
summarySha256: formalEvidenceSummary.evidenceSummarySha256,
|
|
2154
|
+
formalCheckCount: formalEvidenceSummary.formalCheckCount,
|
|
2155
|
+
supplementalEvidenceCount:
|
|
2156
|
+
formalEvidenceSummary.supplementalEvidenceCount,
|
|
2157
|
+
staleSupplementalEvidenceCount:
|
|
2158
|
+
formalEvidenceSummary.staleSupplementalEvidenceCount,
|
|
2159
|
+
authorizationGranted: false,
|
|
2160
|
+
},
|
|
2161
|
+
}),
|
|
2162
|
+
},
|
|
2027
2163
|
});
|
|
2028
2164
|
const closeoutPath = path.join(executionRoot, "closeout-receipt.json");
|
|
2029
2165
|
writeJsonExclusiveAtomically(closeoutPath, created);
|
|
@@ -2038,15 +2174,16 @@ function closeout(options) {
|
|
|
2038
2174
|
return { status: "closed", exitCode: 0, runId, decision, authorizationGranted: false, ...created };
|
|
2039
2175
|
}
|
|
2040
2176
|
|
|
2041
|
-
function
|
|
2177
|
+
function finishExecutionWithinControlTransaction(options, {
|
|
2178
|
+
formalEvidenceSummary = null,
|
|
2179
|
+
} = {}) {
|
|
2042
2180
|
const root = workspace(options);
|
|
2043
2181
|
const runId = safeRunId(requireOption(options, "run-id"));
|
|
2044
2182
|
const decision = requireOption(options, "decision");
|
|
2045
2183
|
if (!new Set(["accepted", "rejected", "blocked"]).has(decision)) {
|
|
2046
2184
|
throw new Error("decision must be accepted, rejected, or blocked.");
|
|
2047
2185
|
}
|
|
2048
|
-
|
|
2049
|
-
const executionRoot = runtimePath(root, "executions", runId);
|
|
2186
|
+
const executionRoot = runtimePath(root, "executions", runId);
|
|
2050
2187
|
const closeoutPath = path.join(executionRoot, "closeout-receipt.json");
|
|
2051
2188
|
if (pathEntryExists(closeoutPath)) {
|
|
2052
2189
|
if (lstatSync(closeoutPath).isSymbolicLink()) {
|
|
@@ -2090,6 +2227,9 @@ function finishExecution(options) {
|
|
|
2090
2227
|
closed = closeout({
|
|
2091
2228
|
...options,
|
|
2092
2229
|
...(gate ? { "gate-input": gate.gateInputPath } : {}),
|
|
2230
|
+
...(formalEvidenceSummary === null
|
|
2231
|
+
? {}
|
|
2232
|
+
: { "formal-evidence-summary": formalEvidenceSummary }),
|
|
2093
2233
|
});
|
|
2094
2234
|
if (closed.status !== "closed") {
|
|
2095
2235
|
rollbackReleasedLeases();
|
|
@@ -2109,7 +2249,14 @@ function finishExecution(options) {
|
|
|
2109
2249
|
closeoutArtifactSha256: closed.artifactSha256,
|
|
2110
2250
|
authorizationGranted: false,
|
|
2111
2251
|
};
|
|
2112
|
-
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
function finishExecution(options) {
|
|
2255
|
+
const root = workspace(options);
|
|
2256
|
+
return withControlTransaction(
|
|
2257
|
+
root,
|
|
2258
|
+
() => finishExecutionWithinControlTransaction(options),
|
|
2259
|
+
);
|
|
2113
2260
|
}
|
|
2114
2261
|
|
|
2115
2262
|
function requestCommand(options, handler) {
|
|
@@ -2161,7 +2308,12 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
2161
2308
|
"profiles",
|
|
2162
2309
|
"project",
|
|
2163
2310
|
]).has(command);
|
|
2164
|
-
|
|
2311
|
+
let [action, ...nestedOptions] = nested ? optionValues : [null, ...optionValues];
|
|
2312
|
+
if (command === "project" && action === "work-item"
|
|
2313
|
+
&& nestedOptions[0] === "revise-scope") {
|
|
2314
|
+
action = "work-item revise-scope";
|
|
2315
|
+
nestedOptions = nestedOptions.slice(1);
|
|
2316
|
+
}
|
|
2165
2317
|
const helpRequested = optionValues.includes("--help")
|
|
2166
2318
|
|| optionValues.includes("-h");
|
|
2167
2319
|
if (helpRequested) {
|
|
@@ -2213,6 +2365,8 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
2213
2365
|
? ["evidence", "blocker", "decision"]
|
|
2214
2366
|
: command === "project" && action === "decision"
|
|
2215
2367
|
? ["blocking-work-item", "option", "evidence"]
|
|
2368
|
+
: command === "project" && action === "work-item revise-scope"
|
|
2369
|
+
? ["owned-path", "evidence"]
|
|
2216
2370
|
: command === "efficiency" && action === "record"
|
|
2217
2371
|
? ["evidence"]
|
|
2218
2372
|
: [],
|
|
@@ -2242,11 +2396,15 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
2242
2396
|
? ["json"]
|
|
2243
2397
|
: command === "bootstrap"
|
|
2244
2398
|
? ["json", "dry-run", "apply"]
|
|
2399
|
+
: command === "formal" && new Set(["preflight", "attach-evidence"]).has(action)
|
|
2400
|
+
? ["json"]
|
|
2245
2401
|
: command === "project" && action === "decision"
|
|
2246
2402
|
? ["json", "open", "resolve"]
|
|
2247
2403
|
: command === "project" && action === "verification"
|
|
2248
2404
|
? ["json", "defer", "close"]
|
|
2249
|
-
: command === "project" &&
|
|
2405
|
+
: command === "project" && action === "work-item revise-scope"
|
|
2406
|
+
? ["json", "unmeasured"]
|
|
2407
|
+
: command === "project" && new Set(["init", "assign", "handoff", "reject-and-return", "reopen-upstream", "transfer", "checkpoint", "integrate", "capture", "status", "takeover", "successor"]).has(action)
|
|
2250
2408
|
? ["json"]
|
|
2251
2409
|
: command === "project" && new Set(["target-snapshot", "import-delivery"]).has(action)
|
|
2252
2410
|
? ["json", "dry-run", "apply"]
|
|
@@ -2361,6 +2519,10 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
2361
2519
|
]);
|
|
2362
2520
|
const recommendation = recommendUsageModeV2({
|
|
2363
2521
|
workspaceRoot: root,
|
|
2522
|
+
projectDriverPresent: existsSync(path.join(
|
|
2523
|
+
root,
|
|
2524
|
+
".owlcoda/runkit/project/definition.json",
|
|
2525
|
+
)),
|
|
2364
2526
|
requestedMode: options["requested-mode"] ?? "auto",
|
|
2365
2527
|
needsDurableEvidence: options["needs-evidence"] === true,
|
|
2366
2528
|
exactCommandCount: parseCanonicalNonnegativeSafeInteger(
|
|
@@ -2394,6 +2556,10 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
2394
2556
|
assertOnlyOptions(options, ["workspace", "json"]);
|
|
2395
2557
|
const recommendation = recommendUsageModeV2({
|
|
2396
2558
|
workspaceRoot: root,
|
|
2559
|
+
projectDriverPresent: existsSync(path.join(
|
|
2560
|
+
root,
|
|
2561
|
+
".owlcoda/runkit/project/definition.json",
|
|
2562
|
+
)),
|
|
2397
2563
|
requestedMode: "auto",
|
|
2398
2564
|
needsDurableEvidence: false,
|
|
2399
2565
|
exactCommandCount: 0,
|
|
@@ -2974,12 +3140,37 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
2974
3140
|
throw new Error("Usage: npx --no-install owlrunkit deployment <prepare|execute> [options]");
|
|
2975
3141
|
}
|
|
2976
3142
|
if (command === "formal") {
|
|
3143
|
+
const allowedFormalOptions = {
|
|
3144
|
+
start: ["workspace", "run-id", "goal", "work-item", "owned-path"],
|
|
3145
|
+
preflight: ["workspace", "envelope", "json"],
|
|
3146
|
+
check: ["workspace", "run-id", "work-item", "from-lease", "check-id", "envelope", "cwd"],
|
|
3147
|
+
"attach-evidence": ["workspace", "run-id", "evidence-id", "kind", "receipt", "json"],
|
|
3148
|
+
finish: ["workspace", "run-id", "decision", "finalize-id"],
|
|
3149
|
+
};
|
|
3150
|
+
if (!Object.hasOwn(allowedFormalOptions, action)) {
|
|
3151
|
+
throw new Error("Usage: npx --no-install owlrunkit formal <start|preflight|check|attach-evidence|finish> [options]");
|
|
3152
|
+
}
|
|
3153
|
+
assertOnlyOptions(options, allowedFormalOptions[action]);
|
|
2977
3154
|
if (action === "start") {
|
|
2978
3155
|
return startExecution({
|
|
2979
3156
|
...options,
|
|
2980
3157
|
"work-item": options["work-item"] ?? "delivery",
|
|
2981
3158
|
});
|
|
2982
3159
|
}
|
|
3160
|
+
if (action === "preflight") {
|
|
3161
|
+
const root = workspace(options);
|
|
3162
|
+
const envelope = readJson(realpathSync(requireOption(options, "envelope")));
|
|
3163
|
+
const preflight = preflightFormalEnvelopeV1({
|
|
3164
|
+
workspaceRoot: root,
|
|
3165
|
+
envelope,
|
|
3166
|
+
});
|
|
3167
|
+
return options.json === true
|
|
3168
|
+
? preflight
|
|
3169
|
+
: withHumanOutput(
|
|
3170
|
+
preflight,
|
|
3171
|
+
formatFormalEnvelopePreflightHumanV1(preflight),
|
|
3172
|
+
);
|
|
3173
|
+
}
|
|
2983
3174
|
if (action === "check") {
|
|
2984
3175
|
const workItemId = options["work-item"] ?? options["from-lease"] ?? "delivery";
|
|
2985
3176
|
if (
|
|
@@ -2993,12 +3184,17 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
2993
3184
|
if (commandArgv.length > 0) {
|
|
2994
3185
|
throw new Error("formal check accepts either --envelope or an exact built-in command, not both.");
|
|
2995
3186
|
}
|
|
3187
|
+
if (options.cwd !== undefined) {
|
|
3188
|
+
throw new Error("formal check --cwd is only valid with an exact built-in command.");
|
|
3189
|
+
}
|
|
3190
|
+
const root = workspace(options);
|
|
3191
|
+
const envelope = readJson(realpathSync(requireOption(options, "envelope")));
|
|
2996
3192
|
return await recordFormalEnvelopeCheckV1({
|
|
2997
|
-
workspaceRoot:
|
|
3193
|
+
workspaceRoot: root,
|
|
2998
3194
|
runId: safeRunId(requireOption(options, "run-id")),
|
|
2999
3195
|
workItemId,
|
|
3000
3196
|
checkId: requireOption(options, "check-id"),
|
|
3001
|
-
envelope
|
|
3197
|
+
envelope,
|
|
3002
3198
|
});
|
|
3003
3199
|
}
|
|
3004
3200
|
return recordFormalCheckV1({
|
|
@@ -3010,6 +3206,15 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
3010
3206
|
commandArgv,
|
|
3011
3207
|
});
|
|
3012
3208
|
}
|
|
3209
|
+
if (action === "attach-evidence") {
|
|
3210
|
+
return attachFormalSupplementalEvidenceV1({
|
|
3211
|
+
workspaceRoot: workspace(options),
|
|
3212
|
+
runId: safeRunId(requireOption(options, "run-id")),
|
|
3213
|
+
evidenceId: requireOption(options, "evidence-id"),
|
|
3214
|
+
kind: requireOption(options, "kind"),
|
|
3215
|
+
receiptPath: requireOption(options, "receipt"),
|
|
3216
|
+
});
|
|
3217
|
+
}
|
|
3013
3218
|
if (action === "finish") {
|
|
3014
3219
|
const decision = options.decision ?? "accepted";
|
|
3015
3220
|
if (!new Set(["accepted", "rejected", "blocked"]).has(decision)) {
|
|
@@ -3024,36 +3229,92 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
3024
3229
|
finalizeId,
|
|
3025
3230
|
decision,
|
|
3026
3231
|
});
|
|
3027
|
-
if (resumed !== null)
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
if (
|
|
3232
|
+
if (resumed !== null) {
|
|
3233
|
+
const evidenceSummary = decision === "accepted"
|
|
3234
|
+
? reattestFormalEvidenceSummaryV1({
|
|
3235
|
+
workspaceRoot: root,
|
|
3236
|
+
runId,
|
|
3237
|
+
summaryId: `${finalizeId}-evidence`,
|
|
3238
|
+
})
|
|
3239
|
+
: null;
|
|
3240
|
+
if (
|
|
3241
|
+
resumed.formalEvidenceBinding !== null
|
|
3242
|
+
&& (
|
|
3243
|
+
evidenceSummary === null
|
|
3244
|
+
|| evidenceSummary.evidenceSummaryPath
|
|
3245
|
+
!== resumed.formalEvidenceBinding.summaryPath
|
|
3246
|
+
|| evidenceSummary.evidenceSummarySha256
|
|
3247
|
+
!== resumed.formalEvidenceBinding.summarySha256
|
|
3248
|
+
|| evidenceSummary.formalCheckCount
|
|
3249
|
+
!== resumed.formalEvidenceBinding.formalCheckCount
|
|
3250
|
+
|| evidenceSummary.supplementalEvidenceCount
|
|
3251
|
+
!== resumed.formalEvidenceBinding.supplementalEvidenceCount
|
|
3252
|
+
|| evidenceSummary.staleSupplementalEvidenceCount
|
|
3253
|
+
!== resumed.formalEvidenceBinding.staleSupplementalEvidenceCount
|
|
3254
|
+
)
|
|
3255
|
+
) {
|
|
3256
|
+
throw new Error(
|
|
3257
|
+
"Existing closeout does not match its Formal evidence summary.",
|
|
3258
|
+
);
|
|
3259
|
+
}
|
|
3260
|
+
const { formalEvidenceBinding: _formalEvidenceBinding, ...resumedResult } = resumed;
|
|
3261
|
+
return {
|
|
3262
|
+
...resumedResult,
|
|
3263
|
+
supplementalEvidenceCount:
|
|
3264
|
+
evidenceSummary?.supplementalEvidenceCount ?? 0,
|
|
3265
|
+
staleSupplementalEvidenceCount:
|
|
3266
|
+
evidenceSummary?.staleSupplementalEvidenceCount ?? 0,
|
|
3267
|
+
evidenceSummaryPath: evidenceSummary?.evidenceSummaryPath,
|
|
3268
|
+
evidenceSummarySha256: evidenceSummary?.evidenceSummarySha256,
|
|
3269
|
+
};
|
|
3036
3270
|
}
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3271
|
+
return withControlTransaction(root, () => {
|
|
3272
|
+
let finalized = null;
|
|
3273
|
+
let evidenceSummary = null;
|
|
3274
|
+
if (decision === "accepted") {
|
|
3275
|
+
finalized = finalizeFormalChecksWithinControlTransaction({
|
|
3276
|
+
workspaceRoot: root,
|
|
3277
|
+
runId,
|
|
3278
|
+
finalizeId,
|
|
3279
|
+
});
|
|
3280
|
+
if (finalized.status !== "accepted_passed") return finalized;
|
|
3281
|
+
evidenceSummary = summarizeFormalEvidenceWithinControlTransaction({
|
|
3282
|
+
workspaceRoot: root,
|
|
3283
|
+
runId,
|
|
3284
|
+
summaryId: `${finalizeId}-evidence`,
|
|
3285
|
+
});
|
|
3286
|
+
if (evidenceSummary.status !== "formal_evidence_summarized") {
|
|
3287
|
+
return evidenceSummary;
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
const finished = finishExecutionWithinControlTransaction({
|
|
3291
|
+
...options,
|
|
3292
|
+
decision,
|
|
3293
|
+
}, { formalEvidenceSummary: evidenceSummary });
|
|
3294
|
+
if (finished.status !== "finished") return finished;
|
|
3295
|
+
return {
|
|
3296
|
+
status: "formal_finished",
|
|
3297
|
+
exitCode: 0,
|
|
3298
|
+
runId: finished.runId,
|
|
3299
|
+
decision,
|
|
3300
|
+
snapshotCount: finalized?.snapshotCount ?? 0,
|
|
3301
|
+
staleCheckCount: finalized?.staleCheckCount ?? 0,
|
|
3302
|
+
supplementalEvidenceCount:
|
|
3303
|
+
evidenceSummary?.supplementalEvidenceCount ?? 0,
|
|
3304
|
+
staleSupplementalEvidenceCount:
|
|
3305
|
+
evidenceSummary?.staleSupplementalEvidenceCount ?? 0,
|
|
3306
|
+
evidenceSummaryPath: evidenceSummary?.evidenceSummaryPath ?? null,
|
|
3307
|
+
evidenceSummarySha256:
|
|
3308
|
+
evidenceSummary?.evidenceSummarySha256 ?? null,
|
|
3309
|
+
sourceFingerprint: finalized?.sourceFingerprint ?? null,
|
|
3310
|
+
activeReceiptSha256: finished.activeReceiptSha256,
|
|
3311
|
+
closeoutArtifactSha256: finished.closeoutArtifactSha256,
|
|
3312
|
+
releasedLeaseIds: finished.releasedLeaseIds,
|
|
3313
|
+
authorizationGranted: false,
|
|
3314
|
+
};
|
|
3040
3315
|
});
|
|
3041
|
-
if (finished.status !== "finished") return finished;
|
|
3042
|
-
return {
|
|
3043
|
-
status: "formal_finished",
|
|
3044
|
-
exitCode: 0,
|
|
3045
|
-
runId: finished.runId,
|
|
3046
|
-
decision,
|
|
3047
|
-
snapshotCount: finalized?.snapshotCount ?? 0,
|
|
3048
|
-
staleCheckCount: finalized?.staleCheckCount ?? 0,
|
|
3049
|
-
sourceFingerprint: finalized?.sourceFingerprint ?? null,
|
|
3050
|
-
activeReceiptSha256: finished.activeReceiptSha256,
|
|
3051
|
-
closeoutArtifactSha256: finished.closeoutArtifactSha256,
|
|
3052
|
-
releasedLeaseIds: finished.releasedLeaseIds,
|
|
3053
|
-
authorizationGranted: false,
|
|
3054
|
-
};
|
|
3055
3316
|
}
|
|
3056
|
-
throw new Error("Usage: npx --no-install owlrunkit formal <start|check|finish> [options]");
|
|
3317
|
+
throw new Error("Usage: npx --no-install owlrunkit formal <start|preflight|check|attach-evidence|finish> [options]");
|
|
3057
3318
|
}
|
|
3058
3319
|
if (command === "candidate") {
|
|
3059
3320
|
if (action === "freeze") {
|
|
@@ -3123,7 +3384,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
3123
3384
|
}
|
|
3124
3385
|
if (command === "project") {
|
|
3125
3386
|
const allowedProjectOptions = {
|
|
3126
|
-
init: ["workspace", "definition"],
|
|
3387
|
+
init: ["workspace", "definition", "json"],
|
|
3127
3388
|
assign: [
|
|
3128
3389
|
"workspace", "request", "assignment-id", "at", "work-item", "agent",
|
|
3129
3390
|
"supersedes", "execution-run-id", "execution-work-item", "json",
|
|
@@ -3145,6 +3406,11 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
3145
3406
|
"from-agent", "to-agent", "state", "summary", "completed-units",
|
|
3146
3407
|
"evidence", "blocker", "decision", "next", "source-fingerprint", "json",
|
|
3147
3408
|
],
|
|
3409
|
+
"work-item revise-scope": [
|
|
3410
|
+
"workspace", "revision-id", "at", "assignment-id", "work-item",
|
|
3411
|
+
"owner-agent", "owned-path", "measurable-unit", "measurable-total",
|
|
3412
|
+
"unmeasured", "reason", "evidence", "json",
|
|
3413
|
+
],
|
|
3148
3414
|
decision: [
|
|
3149
3415
|
"workspace", "request", "open", "resolve", "decision-id", "at", "title",
|
|
3150
3416
|
"question", "owner-agent", "blocking-work-item", "option", "resolution",
|
|
@@ -3161,7 +3427,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
3161
3427
|
"disposition", "summary", "evidence", "decision", "json",
|
|
3162
3428
|
],
|
|
3163
3429
|
integrate: ["workspace", "request", "gate", "at", "summary", "evidence", "json"],
|
|
3164
|
-
capture: ["workspace", "request"],
|
|
3430
|
+
capture: ["workspace", "request", "json"],
|
|
3165
3431
|
"target-snapshot": [
|
|
3166
3432
|
"workspace", "snapshot-id", "at", "work-item", "target-workspace",
|
|
3167
3433
|
"allowed-path", "dry-run", "apply", "json",
|
|
@@ -3371,6 +3637,56 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
3371
3637
|
? transferred
|
|
3372
3638
|
: withHumanOutput(transferred, formatTeamProjectTransferHuman(transferred));
|
|
3373
3639
|
}
|
|
3640
|
+
if (action === "work-item revise-scope") {
|
|
3641
|
+
const currentStatus = readTeamProjectStatusV3({ workspaceRoot: root });
|
|
3642
|
+
const workItemId = requireOption(options, "work-item");
|
|
3643
|
+
const currentWorkItem = currentStatus.workItems.find(
|
|
3644
|
+
row => row.workItemId === workItemId,
|
|
3645
|
+
);
|
|
3646
|
+
if (!currentWorkItem) throw new Error(`Unknown team project WorkItem: ${workItemId}.`);
|
|
3647
|
+
const hasUnit = options["measurable-unit"] !== undefined;
|
|
3648
|
+
const hasTotal = options["measurable-total"] !== undefined;
|
|
3649
|
+
if (options.unmeasured === true && (hasUnit || hasTotal)) {
|
|
3650
|
+
throw new Error("--unmeasured cannot be combined with measurable-unit or measurable-total.");
|
|
3651
|
+
}
|
|
3652
|
+
if (hasUnit !== hasTotal) {
|
|
3653
|
+
throw new Error("measurable-unit and measurable-total must be supplied together.");
|
|
3654
|
+
}
|
|
3655
|
+
const measurable = options.unmeasured === true
|
|
3656
|
+
? null
|
|
3657
|
+
: hasUnit
|
|
3658
|
+
? {
|
|
3659
|
+
unit: requireOption(options, "measurable-unit"),
|
|
3660
|
+
total: parseCanonicalNonnegativeSafeInteger(
|
|
3661
|
+
requireOption(options, "measurable-total"),
|
|
3662
|
+
"measurable-total",
|
|
3663
|
+
),
|
|
3664
|
+
}
|
|
3665
|
+
: currentWorkItem.measurable;
|
|
3666
|
+
if (measurable?.total === 0) {
|
|
3667
|
+
throw new Error("measurable-total must be a positive safe integer.");
|
|
3668
|
+
}
|
|
3669
|
+
const revised = reviseTeamProjectWorkItemScopeV1({
|
|
3670
|
+
workspaceRoot: root,
|
|
3671
|
+
revisionId: requireOption(options, "revision-id"),
|
|
3672
|
+
occurredAt: requireOption(options, "at"),
|
|
3673
|
+
assignmentId: requireOption(options, "assignment-id"),
|
|
3674
|
+
workItemId,
|
|
3675
|
+
ownerAgentId: requireOption(options, "owner-agent"),
|
|
3676
|
+
ownedPaths: options["owned-path"] ?? currentWorkItem.ownedPaths,
|
|
3677
|
+
measurable,
|
|
3678
|
+
reason: requireOption(options, "reason"),
|
|
3679
|
+
evidenceRefs: options.evidence ?? [],
|
|
3680
|
+
});
|
|
3681
|
+
return options.json === true
|
|
3682
|
+
? revised
|
|
3683
|
+
: withHumanOutput(revised, [
|
|
3684
|
+
`Revised WorkItem ${revised.workItemId} scope as ${revised.revisionId}.`,
|
|
3685
|
+
`Owned paths: ${revised.ownedPaths.join(", ")}.`,
|
|
3686
|
+
"Project definition remains immutable; no Git or release authority was granted.",
|
|
3687
|
+
"",
|
|
3688
|
+
].join("\n"));
|
|
3689
|
+
}
|
|
3374
3690
|
if (action === "decision") {
|
|
3375
3691
|
const directDecisionFields = [
|
|
3376
3692
|
"open",
|
|
@@ -3667,13 +3983,13 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
3667
3983
|
});
|
|
3668
3984
|
}
|
|
3669
3985
|
if (action === "status") {
|
|
3670
|
-
const status =
|
|
3986
|
+
const status = readTeamProjectStatusV3({ workspaceRoot: root });
|
|
3671
3987
|
return options.json === true
|
|
3672
3988
|
? status
|
|
3673
3989
|
: withHumanOutput(status, formatTeamProjectStatusHumanV2(status));
|
|
3674
3990
|
}
|
|
3675
3991
|
if (action === "takeover") {
|
|
3676
|
-
const takeover =
|
|
3992
|
+
const takeover = buildTeamProjectTakeoverV3({
|
|
3677
3993
|
workspaceRoot: root,
|
|
3678
3994
|
agentId: requireOption(options, "agent"),
|
|
3679
3995
|
});
|
|
@@ -3694,7 +4010,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
3694
4010
|
? successor
|
|
3695
4011
|
: withHumanOutput(successor, formatTeamProjectSuccessorHumanV1(successor));
|
|
3696
4012
|
}
|
|
3697
|
-
throw new Error("Usage: npx --no-install owlrunkit project <init|assign|checkpoint|handoff|reject-and-return|reopen-upstream|transfer|decision|verification|integrate|capture|target-snapshot|import-delivery|status|takeover|successor> [options]");
|
|
4013
|
+
throw new Error("Usage: npx --no-install owlrunkit project <init|assign|checkpoint|handoff|reject-and-return|reopen-upstream|transfer|work-item revise-scope|decision|verification|integrate|capture|target-snapshot|import-delivery|status|takeover|successor> [options]");
|
|
3698
4014
|
}
|
|
3699
4015
|
if (command === "profiles") {
|
|
3700
4016
|
const root = requireOption(options, "workspace");
|