owlrunkit 0.15.0 → 0.16.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/README.md +274 -66
  3. package/integrations/codex/skills/owlcoda-runkit/SKILL.md +223 -117
  4. package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
  5. package/integrations/codex/skills/owlcoda-runkit/assets/templates/ready-for-commit-request.json +2 -2
  6. package/package.json +2 -2
  7. package/packages/attest/distribution-manifest-v1.json +10 -0
  8. package/packages/attest/src/quick.mjs +10 -0
  9. package/registry-release-policy-v1.json +8 -2
  10. package/sbom.spdx.json +5 -5
  11. package/scripts/runkit-contract/assurance-router.mjs +119 -0
  12. package/scripts/runkit-contract/core-contract.mjs +250 -115
  13. package/scripts/runkit-contract/core-successor.mjs +2043 -0
  14. package/scripts/runkit-contract/deployment-workflow.mjs +2040 -0
  15. package/scripts/runkit-contract/finalize.mjs +242 -21
  16. package/scripts/runkit-contract/fleet-discovery.mjs +456 -0
  17. package/scripts/runkit-contract/formal-workflow.mjs +850 -0
  18. package/scripts/runkit-contract/human-status.mjs +553 -0
  19. package/scripts/runkit-contract/inspect-presentation.mjs +25 -8
  20. package/scripts/runkit-contract/install-codex-skill.mjs +73 -30
  21. package/scripts/runkit-contract/lease-lifecycle.mjs +8 -2
  22. package/scripts/runkit-contract/lifecycle-orchestration.mjs +135 -12
  23. package/scripts/runkit-contract/onboarding-doctor.mjs +43 -90
  24. package/scripts/runkit-contract/owner-authority-trust.mjs +230 -0
  25. package/scripts/runkit-contract/owner-deployment-decision.mjs +385 -0
  26. package/scripts/runkit-contract/profile-onboarding.mjs +841 -13
  27. package/scripts/runkit-contract/project-cli-resolver.mjs +701 -0
  28. package/scripts/runkit-contract/project-control-parser.mjs +830 -0
  29. package/scripts/runkit-contract/project-control-state.mjs +28 -0
  30. package/scripts/runkit-contract/provenance-common.mjs +19 -2
  31. package/scripts/runkit-contract/ready-for-commit.mjs +330 -18
  32. package/scripts/runkit-contract/remote-deployment.mjs +1596 -0
  33. package/scripts/runkit-contract/remote-process-adapter.mjs +177 -0
  34. package/scripts/runkit-contract/runkit-bootstrap.mjs +131 -0
  35. package/scripts/runkit-contract/runkit-cli.mjs +1097 -21
  36. package/scripts/runkit-contract/schemas/assurance-route-v1.schema.json +26 -0
  37. package/scripts/runkit-contract/schemas/core-successor-batch-receipt-v1.schema.json +126 -0
  38. package/scripts/runkit-contract/schemas/core-successor-plan-v1.schema.json +155 -0
  39. package/scripts/runkit-contract/schemas/core-successor-project-success-receipt-v1.schema.json +72 -0
  40. package/scripts/runkit-contract/schemas/deployment-execute-request-v1.schema.json +63 -0
  41. package/scripts/runkit-contract/schemas/deployment-lineage-v1.schema.json +292 -0
  42. package/scripts/runkit-contract/schemas/deployment-prepare-receipt-v1.schema.json +140 -0
  43. package/scripts/runkit-contract/schemas/fleet-discovery-v1.schema.json +31 -0
  44. package/scripts/runkit-contract/schemas/fleet-manifest-v1.schema.json +20 -0
  45. package/scripts/runkit-contract/schemas/fleet-root-registry-v1.schema.json +34 -0
  46. package/scripts/runkit-contract/schemas/human-status-v1.schema.json +102 -0
  47. package/scripts/runkit-contract/schemas/owner-authority-trust-v1.schema.json +66 -0
  48. package/scripts/runkit-contract/schemas/owner-deployment-authority-v1.schema.json +46 -0
  49. package/scripts/runkit-contract/schemas/owner-deployment-authority-v2.schema.json +94 -0
  50. package/scripts/runkit-contract/schemas/owner-deployment-decision-v1.schema.json +102 -0
  51. package/scripts/runkit-contract/schemas/owner-migration-authority-v1.schema.json +33 -0
  52. package/scripts/runkit-contract/schemas/owner-migration-authority-v2.schema.json +67 -0
  53. package/scripts/runkit-contract/schemas/profile-apply-receipt-v1.schema.json +32 -0
  54. package/scripts/runkit-contract/schemas/profile-detection-v2.schema.json +145 -0
  55. package/scripts/runkit-contract/schemas/ready-for-commit-v2.schema.json +37 -0
  56. package/scripts/runkit-contract/schemas/remote-deployment-manifest-v1.schema.json +379 -0
  57. package/scripts/runkit-contract/schemas/remote-deployment-result-v1.schema.json +153 -0
  58. package/scripts/runkit-contract/schemas/remote-deployment-stage-journal-v1.schema.json +183 -0
  59. package/scripts/runkit-contract/schemas/remote-target-v1.schema.json +32 -0
  60. package/scripts/runkit-contract/schemas/source-candidate-v2.schema.json +152 -0
  61. package/scripts/runkit-contract/schemas/verification-receipt-v2.schema.json +13 -0
  62. package/scripts/runkit-contract/snapshot.mjs +1 -1
  63. package/scripts/runkit-contract/source-candidate.mjs +1382 -0
  64. package/scripts/runkit-contract/ssh-remote-adapter.mjs +1184 -0
  65. package/scripts/runkit-contract/sync-core016-release-identity.mjs +161 -0
  66. package/scripts/runkit-contract/templates/assurance-request.json +13 -0
  67. package/scripts/runkit-contract/templates/core-successor-owner-authority.json +15 -0
  68. package/scripts/runkit-contract/templates/deployment-execute-request.json +39 -0
  69. package/scripts/runkit-contract/templates/deployment-owner-authority.json +23 -0
  70. package/scripts/runkit-contract/templates/deployment-owner-decision.json +26 -0
  71. package/scripts/runkit-contract/templates/fleet-manifest.json +8 -0
  72. package/scripts/runkit-contract/templates/fleet-root-registry.json +8 -0
  73. package/scripts/runkit-contract/templates/owner-authority-trust.json +16 -0
  74. package/scripts/runkit-contract/templates/ready-for-commit-request.json +2 -2
  75. package/scripts/runkit-contract/templates/remote-deployment-manifest.json +108 -0
  76. package/scripts/runkit-contract/verification-receipt-gate.mjs +28 -0
@@ -0,0 +1,553 @@
1
+ function isRecord(value) {
2
+ return value && typeof value === "object" && !Array.isArray(value);
3
+ }
4
+
5
+ function completeInspectTruth(inspected) {
6
+ return isRecord(inspected)
7
+ && inspected.status === "inspected"
8
+ && Number.isInteger(inspected.exitCode)
9
+ && typeof inspected.runtimeRoot === "string"
10
+ && isRecord(inspected.configCore)
11
+ && typeof inspected.configCore.status === "string"
12
+ && Array.isArray(inspected.configCore.issues)
13
+ && Array.isArray(inspected.controlIssues)
14
+ && Array.isArray(inspected.runIds)
15
+ && Array.isArray(inspected.executions)
16
+ && isRecord(inspected.recovery)
17
+ && typeof inspected.recovery.state === "string"
18
+ && Array.isArray(inspected.recovery.activeRunIds)
19
+ && (
20
+ inspected.recovery.selectedRunId === null
21
+ || typeof inspected.recovery.selectedRunId === "string"
22
+ )
23
+ && typeof inspected.recovery.nextAllowedAction === "string";
24
+ }
25
+
26
+ function issueCode(value) {
27
+ return String(value)
28
+ .trim()
29
+ .replace(/\s+/g, "_")
30
+ .replace(/[^A-Za-z0-9._-]+/g, "_")
31
+ .replace(/^_+|_+$/g, "");
32
+ }
33
+
34
+ function milestone(status, evidence, label) {
35
+ return { status, evidence, label };
36
+ }
37
+
38
+ function compareCodeUnits(left, right) {
39
+ return left < right ? -1 : left > right ? 1 : 0;
40
+ }
41
+
42
+ function closedDecision(execution) {
43
+ if (
44
+ execution.closeout?.decision === "accepted"
45
+ && execution.recovery?.evidenceTrustLevel !== "closed_nonaccepted"
46
+ ) {
47
+ return "accepted";
48
+ }
49
+ if (execution.closeout?.decision === "blocked") return "blocked";
50
+ if (execution.closeout?.decision === "rejected") return "rejected";
51
+ return "nonaccepted";
52
+ }
53
+
54
+ function sameStringSet(left, right) {
55
+ const sortedLeft = [...left].sort(compareCodeUnits);
56
+ const sortedRight = [...right].sort(compareCodeUnits);
57
+ return sortedLeft.length === sortedRight.length
58
+ && sortedLeft.every((value, index) => value === sortedRight[index]);
59
+ }
60
+
61
+ export function selectClosedHistoryFocusV1(inspected) {
62
+ const closed = Array.isArray(inspected?.executions)
63
+ ? inspected.executions.filter(execution => execution.lifecycle === "closed")
64
+ : [];
65
+ if (closed.length === 0) {
66
+ return {
67
+ status: "empty",
68
+ selectedExecution: null,
69
+ decision: null,
70
+ };
71
+ }
72
+ if (closed.length === 1) {
73
+ return {
74
+ status: "single",
75
+ selectedExecution: closed[0],
76
+ decision: closedDecision(closed[0]),
77
+ };
78
+ }
79
+
80
+ const history = inspected.controlState?.closedHistory;
81
+ const closedRunIds = closed.map(execution => execution.runId);
82
+ const historyBound = isRecord(history)
83
+ && Array.isArray(history.runIds)
84
+ && history.runIds.every(runId => typeof runId === "string")
85
+ && sameStringSet(history.runIds, closedRunIds);
86
+ if (
87
+ historyBound
88
+ && history.status === "unique_head"
89
+ && history.lineageVerified === true
90
+ && typeof history.headRunId === "string"
91
+ ) {
92
+ const head = closed.find(execution => execution.runId === history.headRunId);
93
+ if (head && history.decision === head.closeout?.decision) {
94
+ return {
95
+ status: "unique_head",
96
+ selectedExecution: head,
97
+ decision: closedDecision(head),
98
+ };
99
+ }
100
+ }
101
+
102
+ const decisions = new Set(closed.map(closedDecision));
103
+ if (decisions.size === 1) {
104
+ return {
105
+ status: "consistent_unordered",
106
+ selectedExecution: null,
107
+ decision: decisions.values().next().value,
108
+ };
109
+ }
110
+ return {
111
+ status: "ambiguous_history",
112
+ selectedExecution: null,
113
+ decision: null,
114
+ };
115
+ }
116
+
117
+ function milestoneExecution(inspected) {
118
+ if (!completeInspectTruth(inspected)) return null;
119
+ if (inspected.recovery.selectedRunId !== null) {
120
+ return inspected.executions.find(execution =>
121
+ execution.runId === inspected.recovery.selectedRunId) ?? null;
122
+ }
123
+ if (inspected.recovery.state !== "no_active_execution") return null;
124
+ return selectClosedHistoryFocusV1(inspected).selectedExecution;
125
+ }
126
+
127
+ function operationalMilestones(inspected) {
128
+ const execution = milestoneExecution(inspected);
129
+ const delivery = execution?.recovery?.delivery ?? null;
130
+ const verification = execution?.recovery?.verification ?? null;
131
+ let sourceData = milestone(
132
+ "not_evidenced",
133
+ "none",
134
+ "Source/data readiness is not evidenced by inspect.",
135
+ );
136
+ if (delivery?.status === "fresh") {
137
+ sourceData = milestone(
138
+ "ready",
139
+ "fresh_delivery_packet",
140
+ "Source/data is ready from a fresh delivery packet.",
141
+ );
142
+ } else if (
143
+ delivery?.status === "historical"
144
+ && verification?.status === "passed"
145
+ ) {
146
+ sourceData = milestone(
147
+ "ready",
148
+ "verified_historical_source",
149
+ "Source/data is ready from verified historical evidence.",
150
+ );
151
+ } else if (delivery?.status === "stale" || delivery?.status === "invalid") {
152
+ sourceData = milestone(
153
+ "not_ready",
154
+ `${delivery.status}_delivery_packet`,
155
+ `Source/data is not ready because delivery evidence is ${delivery.status}.`,
156
+ );
157
+ }
158
+ return {
159
+ sourceData,
160
+ releasePackage: milestone(
161
+ "not_evidenced",
162
+ "none",
163
+ "Release package readiness is not evidenced by inspect.",
164
+ ),
165
+ remoteVmWrite: milestone(
166
+ "not_evidenced",
167
+ "none",
168
+ "Remote/VM write is not evidenced by inspect.",
169
+ ),
170
+ };
171
+ }
172
+
173
+ function withMilestones(projection, inspected) {
174
+ return {
175
+ ...projection,
176
+ milestones: operationalMilestones(inspected),
177
+ };
178
+ }
179
+
180
+ function blockedProjection({
181
+ headline,
182
+ controlStatus,
183
+ issueCodes,
184
+ nextAllowedAction,
185
+ gateCode,
186
+ gateLabel,
187
+ currentExecutionId = null,
188
+ stage = "setup",
189
+ }) {
190
+ return {
191
+ schemaVersion: "OwlCodaRunKitHumanStatusV1",
192
+ status: "projected",
193
+ overall: "blocked",
194
+ headline,
195
+ stage,
196
+ currentExecutionId,
197
+ completedSteps: [],
198
+ remainingGates: [{
199
+ code: gateCode,
200
+ label: gateLabel,
201
+ nextAllowedAction,
202
+ }],
203
+ remainingGateCount: 1,
204
+ control: {
205
+ status: controlStatus,
206
+ issueCodes,
207
+ },
208
+ nextAllowedAction,
209
+ authorizationGranted: false,
210
+ gitAuthorization: false,
211
+ releaseAuthorization: false,
212
+ deployAuthorization: false,
213
+ };
214
+ }
215
+
216
+ function consistentUnorderedProjection(decision) {
217
+ if (decision !== "accepted") {
218
+ const details = decision === "rejected"
219
+ ? {
220
+ headline: "All indexed closeouts are rejected, but their chronology is not proven.",
221
+ action: "review_rejected_closeout",
222
+ gateCode: "rejected_closeout",
223
+ gateLabel: "Review the rejected closeout history before planning a successor.",
224
+ }
225
+ : decision === "blocked"
226
+ ? {
227
+ headline: "All indexed closeouts are blocked, but their chronology is not proven.",
228
+ action: "resolve_blocked_closeout",
229
+ gateCode: "blocked_closeout",
230
+ gateLabel: "Resolve the blocked closeout history before planning a successor.",
231
+ }
232
+ : {
233
+ headline: "All indexed closeouts are nonaccepted, but their chronology is not proven.",
234
+ action: "review_nonaccepted_closeout",
235
+ gateCode: "closed_nonaccepted",
236
+ gateLabel: "Review the nonaccepted closeout history before continuing.",
237
+ };
238
+ return {
239
+ ...blockedProjection({
240
+ headline: details.headline,
241
+ controlStatus: "healthy",
242
+ issueCodes: [],
243
+ nextAllowedAction: details.action,
244
+ gateCode: details.gateCode,
245
+ gateLabel: details.gateLabel,
246
+ stage: "closeout",
247
+ }),
248
+ completedSteps: ["execution_history_closed_consistent"],
249
+ };
250
+ }
251
+ return {
252
+ schemaVersion: "OwlCodaRunKitHumanStatusV1",
253
+ status: "projected",
254
+ overall: "closed",
255
+ headline: "Closed execution history is consistent but has no proven chronology.",
256
+ stage: "closeout",
257
+ currentExecutionId: null,
258
+ completedSteps: ["execution_history_closed_consistent"],
259
+ remainingGates: [],
260
+ remainingGateCount: 0,
261
+ control: { status: "healthy", issueCodes: [] },
262
+ nextAllowedAction: "plan_new_execution",
263
+ authorizationGranted: false,
264
+ gitAuthorization: false,
265
+ releaseAuthorization: false,
266
+ deployAuthorization: false,
267
+ };
268
+ }
269
+
270
+ function stageForAction(action) {
271
+ if (["acquire_writer_lease", "plan_new_execution", "run_onboarding_diagnostics"].includes(action)) {
272
+ return "setup";
273
+ }
274
+ if (action === "continue_feature_work") return "implementation";
275
+ if (["prepare_delivery_packet", "replace_delivery_packet"].includes(action)) return "delivery";
276
+ if (
277
+ action === "run_stage_verification"
278
+ || action === "run_resource_preflight"
279
+ || action === "begin_model_execution"
280
+ || action === "continue_without_model_calls"
281
+ || action === "pause_at_deterministic_stage"
282
+ ) {
283
+ return "verification";
284
+ }
285
+ if (["release_writer_lease", "close_execution"].includes(action)) return "closeout";
286
+ return "external_action";
287
+ }
288
+
289
+ function completedSteps(selected) {
290
+ if (!selected) return [];
291
+ const recovery = selected.recovery ?? {};
292
+ const steps = [];
293
+ if (recovery.lease?.status === "active") steps.push("writer_lease_active");
294
+ if (recovery.delivery?.status === "fresh") steps.push("delivery_packet_ready");
295
+ if (recovery.verification?.status === "passed") steps.push("verification_passed");
296
+ if (recovery.resourcePreflight?.status === "ready") steps.push("resource_preflight_passed");
297
+ return steps;
298
+ }
299
+
300
+ function headlineFor(overall, action, selectedRunId) {
301
+ if (overall === "closed") return "Execution is closed.";
302
+ if (overall === "idle") return "No RunKit execution is active.";
303
+ if (overall === "ready_for_closeout") return `Execution ${selectedRunId} is ready to close out.`;
304
+ if (overall === "blocked") return `Execution ${selectedRunId ?? "control"} is blocked at ${action}.`;
305
+ return `Execution ${selectedRunId} is working at ${action}.`;
306
+ }
307
+
308
+ function nonacceptedCloseoutProjection(execution) {
309
+ const decision = execution.closeout?.decision;
310
+ const superseded = execution.closeout?.statusCode === "closed_superseded"
311
+ && execution.closeout?.businessGoalIncomplete === true
312
+ && execution.closeout?.replacementPlanRequired === true;
313
+ const details = superseded
314
+ ? {
315
+ headline: `Execution ${execution.runId} was superseded; the business goal is not complete.`,
316
+ action: "plan_replacement_execution",
317
+ gateCode: "replacement_execution_required",
318
+ gateLabel: "Plan a replacement execution for the current Owner decision.",
319
+ }
320
+ : decision === "rejected"
321
+ ? {
322
+ headline: `Execution ${execution.runId} closed as rejected.`,
323
+ action: "review_rejected_closeout",
324
+ gateCode: "rejected_closeout",
325
+ gateLabel: "Review the rejected closeout before planning a successor.",
326
+ }
327
+ : decision === "blocked"
328
+ ? {
329
+ headline: `Execution ${execution.runId} closed as blocked.`,
330
+ action: "resolve_blocked_closeout",
331
+ gateCode: "blocked_closeout",
332
+ gateLabel: "Resolve the blocked closeout before planning a successor.",
333
+ }
334
+ : {
335
+ headline: `Execution ${execution.runId} closed without acceptance.`,
336
+ action: "review_nonaccepted_closeout",
337
+ gateCode: "closed_nonaccepted",
338
+ gateLabel: "Review the nonaccepted closeout before continuing.",
339
+ };
340
+ return {
341
+ schemaVersion: "OwlCodaRunKitHumanStatusV1",
342
+ status: "projected",
343
+ overall: "blocked",
344
+ headline: details.headline,
345
+ stage: "closeout",
346
+ currentExecutionId: execution.runId,
347
+ completedSteps: [superseded
348
+ ? "execution_closed_superseded"
349
+ : "execution_closed_nonaccepted"],
350
+ remainingGates: [{
351
+ code: details.gateCode,
352
+ label: details.gateLabel,
353
+ nextAllowedAction: details.action,
354
+ }],
355
+ remainingGateCount: 1,
356
+ control: {
357
+ status: "healthy",
358
+ issueCodes: [],
359
+ },
360
+ nextAllowedAction: details.action,
361
+ ...(superseded
362
+ ? {
363
+ businessGoalIncomplete: true,
364
+ replacementPlanRequired: true,
365
+ }
366
+ : {}),
367
+ authorizationGranted: false,
368
+ gitAuthorization: false,
369
+ releaseAuthorization: false,
370
+ deployAuthorization: false,
371
+ };
372
+ }
373
+
374
+ export function deriveHumanStatusFromInspectV1(inspected) {
375
+ if (!completeInspectTruth(inspected)) {
376
+ return withMilestones(blockedProjection({
377
+ headline: "Inspect truth is incomplete; progress was not inferred.",
378
+ controlStatus: "invalid",
379
+ issueCodes: ["inspect_truth_incomplete"],
380
+ nextAllowedAction: "rerun_inspect",
381
+ gateCode: "restore_complete_inspect_truth",
382
+ gateLabel: "Rerun a complete inspect before continuing.",
383
+ }), inspected);
384
+ }
385
+
386
+ if (
387
+ inspected.controlIssues.length > 0
388
+ || inspected.configCore.status === "invalid_config"
389
+ ) {
390
+ return withMilestones(blockedProjection({
391
+ headline: "RunKit control artifacts require repair.",
392
+ controlStatus: "invalid",
393
+ issueCodes: [
394
+ inspected.configCore.status,
395
+ ...inspected.configCore.issues.map(issueCode),
396
+ ...inspected.controlIssues.map(issueCode),
397
+ ],
398
+ nextAllowedAction: "repair_execution_artifacts",
399
+ gateCode: "repair_control_artifacts",
400
+ gateLabel: "Repair the invalid RunKit control artifacts.",
401
+ }), inspected);
402
+ }
403
+
404
+ if (inspected.configCore.status !== "valid") {
405
+ const drifted = inspected.configCore.status === "engine_changed_during_execution";
406
+ const activeExecution = inspected.recovery.activeRunIds.length > 0;
407
+ return withMilestones(blockedProjection({
408
+ headline: drifted && activeExecution
409
+ ? "An active execution must be resolved before the Core binding can migrate."
410
+ : drifted
411
+ ? "Project control is bound to a different Core identity."
412
+ : "Project Core binding is invalid.",
413
+ controlStatus: drifted ? "drifted" : "invalid",
414
+ issueCodes: [
415
+ inspected.configCore.status,
416
+ ...inspected.configCore.issues.map(issueCode),
417
+ ],
418
+ nextAllowedAction: drifted && activeExecution
419
+ ? inspected.recovery.nextAllowedAction
420
+ : drifted
421
+ ? "run_official_init_migration"
422
+ : "repair_execution_artifacts",
423
+ gateCode: drifted && activeExecution
424
+ ? "resolve_active_execution_before_core_migration"
425
+ : drifted
426
+ ? "restore_current_core_binding"
427
+ : "repair_control_artifacts",
428
+ gateLabel: drifted && activeExecution
429
+ ? "Resolve and close the active execution before Core migration."
430
+ : drifted
431
+ ? "Migrate project control to the current Core identity."
432
+ : "Repair the invalid RunKit control artifacts.",
433
+ currentExecutionId: inspected.recovery.selectedRunId,
434
+ }), inspected);
435
+ }
436
+
437
+ if (inspected.recovery.state === "no_active_execution") {
438
+ const history = selectClosedHistoryFocusV1(inspected);
439
+ if (history.status === "ambiguous_history") {
440
+ return withMilestones(blockedProjection({
441
+ headline: "Closed execution history has conflicting outcomes without proven chronology.",
442
+ controlStatus: "healthy",
443
+ issueCodes: ["ambiguous_history"],
444
+ nextAllowedAction: "inspect_closed_history",
445
+ gateCode: "ambiguous_history",
446
+ gateLabel: "Establish a verified predecessor lineage or inspect the conflicting closeouts.",
447
+ stage: "closeout",
448
+ }), inspected);
449
+ }
450
+ if (history.status === "consistent_unordered") {
451
+ return withMilestones(
452
+ consistentUnorderedProjection(history.decision),
453
+ inspected,
454
+ );
455
+ }
456
+ const latestClosed = history.selectedExecution;
457
+ if (
458
+ latestClosed
459
+ && (
460
+ latestClosed.closeout?.decision !== "accepted"
461
+ || latestClosed.recovery?.evidenceTrustLevel === "closed_nonaccepted"
462
+ )
463
+ ) {
464
+ return withMilestones(
465
+ nonacceptedCloseoutProjection(latestClosed),
466
+ inspected,
467
+ );
468
+ }
469
+ const overall = history.status === "empty" ? "idle" : "closed";
470
+ return withMilestones({
471
+ schemaVersion: "OwlCodaRunKitHumanStatusV1",
472
+ status: "projected",
473
+ overall,
474
+ headline: headlineFor(overall, inspected.recovery.nextAllowedAction, null),
475
+ stage: overall === "closed" ? "closeout" : "setup",
476
+ currentExecutionId: null,
477
+ completedSteps: overall === "closed" ? ["execution_closed"] : [],
478
+ remainingGates: [],
479
+ remainingGateCount: 0,
480
+ control: { status: "healthy", issueCodes: [] },
481
+ nextAllowedAction: inspected.recovery.nextAllowedAction,
482
+ authorizationGranted: false,
483
+ gitAuthorization: false,
484
+ releaseAuthorization: false,
485
+ deployAuthorization: false,
486
+ }, inspected);
487
+ }
488
+
489
+ if (inspected.recovery.state === "multiple_active_executions") {
490
+ return withMilestones(blockedProjection({
491
+ headline: "Multiple active executions require an explicit selection.",
492
+ controlStatus: "healthy",
493
+ issueCodes: ["multiple_active_executions"],
494
+ nextAllowedAction: "select_active_execution",
495
+ gateCode: "select_active_execution",
496
+ gateLabel: "Select the execution to continue.",
497
+ }), inspected);
498
+ }
499
+
500
+ const selected = inspected.executions.find(execution =>
501
+ execution.runId === inspected.recovery.selectedRunId);
502
+ if (
503
+ inspected.recovery.state !== "single_active_execution"
504
+ || !selected
505
+ || selected.lifecycle === "closed"
506
+ ) {
507
+ return withMilestones(blockedProjection({
508
+ headline: "Inspect execution selection is inconsistent.",
509
+ controlStatus: "invalid",
510
+ issueCodes: ["inspect_truth_inconsistent"],
511
+ nextAllowedAction: "rerun_inspect",
512
+ gateCode: "restore_consistent_inspect_truth",
513
+ gateLabel: "Rerun inspect and repair inconsistent execution truth.",
514
+ }), inspected);
515
+ }
516
+
517
+ const action = inspected.recovery.nextAllowedAction;
518
+ const blocked = action === "repair_execution_artifacts"
519
+ || action === "replace_delivery_packet";
520
+ const readyForCloseout = action === "release_writer_lease"
521
+ || action === "close_execution";
522
+ const overall = blocked
523
+ ? "blocked"
524
+ : readyForCloseout
525
+ ? "ready_for_closeout"
526
+ : "working";
527
+ const gates = [{
528
+ code: action,
529
+ label: action.replaceAll("_", " "),
530
+ nextAllowedAction: action,
531
+ }];
532
+ const selectedIssues = (selected.recovery?.issues ?? []).map(issueCode);
533
+ return withMilestones({
534
+ schemaVersion: "OwlCodaRunKitHumanStatusV1",
535
+ status: "projected",
536
+ overall,
537
+ headline: headlineFor(overall, action, selected.runId),
538
+ stage: stageForAction(action),
539
+ currentExecutionId: selected.runId,
540
+ completedSteps: completedSteps(selected),
541
+ remainingGates: gates,
542
+ remainingGateCount: gates.length,
543
+ control: {
544
+ status: selectedIssues.length > 0 ? "invalid" : "healthy",
545
+ issueCodes: selectedIssues,
546
+ },
547
+ nextAllowedAction: action,
548
+ authorizationGranted: false,
549
+ gitAuthorization: false,
550
+ releaseAuthorization: false,
551
+ deployAuthorization: false,
552
+ }, inspected);
553
+ }
@@ -1,5 +1,10 @@
1
- function latestIndexedCloseout(executions) {
2
- return [...executions].reverse().find(execution => execution.lifecycle === "closed") ?? null;
1
+ import {
2
+ deriveHumanStatusFromInspectV1,
3
+ selectClosedHistoryFocusV1,
4
+ } from "./human-status.mjs";
5
+
6
+ function chronologySelectedCloseout(inspected) {
7
+ return selectClosedHistoryFocusV1(inspected).selectedExecution;
3
8
  }
4
9
 
5
10
  function compareCodeUnits(left, right) {
@@ -18,13 +23,14 @@ function selectedFocus(inspected) {
18
23
  return inspected.executions.find(execution => execution.runId === selectedRunId) ?? null;
19
24
  }
20
25
  return inspected.recovery.state === "no_active_execution"
21
- ? latestIndexedCloseout(inspected.executions)
26
+ ? chronologySelectedCloseout(inspected)
22
27
  : null;
23
28
  }
24
29
 
25
30
  export function buildInspectSummary(inspected) {
31
+ const humanStatus = deriveHumanStatusFromInspectV1(inspected);
26
32
  const focus = selectedFocus(inspected);
27
- const latestClosed = latestIndexedCloseout(inspected.executions);
33
+ const latestClosed = chronologySelectedCloseout(inspected);
28
34
  const holders = inspected.executions
29
35
  .flatMap(execution => (execution.recovery?.lease?.activeWorkItemIds ?? []).map(workItemId => ({
30
36
  runId: execution.runId,
@@ -42,6 +48,7 @@ export function buildInspectSummary(inspected) {
42
48
  ...(inspected.recovery.state === "multiple_active_executions"
43
49
  ? ["Multiple active executions require explicit selection."]
44
50
  : (focus?.recovery?.issues ?? [])),
51
+ ...(inspected.configCore?.issues ?? []),
45
52
  ...(inspected.controlIssues ?? []),
46
53
  ...(selectedResource?.blockers ?? []),
47
54
  ].filter((reason, index, all) => all.indexOf(reason) === index);
@@ -96,10 +103,10 @@ export function buildInspectSummary(inspected) {
96
103
  resources: [...(selectedResource?.resources ?? [])],
97
104
  },
98
105
  dominantGap: {
99
- code: inspected.recovery.nextAllowedAction,
106
+ code: humanStatus.nextAllowedAction,
100
107
  reasons: [...reasons],
101
108
  },
102
- nextAllowedAction: inspected.recovery.nextAllowedAction,
109
+ nextAllowedAction: humanStatus.nextAllowedAction,
103
110
  authorizationGranted: false,
104
111
  gitAuthorization: false,
105
112
  releaseAuthorization: false,
@@ -111,7 +118,7 @@ function value(value) {
111
118
  return String(value);
112
119
  }
113
120
 
114
- function summaryLines(summary) {
121
+ function summaryLines(summary, humanStatus) {
115
122
  const latest = summary.latestIndexedCloseout
116
123
  ? `${summary.latestIndexedCloseout.runId} ${summary.latestIndexedCloseout.decision}`
117
124
  : "none";
@@ -123,12 +130,21 @@ function summaryLines(summary) {
123
130
  ? ` (+${summary.leases.holders.length - visibleHolders.length} more)`
124
131
  : ""}`;
125
132
  return [
133
+ `Status: ${humanStatus.overall}`,
134
+ `Summary: ${humanStatus.headline}`,
126
135
  `Current execution: ${value(summary.currentExecution.selectedRunId)}`,
127
136
  `Latest indexed closeout: ${latest}`,
128
137
  `Source status: ${summary.source.status}`,
138
+ `Source/data readiness: ${humanStatus.milestones.sourceData.status}`,
139
+ `Release package: ${humanStatus.milestones.releasePackage.status}`,
140
+ `Remote/VM write: ${humanStatus.milestones.remoteVmWrite.status}`,
129
141
  `Active leases: ${summary.leases.activeCount}`,
130
142
  `Lease holders: ${holders}`,
131
143
  `Open executions: ${summary.currentExecution.openCount}`,
144
+ `Completed: ${humanStatus.completedSteps.length > 0
145
+ ? humanStatus.completedSteps.join(", ")
146
+ : "none"}`,
147
+ `Remaining gates: ${humanStatus.remainingGateCount}`,
132
148
  `Evidence: ${summary.evidence.status}`,
133
149
  `Resource preflight: ${summary.resourcePreflight.status}`,
134
150
  `Model estimate: ${summary.resourcePreflight.estimate.calls} calls, ${summary.resourcePreflight.estimate.totalTokens} tokens`,
@@ -179,5 +195,6 @@ function formatExecution(execution) {
179
195
  export function formatInspectHuman(inspected) {
180
196
  if (inspected.view?.mode === "history") return `${formatHistory(inspected)}\n`;
181
197
  if (inspected.view?.mode === "execution") return `${formatExecution(inspected.view.execution)}\n`;
182
- return `${summaryLines(inspected.summary).join("\n")}\n`;
198
+ const humanStatus = deriveHumanStatusFromInspectV1(inspected);
199
+ return `${summaryLines(inspected.summary, humanStatus).join("\n")}\n`;
183
200
  }