@quantiya/codevibe-core 2.0.7 → 2.0.9

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 (128) hide show
  1. package/dist/appsync/__tests__/dispose-watcher-socket.test.d.ts +1 -0
  2. package/dist/appsync/__tests__/refresh-open-prompt-ttl-chunk.test.d.ts +1 -0
  3. package/dist/appsync/appsync-client.d.ts +232 -30
  4. package/dist/appsync/queries.d.ts +2 -0
  5. package/dist/auth/__tests__/keychain-cli-nudge.test.d.ts +1 -0
  6. package/dist/auth/__tests__/keychain-cli.test.d.ts +1 -0
  7. package/dist/auth/keychain-cli.d.ts +14 -0
  8. package/dist/companion-mode/index.d.ts +14 -0
  9. package/dist/credential-broker/oauth-account-lock.d.ts +47 -1
  10. package/dist/crypto/__tests__/open-prompt-id.test.d.ts +1 -0
  11. package/dist/crypto/index.d.ts +1 -0
  12. package/dist/crypto/open-prompt-id.d.ts +36 -0
  13. package/dist/e1/__tests__/prompt-raise.test.d.ts +1 -0
  14. package/dist/e1/index.d.ts +2 -0
  15. package/dist/e1/prompt-raise.d.ts +65 -0
  16. package/dist/index.d.ts +4 -1
  17. package/dist/index.js +4652 -252
  18. package/dist/keychain/__tests__/keychain-manager.test.d.ts +1 -0
  19. package/dist/keychain/__tests__/keychain-migrate.test.d.ts +1 -0
  20. package/dist/keychain/__tests__/migrate-nudge.test.d.ts +1 -0
  21. package/dist/keychain/keychain-backend.d.ts +105 -0
  22. package/dist/keychain/keychain-manager.d.ts +17 -3
  23. package/dist/keychain/keychain-migrate.d.ts +63 -0
  24. package/dist/keychain/migrate-nudge.d.ts +38 -0
  25. package/dist/local-executor/__tests__/anchored-fs.test.d.ts +1 -0
  26. package/dist/local-executor/__tests__/bounded-directory.test.d.ts +1 -0
  27. package/dist/local-executor/__tests__/bounded-output.test.d.ts +1 -0
  28. package/dist/local-executor/__tests__/durable-directory.test.d.ts +1 -0
  29. package/dist/local-executor/__tests__/hosted-class-a-sink.test.d.ts +1 -0
  30. package/dist/local-executor/__tests__/process-identity.test.d.ts +1 -0
  31. package/dist/local-executor/__tests__/process-tree.test.d.ts +1 -0
  32. package/dist/local-executor/__tests__/protocol-backlog-wiring.test.d.ts +1 -0
  33. package/dist/local-executor/__tests__/protocol-backlog.test.d.ts +1 -0
  34. package/dist/local-executor/__tests__/publication-authority-capability.test.d.ts +1 -0
  35. package/dist/local-executor/__tests__/snapshot-merge.test.d.ts +1 -0
  36. package/dist/local-executor/__tests__/workspace-authority-fixture.d.ts +3 -0
  37. package/dist/local-executor/__tests__/workspace-authority.test.d.ts +1 -0
  38. package/dist/local-executor/__tests__/workspace-cleanup-audit.test.d.ts +1 -0
  39. package/dist/local-executor/__tests__/workspace-materializer.test.d.ts +1 -0
  40. package/dist/local-executor/agentic-disposable-repo.d.ts +23 -6
  41. package/dist/local-executor/agentic-resolve.d.ts +16 -0
  42. package/dist/local-executor/anchored-fs.d.ts +250 -0
  43. package/dist/local-executor/bounded-directory.d.ts +78 -0
  44. package/dist/local-executor/bounded-helper.d.ts +22 -0
  45. package/dist/local-executor/bounded-output.d.ts +11 -0
  46. package/dist/local-executor/class-a-emit.d.ts +13 -1
  47. package/dist/local-executor/durable-directory.d.ts +25 -0
  48. package/dist/local-executor/durable-store.d.ts +217 -25
  49. package/dist/local-executor/hosted-class-a-sink.d.ts +27 -0
  50. package/dist/local-executor/index.d.ts +3 -2
  51. package/dist/local-executor/local-executor-impl.d.ts +159 -69
  52. package/dist/local-executor/process-identity.d.ts +46 -0
  53. package/dist/local-executor/process-tree.d.ts +123 -0
  54. package/dist/local-executor/protocol-backlog.d.ts +62 -0
  55. package/dist/local-executor/revert-reconcile.d.ts +4 -0
  56. package/dist/local-executor/revert-runner.d.ts +14 -1
  57. package/dist/local-executor/snapshot-merge.d.ts +124 -0
  58. package/dist/local-executor/task-group-types.d.ts +7 -6
  59. package/dist/local-executor/team-execution-flag.d.ts +2 -2
  60. package/dist/local-executor/track-registry.d.ts +2 -0
  61. package/dist/local-executor/types.d.ts +33 -2
  62. package/dist/local-executor/verification-gates/build.d.ts +5 -0
  63. package/dist/local-executor/verification-gates/deploy-preflight.d.ts +2 -0
  64. package/dist/local-executor/verification-gates/diff-sanity.d.ts +12 -0
  65. package/dist/local-executor/verification-gates/hostile-grep.d.ts +2 -0
  66. package/dist/local-executor/verification-gates/lint.d.ts +2 -0
  67. package/dist/local-executor/verification-gates/shell-runner.d.ts +5 -0
  68. package/dist/local-executor/verification-gates/source-traceability.d.ts +2 -0
  69. package/dist/local-executor/verification-gates/tests.d.ts +3 -0
  70. package/dist/local-executor/verification-gates/typecheck.d.ts +3 -0
  71. package/dist/local-executor/verification-runner.d.ts +6 -0
  72. package/dist/local-executor/workspace-authority.d.ts +45 -0
  73. package/dist/local-executor/workspace-cleanup-audit.d.ts +3 -0
  74. package/dist/local-executor/workspace-materializer.d.ts +48 -0
  75. package/dist/local-executor/workspace-shadow.d.ts +380 -85
  76. package/dist/orchestration-shell/__tests__/advisory-attachment-journal.test.d.ts +1 -0
  77. package/dist/orchestration-shell/__tests__/direct-file-delete.test.d.ts +1 -0
  78. package/dist/orchestration-shell/__tests__/flag-command.test.d.ts +1 -0
  79. package/dist/orchestration-shell/__tests__/halt-message-wire-content.test.d.ts +1 -0
  80. package/dist/orchestration-shell/__tests__/planner-offer-e1.test.d.ts +1 -0
  81. package/dist/orchestration-shell/__tests__/workspace-shutdown.test.d.ts +1 -0
  82. package/dist/orchestration-shell/advisory-attachment-journal.d.ts +165 -0
  83. package/dist/orchestration-shell/attachments.d.ts +47 -58
  84. package/dist/orchestration-shell/audit-browser.d.ts +54 -1
  85. package/dist/orchestration-shell/bounded-shutdown.d.ts +6 -0
  86. package/dist/orchestration-shell/cli.d.ts +10 -0
  87. package/dist/orchestration-shell/cli.js +38355 -27300
  88. package/dist/orchestration-shell/context-items.d.ts +3 -0
  89. package/dist/orchestration-shell/declared-test-runner.d.ts +21 -2
  90. package/dist/orchestration-shell/direct-file-delete.d.ts +22 -0
  91. package/dist/orchestration-shell/emit-shell-event.d.ts +7 -0
  92. package/dist/orchestration-shell/explicit-tty-exit.d.ts +1 -2
  93. package/dist/orchestration-shell/flag-command.d.ts +81 -0
  94. package/dist/orchestration-shell/gate-decision-submit.d.ts +11 -0
  95. package/dist/orchestration-shell/gate-prompts.d.ts +116 -0
  96. package/dist/orchestration-shell/index.d.ts +34 -6
  97. package/dist/orchestration-shell/planner-offer-e1.d.ts +97 -0
  98. package/dist/orchestration-shell/quorum-loop.d.ts +312 -61
  99. package/dist/orchestration-shell/reducer.d.ts +9 -0
  100. package/dist/orchestration-shell/task-progress.d.ts +18 -4
  101. package/dist/orchestration-shell/team-decompose.d.ts +10 -10
  102. package/dist/orchestration-shell/types.d.ts +90 -2
  103. package/dist/orchestration-shell/workspace-shutdown.d.ts +47 -0
  104. package/dist/reviewer/output-parser.d.ts +19 -0
  105. package/dist/reviewer/providers/codex.d.ts +5 -3
  106. package/dist/reviewer/token-usage.d.ts +41 -12
  107. package/dist/reviewer/types.d.ts +6 -0
  108. package/dist/reviewer/verdict-classifier.d.ts +1 -0
  109. package/dist/session/session-rekey.d.ts +4 -3
  110. package/dist/substrate/__tests__/command-runner.test.d.ts +1 -0
  111. package/dist/substrate/command-runner.d.ts +2 -0
  112. package/dist/substrate/docker.d.ts +7 -32
  113. package/dist/substrate/index.d.ts +0 -1
  114. package/dist/substrate/sandbox-exec.d.ts +0 -13
  115. package/dist/substrate/types.d.ts +15 -2
  116. package/dist/substrate-launch/__tests__/reviewer-credential-preflight.test.d.ts +1 -0
  117. package/dist/substrate-launch/engage-substrate.d.ts +3 -0
  118. package/dist/substrate-launch/index.d.ts +2 -0
  119. package/dist/substrate-launch/reviewer-credential-preflight.d.ts +50 -0
  120. package/dist/test-publication-authority-setup.d.ts +1 -0
  121. package/dist/tool-activity/replay-cursor.d.ts +42 -8
  122. package/dist/track-presentation.d.ts +2 -0
  123. package/dist/track-presentation.test.d.ts +1 -0
  124. package/dist/types/encryption.d.ts +5 -0
  125. package/dist/types/events.d.ts +5 -0
  126. package/package.json +3 -3
  127. package/dist/substrate/git-proxy.d.ts +0 -35
  128. /package/dist/{substrate/__tests__/git-proxy.test.d.ts → appsync/__tests__/appsync-client-flag-locator.test.d.ts} +0 -0
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * One desktop-local progress phase. Discriminated by `phase`. Every variant is
3
- * counts + labels + paths only — NEVER plaintext (see the module invariant).
3
+ * counts + labels + paths only — never workspace/diff/reasoning plaintext —
4
+ * with the module invariant's ONE documented exception: `halt_notice.message`
5
+ * (controlled operational notice text; see the header + the entry's carve-out).
4
6
  */
5
7
  export type TaskProgressEvent = ({
6
8
  phase: 'shadow_created';
@@ -43,6 +45,7 @@ export type TaskProgressEvent = ({
43
45
  phase: 'round_failed';
44
46
  round: number;
45
47
  reason: string;
48
+ taskId?: string;
46
49
  } | {
47
50
  phase: 'continuation_offered';
48
51
  round: number;
@@ -57,10 +60,15 @@ export type TaskProgressEvent = ({
57
60
  } | {
58
61
  phase: 'promoted';
59
62
  files: number;
63
+ taskId?: string;
60
64
  } | {
61
65
  phase: 'discarding';
62
66
  } | {
63
67
  phase: 'discarded';
68
+ taskId?: string;
69
+ } | {
70
+ phase: 'not_applied';
71
+ taskId?: string;
64
72
  } | {
65
73
  phase: 'waiting_user';
66
74
  } | {
@@ -71,6 +79,9 @@ export type TaskProgressEvent = ({
71
79
  phase: 'agent_advisory';
72
80
  } | {
73
81
  phase: 'progress_cleared';
82
+ } | {
83
+ phase: 'halt_notice';
84
+ message: string;
74
85
  }) & {
75
86
  epoch?: number;
76
87
  tokens?: number;
@@ -109,9 +120,12 @@ export declare function formatTokens(n: number): string;
109
120
  */
110
121
  export declare function isSpinnerPhase(phase: TaskProgressEvent['phase']): boolean;
111
122
  /**
112
- * Render the user-facing ONE-LINE text for a progress event. Pure (no plaintext
113
- * — only counts/labels/paths/elapsed). The TUI shows spinner phases as an
114
- * ephemeral live line and milestone phases as persisted scrollback entries.
123
+ * Render the user-facing ONE-LINE text for a progress event. Pure. No
124
+ * workspace/diff/reasoning plaintext — counts/labels/paths/elapsed, plus the
125
+ * module invariant's ONE documented exception: `halt_notice` renders its
126
+ * controlled operational `message` verbatim (see the header carve-out). The
127
+ * TUI shows spinner phases as an ephemeral live line and milestone phases as
128
+ * persisted scrollback entries.
115
129
  */
116
130
  export declare function renderProgressLine(event: TaskProgressEvent): string;
117
131
  /**
@@ -18,17 +18,17 @@ export declare const WorkItemInputSchema: z.ZodDiscriminatedUnion<"decompose", [
18
18
  access: z.ZodEnum<["write", "read"]>;
19
19
  }, "strip", z.ZodTypeAny, {
20
20
  path: string;
21
- access: "write" | "read";
21
+ access: "read" | "write";
22
22
  }, {
23
23
  path: string;
24
- access: "write" | "read";
24
+ access: "read" | "write";
25
25
  }>, "many">;
26
26
  test_surfaces: z.ZodArray<z.ZodString, "many">;
27
27
  auto_modified_files: z.ZodArray<z.ZodString, "many">;
28
28
  }, "strip", z.ZodTypeAny, {
29
29
  shared_contracts: {
30
30
  path: string;
31
- access: "write" | "read";
31
+ access: "read" | "write";
32
32
  }[];
33
33
  write_paths: string[];
34
34
  test_surfaces: string[];
@@ -36,7 +36,7 @@ export declare const WorkItemInputSchema: z.ZodDiscriminatedUnion<"decompose", [
36
36
  }, {
37
37
  shared_contracts: {
38
38
  path: string;
39
- access: "write" | "read";
39
+ access: "read" | "write";
40
40
  }[];
41
41
  write_paths: string[];
42
42
  test_surfaces: string[];
@@ -50,7 +50,7 @@ export declare const WorkItemInputSchema: z.ZodDiscriminatedUnion<"decompose", [
50
50
  ownershipScope: {
51
51
  shared_contracts: {
52
52
  path: string;
53
- access: "write" | "read";
53
+ access: "read" | "write";
54
54
  }[];
55
55
  write_paths: string[];
56
56
  test_surfaces: string[];
@@ -63,7 +63,7 @@ export declare const WorkItemInputSchema: z.ZodDiscriminatedUnion<"decompose", [
63
63
  ownershipScope: {
64
64
  shared_contracts: {
65
65
  path: string;
66
- access: "write" | "read";
66
+ access: "read" | "write";
67
67
  }[];
68
68
  write_paths: string[];
69
69
  test_surfaces: string[];
@@ -73,13 +73,12 @@ export declare const WorkItemInputSchema: z.ZodDiscriminatedUnion<"decompose", [
73
73
  implementorAgent?: unknown;
74
74
  }>, "many">;
75
75
  }, "strip", z.ZodTypeAny, {
76
- decompose: true;
77
76
  workItems: {
78
77
  description: string;
79
78
  ownershipScope: {
80
79
  shared_contracts: {
81
80
  path: string;
82
- access: "write" | "read";
81
+ access: "read" | "write";
83
82
  }[];
84
83
  write_paths: string[];
85
84
  test_surfaces: string[];
@@ -88,14 +87,14 @@ export declare const WorkItemInputSchema: z.ZodDiscriminatedUnion<"decompose", [
88
87
  implementorAgent: "CLAUDE" | "CODEX" | "ANTIGRAVITY";
89
88
  isSharedTestOwner: boolean;
90
89
  }[];
91
- }, {
92
90
  decompose: true;
91
+ }, {
93
92
  workItems: {
94
93
  description: string;
95
94
  ownershipScope: {
96
95
  shared_contracts: {
97
96
  path: string;
98
- access: "write" | "read";
97
+ access: "read" | "write";
99
98
  }[];
100
99
  write_paths: string[];
101
100
  test_surfaces: string[];
@@ -104,6 +103,7 @@ export declare const WorkItemInputSchema: z.ZodDiscriminatedUnion<"decompose", [
104
103
  isSharedTestOwner: boolean;
105
104
  implementorAgent?: unknown;
106
105
  }[];
106
+ decompose: true;
107
107
  }>, z.ZodObject<{
108
108
  decompose: z.ZodLiteral<false>;
109
109
  reason: z.ZodString;
@@ -136,6 +136,29 @@ export interface RunningTaskState {
136
136
  exitCode?: number;
137
137
  bypassReason?: 'deterministic_shortcut' | 'planner_outage' | 'planner_degraded_explicit_override';
138
138
  }
139
+ /**
140
+ * P10 E3 r2 — one row of the bare-`/audit` session listing (the
141
+ * `sessionTasks` value). Deliberately NOT `RunningTaskState`: Agent Teams
142
+ * child tasks arrive via TEAM_TRACK_ASSIGNED (Stage-2 r1 Codex MED-1) which
143
+ * carries no pid, so forcing that shape would fabricate fields. Display-only.
144
+ */
145
+ export interface SessionTaskRecord {
146
+ taskId: string;
147
+ /** Implementor agent when known; a team ASSIGNED event may omit it. */
148
+ agentKind?: string;
149
+ /** 'single' = TASK_LIFECYCLE-tracked; 'team' = Agent Teams track. */
150
+ origin: 'single' | 'team';
151
+ /**
152
+ * Singles: the lifecycle status — 'running' at dispatch, flipped terminal
153
+ * by the task-end CLOSER progress events (promoted → 'completed',
154
+ * discarded → 'cancelled', round_failed → 'failed'; Stage-2 r1 Codex
155
+ * MED-2 — no production TASK_LIFECYCLE dispatch ever carries a terminal
156
+ * status). Team rows: the TeamTrackState label verbatim.
157
+ */
158
+ status: string;
159
+ /** Singles: the dispatch stamp. Team rows: first-observed stamp. */
160
+ startedAt: string;
161
+ }
139
162
  /**
140
163
  * §5.1 LOCK (lines 547-556). Single reviewer subprocess identity +
141
164
  * verdict. `reviewerKind` is hand-listed per CP-1 — CP-3 Stage A
@@ -356,6 +379,7 @@ export type ConversationEntry = {
356
379
  serverDecision: string | null;
357
380
  };
358
381
  reviewSummary?: ReviewSummaryPanelModel;
382
+ queuedReviewSummaries?: Readonly<Record<string, ReviewSummaryPanelModel>>;
359
383
  } | {
360
384
  kind: 'gate-panel';
361
385
  id: string;
@@ -544,13 +568,15 @@ export interface TeamState {
544
568
  * the user is in control (a gate prompt is shown → `waiting_user` clears it).
545
569
  * Milestones (diff captured, verdicts received, promoted, …) are NOT stored here
546
570
  * — they are appended to `conversation` as persisted scrollback entries. This is
547
- * desktop-LOCAL only: counts/labels/elapsed, never plaintext (see
571
+ * desktop-LOCAL only: counts/labels/elapsed, never plaintext — `halt_notice`,
572
+ * the union's one free-text exception, can never open or refresh this live
573
+ * line (reducer phase-family guard); it is scrollback-only (see
548
574
  * `task-progress.ts`).
549
575
  */
550
576
  export interface LiveProgress {
551
577
  /** The phase of the in-flight spinner line. */
552
578
  phase: TaskProgressEvent['phase'];
553
- /** The BOUNDED live label (counts/labels/paths only — no plaintext, no embedded timer). */
579
+ /** The BOUNDED live label (counts/labels/paths only — no plaintext; `halt_notice` never reaches here; no embedded timer). */
554
580
  text: string;
555
581
  /** When this line was last refreshed. Retained; currently unused (no component reads it). */
556
582
  updatedAt: string;
@@ -582,6 +608,11 @@ export interface OrchestrationState {
582
608
  plannerHealth: PlannerHealthState;
583
609
  conversation: ConversationEntry[];
584
610
  runningTasks: Map<string, RunningTaskState>;
611
+ sessionTasks: Map<string, SessionTaskRecord>;
612
+ lastReviewerProgress: {
613
+ text: string;
614
+ at: string;
615
+ } | null;
585
616
  queuedTasks: QueuedTask[];
586
617
  activeReviewerSeats: Map<string, ReviewerSeatState>;
587
618
  currentGate: GateState | null;
@@ -637,6 +668,57 @@ export interface OrchestrationState {
637
668
  * keyboard focus. Non-team / Companion / CP-1.a sessions never open it.
638
669
  */
639
670
  reviewerWizard: ReviewerWizardState | null;
671
+ /**
672
+ * `[ADDITIVE WIDENING — O1 C1 (#652)]` per
673
+ * PHASE-O1-C1-SAFETY-OBSERVABILITY-DESIGN.md §3.1 item 1: the shell used to
674
+ * render and DISCARD the `/audit` browser model; `/flag <entry-id>` needs
675
+ * session-scoped retention of the LAST-rendered listing's
676
+ * `entryId → {seqNum, kind, flaggable}` mapping to build the plaintext
677
+ * target locator without re-querying. `null` until the first successful
678
+ * `/audit <task-id>` render. Desktop-local only; row COORDINATES + closed
679
+ * enum labels only — never decrypted payload content.
680
+ */
681
+ auditFlagIndex: AuditFlagIndex | null;
682
+ }
683
+ /**
684
+ * One retained `/audit` listing row, keyed by its audit `entry_id` in
685
+ * {@link AuditFlagIndex.entries}. Shape-only: row coordinates + the plaintext
686
+ * wire kind + the precomputed flag-eligibility bit (derived from the decrypted
687
+ * `gate_resolved` outcome at render time — the decrypted payload itself is
688
+ * NOT retained).
689
+ */
690
+ export interface AuditFlagEntryRecord {
691
+ /**
692
+ * The flagged row's audit-table sort key — the zero-padded 16-digit
693
+ * `seqNum` string exactly as surfaced by `queryAudit`'s additive
694
+ * `AuditEntryWireRow.seqNum` projection (core-rs `types.rs`), or `null`
695
+ * when the row predates the projection (stale backend) — `/flag` then
696
+ * fails closed with an actionable message.
697
+ */
698
+ seqNum: string | null;
699
+ /** Plaintext snake_case wire kind (e.g. `gate_resolved`). */
700
+ kind: string;
701
+ /**
702
+ * True iff the entry is a decrypted `gate_resolved` row whose outcome is
703
+ * the quorum's approve consensus (`consensus_approve` / `proceed`) — the
704
+ * client-side defense-in-depth subset check of design §3.1 item 1 (the
705
+ * server independently enforces the same subset, §3.1 item 4).
706
+ */
707
+ flaggable: boolean;
708
+ }
709
+ /**
710
+ * The session-scoped retained `/audit` mapping (design §3.1 item 1). Replaced
711
+ * wholesale on each successful `/audit <task-id>` render (last render wins);
712
+ * `flagged` carries forward across renders so "already flagged" survives
713
+ * re-listing. Lives in {@link OrchestrationState.auditFlagIndex}.
714
+ */
715
+ export interface AuditFlagIndex {
716
+ /** The task whose listing was rendered — becomes `flaggedTaskId`. */
717
+ taskId: string;
718
+ /** `entryId → record` for every entry in the last-rendered listing. */
719
+ entries: Map<string, AuditFlagEntryRecord>;
720
+ /** Entry ids flagged this session (dedup no-op render on repeat `/flag`). */
721
+ flagged: Set<string>;
640
722
  }
641
723
  /**
642
724
  * Snapshot threaded into the interactive `/reviewer-setup` wizard when it
@@ -823,6 +905,12 @@ export type OrchestrationAction = {
823
905
  wizard: ReviewerWizardState;
824
906
  } | {
825
907
  type: 'REVIEWER_WIZARD_CLOSE';
908
+ } | {
909
+ type: 'AUDIT_FLAG_INDEX_RETAINED';
910
+ index: AuditFlagIndex;
911
+ } | {
912
+ type: 'AUDIT_FLAG_RECORDED';
913
+ entryId: string;
826
914
  } | {
827
915
  type: 'EXIT';
828
916
  };
@@ -0,0 +1,47 @@
1
+ export interface WorkspaceShutdownOperations {
2
+ flushPlannerCache?: () => Promise<void>;
3
+ clearPlannerSession?: () => void;
4
+ disposeQuorumWorkspaces?: () => Promise<void>;
5
+ drainLocalWorkspaces?: () => Promise<void>;
6
+ /** Settle already-admitted shell turns after their agent processes drain. */
7
+ drainShellSubmissions?: () => Promise<void>;
8
+ /** Flush the settled turns' local and hosted canonical context publications. */
9
+ finalizeContextItemPublications?: () => Promise<void>;
10
+ /** Audit/retry exact advisory-image authority after every owning turn settles. */
11
+ disposeAdvisoryAttachmentAuthority?: () => Promise<void>;
12
+ disposeLocalDurableSessionResources?: () => Promise<void>;
13
+ /** Final hosted terminal mutation; no local or hosted turn publication follows. */
14
+ retireHostedSession?: () => Promise<void>;
15
+ onPlannerFlushFailure?: (error: Error) => void;
16
+ onWorkspaceFailure?: (error: Error) => void;
17
+ }
18
+ export interface StartedWorkspaceShutdown {
19
+ /**
20
+ * Every teardown phase, including best-effort planner flush and hosted
21
+ * retirement. This is the operation governed by the shell's normal/signal
22
+ * responsiveness deadline.
23
+ */
24
+ completion: Promise<void>;
25
+ /**
26
+ * The local resource-retirement boundary. A normal process exit must await
27
+ * this even after the broader teardown deadline expires, otherwise a large
28
+ * authenticated snapshot deletion can be killed halfway through and leak its
29
+ * private workspace.
30
+ */
31
+ resourceRetirement: Promise<void>;
32
+ }
33
+ /**
34
+ * Start every independent shutdown fence before awaiting any one owner.
35
+ *
36
+ * The LocalExecutor's shared durable group retirement is deliberately a final
37
+ * phase: Quorum may still have an already-admitted terminal publisher that is
38
+ * allowed to finish while its ingress is closed. Only after both Quorum and
39
+ * LocalExecutor drains settle can the durable store be enumerated exactly once
40
+ * without a late publisher recreating a group behind the cleanup pass.
41
+ */
42
+ export declare function startWorkspaceShutdownOperations(operations: WorkspaceShutdownOperations): StartedWorkspaceShutdown;
43
+ /**
44
+ * Compatibility surface for callers that need the complete shutdown rather
45
+ * than its separately-observable local resource boundary.
46
+ */
47
+ export declare function runWorkspaceShutdownOperations(operations: WorkspaceShutdownOperations): Promise<void>;
@@ -19,7 +19,26 @@ export interface ParsedVerdict {
19
19
  * via `revise_missing_changes` / `suggested_changes_require_revise`).
20
20
  */
21
21
  suggested_changes: string[];
22
+ /**
23
+ * Ordered non-blocking observations from the explicit
24
+ * `RESIDUAL OBSERVATIONS:` section. These never count as suggested changes.
25
+ */
26
+ residual_observations: string[];
27
+ }
28
+ export interface ResidualObservationSplit {
29
+ /** Reviewer output with the explicit residual section removed. */
30
+ reviewText: string;
31
+ /** Ordered, non-empty residual observations. */
32
+ residualObservations: string[];
22
33
  }
34
+ /**
35
+ * Split the optional P15 residual-observation section from reviewer prose.
36
+ *
37
+ * The heading must occupy its own line. Bullets are preferred, but plain
38
+ * non-empty lines are retained as observations so harmless reviewer format
39
+ * drift cannot turn a non-blocking note into a revision request.
40
+ */
41
+ export declare function splitResidualObservations(raw: string): ResidualObservationSplit;
23
42
  /**
24
43
  * Why a reviewer's reply failed the locked-format check. Discriminated
25
44
  * union; the subprocess layer maps any of these into `ReviewerError` with
@@ -3,6 +3,7 @@ import { type SubprocessOutcome } from '../subprocess.js';
3
3
  import type { ReviewerVerdict } from '../types.js';
4
4
  import { type VerdictClassifier } from '../verdict-classifier.js';
5
5
  import type { BuiltCommand } from './claude.js';
6
+ import { type InvocationUsageSnapshot } from '../token-usage.js';
6
7
  /** Construction options. */
7
8
  export interface CodexReviewerProviderOptions {
8
9
  /** Override the `codex` executable path. Production callers pass nothing
@@ -58,15 +59,16 @@ export declare function buildCommand(executable: string, spec: ReviewerSpec, las
58
59
  export declare function buildVerdict(spec: ReviewerSpec, gateId: string, outcome: SubprocessOutcome, lastMessage: string, classifyVerdict?: VerdictClassifier): Promise<ReviewerVerdict>;
59
60
  /**
60
61
  * Sum `usage.input_tokens + usage.output_tokens` across every
61
- * `turn.completed` JSONL event in `stdout`. Returns `null` when no
62
- * `turn.completed` event reported any token count, so dashboards can
63
- * distinguish "no data" from a real zero.
62
+ * `turn.completed` JSONL event in `stdout`. Returns `null` when usage is absent,
63
+ * partial, or invalid so legacy call sites do not turn unknown values into a
64
+ * false complete total.
64
65
  *
65
66
  * Lenient: malformed JSONL lines are silently skipped (Codex's stream is
66
67
  * designed to be append-only, so partial flushes during timeout could
67
68
  * leave a final truncated line).
68
69
  */
69
70
  export declare function sumCodexTokens(stdout: string): number | null;
71
+ export declare function extractCodexUsageSnapshot(stdout: string, elapsedMs?: number | null): InvocationUsageSnapshot;
70
72
  /**
71
73
  * Generate a unique-per-spawn path for `--output-last-message`. Lives in
72
74
  * the OS temp dir; we own its lifecycle (create on codex's side, read +
@@ -1,14 +1,39 @@
1
1
  /**
2
- * [P2-0] Clamp an UNTYPED token field (from agent CLI JSON) to a finite,
3
- * non-negative INTEGER. Token fields come from untyped agent JSON — a string /
4
- * object / `NaN` / negative / fractional value would poison the per-task
5
- * accumulator (→ `NaN` render, or a reopened window showing a LOWER total),
6
- * violating the "token count is a number" invariant. Every numeric ingress
7
- * (`unwrapClaudeJson` usage reads, Codex `sumCodexTokens` per-event sum, the
8
- * QuorumLoop `addTaskTokens`) gates on this, so a malformed field contributes 0,
9
- * never corrupts the accumulator.
2
+ * [P2-0] Clamp an UNTYPED token field (from agent CLI JSON) to the same finite,
3
+ * bounded INTEGER contract the runtime persists. Token fields come from untyped
4
+ * agent JSON — a string / object / `NaN` / negative / fractional / over-contract
5
+ * value would poison the per-task accumulator or fabricate usage. Malformed
6
+ * fields contribute 0 to legacy additive counters and canonical snapshots mark
7
+ * reported invalid fields as `usage_invalid`.
10
8
  */
11
9
  export declare function finiteToken(n: unknown): number;
10
+ export type InvocationUsageAvailability = 'complete' | 'partial' | 'unavailable';
11
+ export interface InvocationUsageSnapshot {
12
+ /** Prompt/input tokens. `cachedInputTokens` is a subset, not an addend. */
13
+ inputTokens: number | null;
14
+ /** Output/completion tokens. */
15
+ outputTokens: number | null;
16
+ /** Cached input token subset when the provider exposes it. */
17
+ cachedInputTokens: number | null;
18
+ /** Backward-compatible aggregate: input + output, never cache-added. */
19
+ totalTokens: number | null;
20
+ /** End-to-end invocation elapsed time when known. */
21
+ elapsedMs: number | null;
22
+ availability: InvocationUsageAvailability;
23
+ /** Closed reason label when availability is unavailable/partial. */
24
+ unavailableReason: string | null;
25
+ }
26
+ export declare function tokenFieldAvailable(value: unknown): value is number;
27
+ export declare function usageSnapshotFromParts(args: {
28
+ inputTokens: number;
29
+ outputTokens: number;
30
+ cachedInputTokens?: number;
31
+ elapsedMs?: number | null;
32
+ inputTokensAvailable?: boolean;
33
+ outputTokensAvailable?: boolean;
34
+ cachedInputTokensAvailable?: boolean;
35
+ }): InvocationUsageSnapshot;
36
+ export declare function unavailableUsageSnapshot(reason: string, elapsedMs?: number | null): InvocationUsageSnapshot;
12
37
  /**
13
38
  * Locate the FIRST balanced top-level `{...}` in `stdout` that parses to an object
14
39
  * with `type === 'result'` — Claude may emit non-JSON warning / MCP lines before
@@ -31,12 +56,16 @@ export declare function firstResultEnvelope(stdout: string): Record<string, unkn
31
56
  * • `is_error === true` OR `result` not a non-empty string → `{ text:'', tokens:
32
57
  * undefined }`. The CALLER treats an empty/failed result as an agent FAILURE
33
58
  * (reviewer ESCALATE / resolver human-gate — same as today), NOT a silent pass.
34
- * • else → `{ text: result, tokens: (finiteToken(usage.input_tokens) +
35
- * finiteToken(usage.output_tokens)) || undefined }`. `finiteToken` clamps
36
- * absent/malformed usage to 0 (no `TypeError`, no `NaN`); cache tokens are
37
- * excluded in v1 (input+output only — see design "Known v1 limitation").
59
+ * • else → `{ text: result, tokens: totalTokens || undefined }`. `finiteToken`
60
+ * clamps absent/malformed usage to 0 (no `TypeError`, no `NaN`). Claude's
61
+ * documented input total is uncached input plus cache-write/cache-read
62
+ * buckets, while `cachedInputTokens` remains the cached subset. The older
63
+ * `cached_input_tokens` alias is intentionally ignored unless backed by
64
+ * documented Claude result-envelope evidence.
38
65
  */
66
+ export declare function extractClaudeUsageSnapshot(stdout: string, elapsedMs?: number | null): InvocationUsageSnapshot;
39
67
  export declare function unwrapClaudeJson(stdout: string): {
40
68
  text: string;
41
69
  tokens?: number;
70
+ usage: InvocationUsageSnapshot;
42
71
  };
@@ -1,3 +1,4 @@
1
+ import type { InvocationUsageSnapshot } from './token-usage.js';
1
2
  /**
2
3
  * Agent kinds the reviewer subprocess layer can spawn.
3
4
  *
@@ -90,6 +91,9 @@ export interface ReviewerVerdict {
90
91
  /** Ordered list of specific changes. **Required** when `verdict === 'REVISE'`;
91
92
  * empty for other verdicts (enforced by the output parser). */
92
93
  suggested_changes: string[];
94
+ /** Optional non-blocking risks or recommendations. These are displayed in
95
+ * the terminal summary but never affect consensus or trigger revision. */
96
+ residual_observations: string[];
93
97
  /** Model identifier used (for cost attribution). */
94
98
  model_used: string | null;
95
99
  /** Tokens consumed by this reviewer. */
@@ -98,4 +102,6 @@ export interface ReviewerVerdict {
98
102
  latency_ms: number | null;
99
103
  /** ISO 8601 UTC timestamp string when the reviewer returned the verdict. */
100
104
  submitted_at: string;
105
+ /** Canonical input/output/cache/elapsed usage snapshot. Additive post-launch. */
106
+ usage?: InvocationUsageSnapshot;
101
107
  }
@@ -59,4 +59,5 @@ export declare function resolveClassifiedVerdictFields(classification: VerdictCl
59
59
  verdict: VerdictKind;
60
60
  reasoning: string;
61
61
  suggested_changes: string[];
62
+ residual_observations: string[];
62
63
  };
@@ -27,9 +27,10 @@ export interface RekeyOptions {
27
27
  * bound to its current public key and nothing is forced.
28
28
  *
29
29
  * @param sessionId The session to re-key.
30
- * @param sessionKey The plaintext session key (base64). The caller must
31
- * already hold this — typically from
32
- * keychainManager.getCachedSessionKey(sessionId).
30
+ * @param sessionKey The caller's current plaintext session key (base64).
31
+ * This is only an admission hint: after fetching the
32
+ * authoritative row, the function re-derives/loads the key
33
+ * for that row's exact generation before wrapping.
33
34
  * @param appSyncClient Authenticated AppSyncClient.
34
35
  * @param options Optional behavior knobs. See RekeyOptions.
35
36
  * @returns The number of new grants that succeeded.
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,5 @@
1
1
  import type { CommandResult, CommandRunner, RunnerProc } from './types';
2
+ import type { WorkspaceRootAuthority } from '../local-executor/workspace-authority';
2
3
  /**
3
4
  * The production `CommandRunner` — runs `docker` / `sandbox-exec` via
4
5
  * `node:child_process`. No shell is used (argv is passed directly to
@@ -15,5 +16,6 @@ export declare class ChildProcessCommandRunner implements CommandRunner {
15
16
  signal?: AbortSignal;
16
17
  env?: Readonly<Record<string, string>>;
17
18
  cwd?: string;
19
+ cwdAuthority?: WorkspaceRootAuthority;
18
20
  }): RunnerProc;
19
21
  }
@@ -1,5 +1,6 @@
1
1
  import { type ForwarderFactory } from './forwarder';
2
2
  import type { CommandRunner, EgressObservationHook, Substrate, SubstrateHandle, SubstrateSpec } from './types';
3
+ import { type WorkspaceRootAuthority, type WorkspaceRootLease } from '../local-executor/workspace-authority';
3
4
  /** Where, inside the container, the worktree is mounted (the agent's cwd/home). */
4
5
  export declare const CONTAINER_WORKDIR = "/workspace";
5
6
  /** Injectable deps — default-wired to the real runtime; stubbed in unit tests. */
@@ -14,12 +15,13 @@ export interface DockerSubstrateDeps {
14
15
  image?: string;
15
16
  /**
16
17
  * Override the host root for the per-session scratch dir (default:
17
- * os.tmpdir()). The per-session dir holds ONLY the broker socket (in `uds/`),
18
- * the relay script, and the scrubbed git-proxy (in `gitproxy/`) — no secrets.
19
- * The git-proxy now lives UNDER this dir (MED fix), so the one
20
- * teardown/rollback rm removes it.
18
+ * os.tmpdir()). The per-session dir holds ONLY the broker socket (in `uds/`)
19
+ * and the relay script — no secrets or repository metadata.
20
+ * The one teardown/rollback removal retires the complete session authority.
21
21
  */
22
22
  sessionRoot?: string;
23
+ /** Original-handle bind source (native Linux by default; injectable for seam tests). */
24
+ acquireWorkdirLease?: (authority: WorkspaceRootAuthority) => Promise<WorkspaceRootLease>;
23
25
  }
24
26
  /** The deterministic per-session container name. */
25
27
  export declare function containerName(id: string): string;
@@ -44,7 +46,6 @@ export declare function buildContainerEntrypoint(sanitizedEnv: Readonly<Record<s
44
46
  * surface the conformance test pins:
45
47
  * - `--network none` → STRUCTURAL default-deny (only `lo`, no egress).
46
48
  * - `-v <workdir>:/workspace` → ONLY the worktree mounted (rw).
47
- * - `-v <gitProxy>:/workspace/.git:ro` → scrubbed `.git`, read-only (if any).
48
49
  * - `-v <relayScript>:/codevibe/relay.js:ro` → the in-container relay (ro).
49
50
  * - `-v <udsDir>:/codevibe/broker:rw` → the bind-mounted broker UDS dir (rw,
50
51
  * so the container's `connect()` works; the dir holds only the socket).
@@ -63,7 +64,6 @@ export declare function buildRunArgv(args: {
63
64
  id: string;
64
65
  image: string;
65
66
  workdir: string;
66
- gitProxyPath: string | null;
67
67
  relayScriptPath: string;
68
68
  udsDir: string;
69
69
  sanitizedEnv: Readonly<Record<string, string>>;
@@ -101,40 +101,15 @@ export declare class DockerSubstrate implements Substrate {
101
101
  private readonly onEgressDenied;
102
102
  private readonly image;
103
103
  private readonly sessionRoot;
104
+ private readonly acquireWorkdirLease;
104
105
  constructor(deps?: DockerSubstrateDeps);
105
106
  launch(spec: SubstrateSpec): Promise<SubstrateHandle>;
106
107
  private rollback;
107
- /**
108
- * r5 HIGH-2 (Codex — NULL-vs-THROW gap). The proxy build produced no usable
109
- * proxy (it returned `null` OR threw). Decide the safe outcome by whether the
110
- * workdir actually HAS a `.git`:
111
- *
112
- * - NO `<workdir>/.git` → return `null` (a non-git workdir; the
113
- * `docker run` mounts only the worktree,
114
- * git reports "not a repository" — no
115
- * credential surface either way).
116
- * - `<workdir>/.git` EXISTS → write an EMPTY SCRUBBED `.git` overlay
117
- * (a dir with ONLY a stripped synthetic
118
- * `config` — NO remotes/creds/hooks) and
119
- * return its path, so the `:ro` bind mount
120
- * SHADOWS the real `.git`. Degraded git
121
- * reads, but the credential surface is
122
- * fail-closed.
123
- * - overlay write ALSO fails → roll back + throw (NEVER mount the
124
- * worktree with a live `.git`).
125
- *
126
- * Used for BOTH the null-return and the throw path so a workdir with a real
127
- * but unresolvable `.git` can never reach the agent un-shadowed. `fsp.stat`
128
- * (NOT `lstat`) follows a `.git` that is a symlink/dir/file alike — any of
129
- * those "exists" cases must be shadowed.
130
- */
131
- private ensureGitOverlayOrFailClosed;
132
108
  private assertDockerAvailable;
133
109
  }
134
110
  export declare const __testing: {
135
111
  DEFAULT_IMAGE: string;
136
112
  CONTAINER_WORKDIR: string;
137
- CONTAINER_GIT: string;
138
113
  CONTAINER_RELAY_PATH: string;
139
114
  CONTAINER_BROKER_DIR: string;
140
115
  RELAY_PORT: number;
@@ -8,5 +8,4 @@ export { SubstrateUnavailableError, SubstrateLaunchError } from "./errors";
8
8
  export { ChildProcessCommandRunner } from "./command-runner";
9
9
  export { HostEgressForwarder, defaultForwarderFactory } from "./forwarder";
10
10
  export type { ForwarderSpec, ForwarderFactory } from "./forwarder";
11
- export { buildScrubbedGitProxy, resolveGitCommonDir } from "./git-proxy";
12
11
  export { IN_CONTAINER_RELAY_SOURCE, CONTAINER_RELAY_PATH, CONTAINER_BROKER_DIR, CONTAINER_BROKER_SOCK, BROKER_SOCK_NAME, RELAY_PORT, } from "./relay-script";
@@ -68,19 +68,6 @@ export declare function buildSeatbeltProfile(workdir: string, execPath?: string,
68
68
  * invariant that host secrets stay unreadable still holds).
69
69
  */
70
70
  extraReadDirs?: readonly string[],
71
- /**
72
- * Stage-2 HIGH (Codex — the `.git` credential leak). The host path of the
73
- * SCRUBBED `.git` proxy (built by `git-proxy.ts`, same as A1's mount). When
74
- * provided, the profile (a) GRANTS read on it (read-only — the agent runs
75
- * `git` against it via `GIT_DIR`) and (b) DENIES read+write of the REAL
76
- * `<workdir>/.git`, so the agent CANNOT read the host repo's credential
77
- * helpers / tokenized remotes / hooks / reflogs directly. Without this the A5
78
- * agent runs on the host fs and the `(allow file-read* (subpath "<wd>"))`
79
- * grant would expose the real `.git`. Null/absent for a non-git workdir (the
80
- * `.git` deny is still emitted — denying a non-existent path is harmless and
81
- * keeps the profile shape uniform).
82
- */
83
- gitProxyDir?: string | null,
84
71
  /**
85
72
  * r5 HIGH-1 (Codex) — the home dir to anchor the file-keychain (`~/.codevibe`)
86
73
  * DENY at. Default `os.homedir()`; injectable for deterministic tests. The