opencode-swarm 7.140.2 → 7.140.4

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 (113) hide show
  1. package/.opencode/skills/brainstorm/SKILL.md +1 -1
  2. package/.opencode/skills/ci-failure-batching/SKILL.md +11 -1
  3. package/.opencode/skills/ci-fix-monitor/SKILL.md +6 -4
  4. package/.opencode/skills/discover/SKILL.md +1 -1
  5. package/.opencode/skills/durable-session-state/SKILL.md +82 -0
  6. package/.opencode/skills/engineering-conventions/SKILL.md +1 -1
  7. package/.opencode/skills/issue-ingest/SKILL.md +13 -7
  8. package/.opencode/skills/issue-tracer/SKILL.md +1 -1
  9. package/.opencode/skills/orchestrating-subagents/SKILL.md +113 -0
  10. package/.opencode/skills/parallel-work-check/SKILL.md +1 -1
  11. package/.opencode/skills/swarm-ci-monitor/SKILL.md +5 -3
  12. package/.opencode/skills/swarm-pr-feedback/SKILL.md +30 -4
  13. package/.opencode/skills/writing-tests/SKILL.md +1 -1
  14. package/dist/agents/reviewer-directive-compliance.d.ts +19 -5
  15. package/dist/cli/{config-doctor-shc0n4q1.js → config-doctor-qqe6172n.js} +3 -3
  16. package/dist/cli/{core-p5cyej3r.js → core-52k057mf.js} +2 -2
  17. package/dist/cli/{curation-policy-7n6t8he4.js → curation-policy-9291bdat.js} +5 -7
  18. package/dist/cli/{curator-zp5qq24c.js → curator-04xqq68e.js} +28 -28
  19. package/dist/cli/{curator-llm-factory-pr4bdfqw.js → curator-llm-factory-cfm8fhdw.js} +28 -28
  20. package/dist/cli/{evidence-summary-service-nfdc1ht9.js → evidence-summary-service-em58myd7.js} +8 -8
  21. package/dist/cli/{gate-evidence-46qeyfc1.js → gate-evidence-ezxfkb22.js} +4 -4
  22. package/dist/cli/{guardrail-explain-thddj6jv.js → guardrail-explain-pn1bcgfz.js} +29 -29
  23. package/dist/cli/{guardrail-log-w8fmxe1x.js → guardrail-log-vb5zkegf.js} +4 -4
  24. package/dist/cli/{hive-promoter-0yg3gxg6.js → hive-promoter-z09khawt.js} +28 -28
  25. package/dist/cli/index-2rb3x0fk.js +2554 -0
  26. package/dist/cli/{index-hfvxhk4z.js → index-35qep0v7.js} +1 -1
  27. package/dist/cli/{index-h2waehqq.js → index-4hp8nvwb.js} +1 -1
  28. package/dist/cli/{index-1j5my2qy.js → index-7begd9aq.js} +4 -4
  29. package/dist/cli/{index-n831qq2v.js → index-a1fjhx4w.js} +822 -688
  30. package/dist/cli/{index-chx92bes.js → index-arza4m4j.js} +2 -2
  31. package/dist/cli/{index-ry0hgg3m.js → index-bfhwtdsw.js} +34 -0
  32. package/dist/cli/{index-jfjnn408.js → index-bn17ycxn.js} +1 -1
  33. package/dist/cli/{index-1m1ksyqt.js → index-c5kr20nz.js} +1 -1
  34. package/dist/cli/{index-4rje8dc0.js → index-djbhe0yh.js} +30 -30
  35. package/dist/cli/{index-t59cdg48.js → index-dtam929z.js} +2 -19
  36. package/dist/cli/{index-n0pja0qs.js → index-dtyeabmj.js} +2 -2
  37. package/dist/cli/{index-9txca231.js → index-hfjvepk2.js} +11 -9
  38. package/dist/cli/{index-vjqe1z2w.js → index-hfwzxh3j.js} +3 -3
  39. package/dist/cli/{index-n408rw7n.js → index-hxvkfx6t.js} +12 -0
  40. package/dist/cli/{index-brh827g0.js → index-hz0refz4.js} +10 -10
  41. package/dist/cli/{index-yt3vz0e1.js → index-mpytsq6k.js} +2 -2
  42. package/dist/cli/{index-rs1f1bh0.js → index-mrpfd1jx.js} +1 -1
  43. package/dist/cli/{index-0tevsq1a.js → index-pp5m7xga.js} +2 -2
  44. package/dist/cli/{index-b9rd29ge.js → index-rrb6cz2f.js} +1 -1
  45. package/dist/cli/{index-adyxbmt5.js → index-ryq97w1x.js} +2 -2
  46. package/dist/cli/{index-y98ngs4g.js → index-s8g7jh1k.js} +2 -2
  47. package/dist/cli/{index-bmmzfrc7.js → index-tj04dj06.js} +5 -2
  48. package/dist/cli/{index-z6md3t8m.js → index-v1an91bq.js} +54 -19
  49. package/dist/cli/{index-898f16j9.js → index-v3x7j9ey.js} +2 -2
  50. package/dist/cli/{index-7ax0bkqh.js → index-v3xhc7kg.js} +1 -1
  51. package/dist/cli/{index-325zmfyj.js → index-vrmkg8fm.js} +46 -15
  52. package/dist/cli/{index-yyyk63kk.js → index-w4etfamq.js} +2 -2
  53. package/dist/cli/{index-kbfsp07d.js → index-wk8s1m7b.js} +2 -2
  54. package/dist/cli/{index-x6mtyj6q.js → index-ysa38bnr.js} +2 -2
  55. package/dist/cli/index.js +28 -28
  56. package/dist/cli/{knowledge-escalator-58tw74js.js → knowledge-escalator-gdjnwszd.js} +19 -7
  57. package/dist/cli/{knowledge-events-knr0pfq4.js → knowledge-events-581x4q7n.js} +18 -5
  58. package/dist/cli/{knowledge-link-q46k9adx.js → knowledge-link-axx45d1h.js} +4 -4
  59. package/dist/cli/{knowledge-store-e2srcd89.js → knowledge-store-ttg33482.js} +5 -5
  60. package/dist/cli/{knowledge-validator-1dtj02q8.js → knowledge-validator-8kywqt8b.js} +7 -8
  61. package/dist/cli/{pending-delegations-qzrx38y9.js → pending-delegations-btwqsvz4.js} +3 -3
  62. package/dist/cli/{pr-subscriptions-5s59h4dd.js → pr-subscriptions-83y1cdwv.js} +3 -3
  63. package/dist/cli/{runner-y78d7ryb.js → runner-fh3r41nw.js} +5 -5
  64. package/dist/cli/{scan-cursor-7tqsvbp8.js → scan-cursor-j8ytdpam.js} +6 -6
  65. package/dist/cli/{schema-b046zss2.js → schema-6xfqtpvn.js} +2 -2
  66. package/dist/cli/{scope-persistence-dr1msqxw.js → scope-persistence-8c72jrgp.js} +4 -4
  67. package/dist/cli/{skill-generator-bvph9d98.js → skill-generator-n8vm1yhn.js} +18 -9
  68. package/dist/cli/{telemetry-sc57xtb0.js → telemetry-fb44gpba.js} +1 -1
  69. package/dist/cli/{worktree-collision-ownership-7a8e6gr9.js → worktree-collision-ownership-f28r473k.js} +3 -3
  70. package/dist/commands/ci-simulate.d.ts +7 -3
  71. package/dist/commands/close.d.ts +8 -0
  72. package/dist/commands/registry.d.ts +2 -2
  73. package/dist/commands/sdd.d.ts +15 -0
  74. package/dist/config/bundled-skills.d.ts +1 -1
  75. package/dist/config/schema.d.ts +2 -0
  76. package/dist/git/branch.d.ts +1 -1
  77. package/dist/hooks/compaction-customizer.d.ts +8 -0
  78. package/dist/hooks/delegate-ack-collector.d.ts +5 -0
  79. package/dist/hooks/hive-promoter.d.ts +4 -4
  80. package/dist/hooks/issue-trace-reducer.d.ts +7 -1
  81. package/dist/hooks/issue-trace-state.d.ts +18 -0
  82. package/dist/hooks/issue-trace.d.ts +3 -1
  83. package/dist/hooks/knowledge-application-gate.d.ts +8 -3
  84. package/dist/hooks/knowledge-application.d.ts +8 -5
  85. package/dist/hooks/knowledge-escalator.d.ts +9 -5
  86. package/dist/hooks/knowledge-events.d.ts +21 -8
  87. package/dist/hooks/knowledge-injector.d.ts +9 -0
  88. package/dist/hooks/knowledge-receipt-ledger-storage.d.ts +49 -0
  89. package/dist/hooks/knowledge-receipt-ledger.d.ts +305 -0
  90. package/dist/hooks/knowledge-receipt-observability.d.ts +28 -0
  91. package/dist/hooks/knowledge-receipt-validator.d.ts +13 -50
  92. package/dist/hooks/knowledge-store.d.ts +6 -1
  93. package/dist/hooks/knowledge-types.d.ts +12 -0
  94. package/dist/hooks/phase-complete-directive-gate.d.ts +3 -1
  95. package/dist/hooks/phase-directives.d.ts +4 -4
  96. package/dist/hooks/pr-workflow-gate.d.ts +34 -1
  97. package/dist/hooks/promotion-evidence-store.d.ts +14 -8
  98. package/dist/hooks/reviewer-verdict-parser.d.ts +34 -10
  99. package/dist/index.js +551 -532
  100. package/dist/knowledge/curation-policy.d.ts +0 -2
  101. package/dist/observability/catalog.d.ts +5 -3
  102. package/dist/observability/legacy.d.ts +4 -3
  103. package/dist/telemetry.d.ts +1 -1
  104. package/dist/tools/index.d.ts +3 -0
  105. package/dist/tools/manifest.d.ts +3 -0
  106. package/dist/tools/phase-complete.d.ts +9 -0
  107. package/dist/tools/rebind-pr-feedback-head.d.ts +17 -0
  108. package/dist/tools/record-implementation-review.d.ts +19 -0
  109. package/dist/tools/record-recurrence-sweep.d.ts +17 -0
  110. package/dist/tools/run-pr-feedback-stage-a.d.ts +8 -0
  111. package/dist/tools/tool-metadata.d.ts +12 -0
  112. package/package.json +3 -1
  113. package/dist/cli/index-jfp1bgt1.js +0 -666
@@ -0,0 +1,49 @@
1
+ import * as fs from 'node:fs';
2
+ import { lstat, realpath } from 'node:fs/promises';
3
+ export declare const RECEIPT_SCHEMA_VERSION = 2;
4
+ export declare const RECEIPT_CUTOVER_VERSION = 1;
5
+ export interface ReceiptLedgerPaths {
6
+ root: string;
7
+ swarmDir: string;
8
+ journal: string;
9
+ snapshot: string;
10
+ archive: string;
11
+ quarantine: string;
12
+ lockTarget: string;
13
+ legacyEvents: string;
14
+ legacyBaseline: string;
15
+ linkPointer: string;
16
+ }
17
+ export type ReceiptStoreErrorCode = 'lock_timeout' | 'store_unavailable' | 'store_corrupt';
18
+ export declare class ReceiptStoreError extends Error {
19
+ readonly code: ReceiptStoreErrorCode;
20
+ constructor(code: ReceiptStoreErrorCode, message: string);
21
+ }
22
+ export declare function resolveReceiptLedgerPaths(directory: string): ReceiptLedgerPaths;
23
+ interface MutationParentDependencies {
24
+ lstat: typeof lstat;
25
+ realpath: typeof realpath;
26
+ }
27
+ declare function validateMutationParent(filePath: string, dependencies?: MutationParentDependencies): Promise<string>;
28
+ declare function readLinuxProcStat(pid: number, signal: AbortSignal): Promise<string>;
29
+ declare function isProcessAlive(pid: number): Promise<boolean>;
30
+ declare function recoverLockIfSafe(paths: ReceiptLedgerPaths): Promise<void>;
31
+ export declare function withReceiptLedgerLock<T>(directory: string, action: (paths: ReceiptLedgerPaths) => Promise<T>): Promise<T>;
32
+ export declare function receiptRecordHash(value: unknown): string;
33
+ export declare function readUtf8IfPresent(filePath: string, maxBytes?: number): Promise<string | null>;
34
+ export declare function appendFsynced(filePath: string, line: string): Promise<void>;
35
+ export declare function atomicWriteFsynced(targetPath: string, content: string): Promise<void>;
36
+ export declare function fileMtimeMs(filePath: string): Promise<number | null>;
37
+ export declare const _internals: {
38
+ platform: () => NodeJS.Platform;
39
+ killProcess: (pid: number) => void;
40
+ readLinuxProcStat: typeof readLinuxProcStat;
41
+ procStateReadTimeoutMs: number;
42
+ isProcessAlive: typeof isProcessAlive;
43
+ rename: typeof fs.promises.rename;
44
+ rm: typeof fs.promises.rm;
45
+ afterRecoveryRename: (_paths: ReceiptLedgerPaths, _claimedPath: string) => Promise<void>;
46
+ recoverLockIfSafe: typeof recoverLockIfSafe;
47
+ validateMutationParent: typeof validateMutationParent;
48
+ };
49
+ export {};
@@ -0,0 +1,305 @@
1
+ import { atomicWriteFsynced, type ReceiptLedgerPaths, type ReceiptStoreErrorCode } from './knowledge-receipt-ledger-storage.js';
2
+ import { type KnowledgeReceiptTransitionObservation } from './knowledge-receipt-observability.js';
3
+ export type ReceiptOutcome = 'applied' | 'ignored' | 'contradicted' | 'violated' | 'n_a';
4
+ export interface ReceiptPredicateCheck {
5
+ predicate: string;
6
+ result: 'pass' | 'fail' | 'error';
7
+ detail: string;
8
+ }
9
+ export interface ReceiptTerminal {
10
+ outcome: ReceiptOutcome;
11
+ source: string;
12
+ reason?: string;
13
+ predicate_check?: ReceiptPredicateCheck;
14
+ event_id: string;
15
+ committed_at: string;
16
+ authorized_transition?: {
17
+ actor: 'manual-override' | 'reviewer-remediation' | 'phase-override';
18
+ reason: string;
19
+ previous_event_id: string;
20
+ previous_outcome?: ReceiptOutcome;
21
+ };
22
+ }
23
+ export interface ReceiptApplicationMarker {
24
+ outcome: ReceiptOutcome;
25
+ source: string;
26
+ reason?: string;
27
+ event_id: string;
28
+ committed_at: string;
29
+ }
30
+ export interface ReceiptMembership {
31
+ trace_id: string;
32
+ entry_id: string;
33
+ session_id: string;
34
+ phase?: string;
35
+ task_id?: string;
36
+ agent?: string;
37
+ critical: boolean;
38
+ rank?: number;
39
+ score?: number;
40
+ committed_at: string;
41
+ membership_event_id: string;
42
+ grace_days: number;
43
+ phase_close_intent_at?: string;
44
+ phase_closed_at?: string;
45
+ terminal?: ReceiptTerminal;
46
+ /** Append-only audited terminal transitions; `terminal` is the current gate state. */
47
+ terminal_history?: ReceiptTerminal[];
48
+ application_marker?: ReceiptApplicationMarker;
49
+ cohort_id?: string;
50
+ source_link_id?: string;
51
+ exposure_kind: ReceiptExposureKind;
52
+ origin: 'v2' | 'legacy';
53
+ }
54
+ export type ReceiptExposureKind = 'architect_directive' | 'delegate_directive' | 'manual_recall' | 'legacy_unknown';
55
+ interface EmptyTrace {
56
+ trace_id: string;
57
+ session_id: string;
58
+ phase?: string;
59
+ task_id?: string;
60
+ committed_at: string;
61
+ empty_event_id: string;
62
+ grace_days: number;
63
+ phase_close_intent_at?: string;
64
+ phase_closed_at?: string;
65
+ terminal_event_id?: string;
66
+ }
67
+ interface PhaseLifecycle {
68
+ phase: string;
69
+ session_id: string;
70
+ task_id?: string;
71
+ intent_event_id?: string;
72
+ intent_at?: string;
73
+ closed_event_id?: string;
74
+ closed_at?: string;
75
+ }
76
+ interface ReceiptAuditSummary {
77
+ original_seq: number;
78
+ original_hash: string;
79
+ event_id: string;
80
+ timestamp: string;
81
+ kind: ReceiptTransitionKind;
82
+ trace_id?: string;
83
+ phase?: string;
84
+ entry_ids?: string[];
85
+ reason_codes?: string[];
86
+ }
87
+ export type ReceiptTransitionKind = 'membership_committed' | 'empty_retrieval_committed' | 'terminal_committed' | 'terminal_attempt_rejected' | 'terminal_attempt_idempotent' | 'authorized_transition_committed' | 'application_marker_committed' | 'phase_close_intent' | 'phase_closed' | 'legacy_imported' | 'legacy_unverifiable' | 'cutover_completed' | 'checkpoint';
88
+ interface LedgerState {
89
+ memberships: Map<string, ReceiptMembership>;
90
+ traceIds: Set<string>;
91
+ emptyTraces: Map<string, EmptyTrace>;
92
+ cutoverCompleted: boolean;
93
+ legacyUnverifiable: boolean;
94
+ legacyTraceRegistry: Set<string>;
95
+ legacyUnverifiableTraceIds: Set<string>;
96
+ phaseLifecycle: Map<string, PhaseLifecycle>;
97
+ auditTail: ReceiptAuditSummary[];
98
+ lastSeq: number;
99
+ lastHash: string;
100
+ recordCount: number;
101
+ observations: KnowledgeReceiptTransitionObservation[];
102
+ }
103
+ export type ReceiptUnavailable = {
104
+ ok: false;
105
+ code: ReceiptStoreErrorCode | 'legacy_unverifiable';
106
+ detail: string;
107
+ /** Compatibility alias for hook responses that surface typed uncertainty. */
108
+ uncertainty: string;
109
+ };
110
+ export type ReceiptLedgerResult<T> = ({
111
+ ok: true;
112
+ } & T) | ReceiptUnavailable;
113
+ declare function writeSnapshot(paths: ReceiptLedgerPaths, state: LedgerState): Promise<void>;
114
+ export interface CommitDisplayedMembershipInput {
115
+ trace_id: string;
116
+ session_id: string;
117
+ phase?: string;
118
+ task_id?: string;
119
+ agent?: string;
120
+ entries: Array<{
121
+ entry_id: string;
122
+ critical: boolean;
123
+ rank?: number;
124
+ score?: number;
125
+ }>;
126
+ grace_days?: number;
127
+ cohort_id?: string;
128
+ source_link_id?: string;
129
+ /** Producer provenance used by application gates; omitted callers fail closed. */
130
+ exposure_kind?: ReceiptExposureKind;
131
+ }
132
+ export declare function commitDisplayedMembership(directory: string, input: CommitDisplayedMembershipInput): Promise<ReceiptLedgerResult<{
133
+ event_id: string;
134
+ memberships: ReceiptMembership[];
135
+ }>>;
136
+ export declare function commitEmptyRetrieval(directory: string, input: Omit<CommitDisplayedMembershipInput, 'entries'>): Promise<ReceiptLedgerResult<{
137
+ event_id: string;
138
+ terminal_event_id: string;
139
+ }>>;
140
+ export interface TerminalBatchInput {
141
+ trace_id: string;
142
+ session_id: string;
143
+ phase?: string;
144
+ task_id?: string;
145
+ agent?: string;
146
+ cohort_id?: string;
147
+ source_link_id?: string;
148
+ grace_days?: number;
149
+ items?: Array<{
150
+ entry_id: string;
151
+ outcome: ReceiptOutcome;
152
+ source?: string;
153
+ reason?: string;
154
+ predicate_check?: ReceiptPredicateCheck;
155
+ event_id?: string;
156
+ }>;
157
+ /** Alias used by reviewer/delegate batch producers. */
158
+ terminals?: Array<{
159
+ entry_id: string;
160
+ outcome: ReceiptOutcome;
161
+ source?: string;
162
+ reason?: string;
163
+ predicate_check?: ReceiptPredicateCheck;
164
+ event_id?: string;
165
+ }>;
166
+ no_relevant_knowledge?: boolean;
167
+ authorization?: {
168
+ actor: 'manual-override' | 'reviewer-remediation' | 'phase-override';
169
+ reason: string;
170
+ expected_event_id: string;
171
+ expected_outcome?: ReceiptOutcome;
172
+ };
173
+ }
174
+ export declare function validateAndCommitTerminalBatch(directory: string, input: TerminalBatchInput): Promise<ReceiptLedgerResult<{
175
+ accepted: Array<{
176
+ entry_id: string;
177
+ outcome: ReceiptOutcome;
178
+ event_id: string;
179
+ }>;
180
+ committed: Array<{
181
+ entry_id: string;
182
+ outcome: ReceiptOutcome;
183
+ event_id: string;
184
+ }>;
185
+ idempotent: string[];
186
+ idempotent_events: Array<{
187
+ entry_id: string;
188
+ outcome: ReceiptOutcome;
189
+ event_id: string;
190
+ }>;
191
+ rejected: Array<{
192
+ entry_id: string;
193
+ reason: string;
194
+ }>;
195
+ closes_no_relevant: boolean;
196
+ terminal_event_id?: string;
197
+ }>>;
198
+ interface ApplicationMarkerBatchInput {
199
+ trace_id: string;
200
+ session_id: string;
201
+ items?: Array<{
202
+ entry_id: string;
203
+ outcome: ReceiptOutcome;
204
+ source?: string;
205
+ reason?: string;
206
+ }>;
207
+ markers?: Array<{
208
+ entry_id: string;
209
+ outcome: ReceiptOutcome;
210
+ source?: string;
211
+ reason?: string;
212
+ }>;
213
+ }
214
+ declare function commitApplicationMarkerBatch(directory: string, input: ApplicationMarkerBatchInput): Promise<ReceiptLedgerResult<{
215
+ committed: Array<{
216
+ entry_id: string;
217
+ outcome: ReceiptOutcome;
218
+ event_id: string;
219
+ }>;
220
+ idempotent: string[];
221
+ rejected: Array<{
222
+ entry_id: string;
223
+ reason: string;
224
+ }>;
225
+ }>>;
226
+ export interface ApplicationOutcomeBatchInput {
227
+ trace_id: string;
228
+ session_id: string;
229
+ grace_days?: number;
230
+ items: Array<{
231
+ entry_id: string;
232
+ outcome: ReceiptOutcome;
233
+ source?: string;
234
+ reason?: string;
235
+ }>;
236
+ }
237
+ /**
238
+ * Atomically commit the architect application marker and its receipt terminal.
239
+ * Each exact pair is validated before either state projection is staged, so a
240
+ * terminal conflict can never leave a marker behind. Existing same-outcome
241
+ * state is preserved and any missing half is repaired in the same journal row.
242
+ */
243
+ export declare function commitApplicationOutcomeBatch(directory: string, input: ApplicationOutcomeBatchInput): Promise<ReceiptLedgerResult<{
244
+ committed: Array<{
245
+ entry_id: string;
246
+ outcome: ReceiptOutcome;
247
+ marker_event_id: string;
248
+ terminal_event_id: string;
249
+ }>;
250
+ idempotent: Array<{
251
+ entry_id: string;
252
+ outcome: ReceiptOutcome;
253
+ marker_event_id: string;
254
+ terminal_event_id: string;
255
+ }>;
256
+ rejected: Array<{
257
+ entry_id: string;
258
+ reason: string;
259
+ }>;
260
+ }>>;
261
+ export declare function queryLiveMemberships(directory: string, filters?: {
262
+ phase?: string;
263
+ task_id?: string;
264
+ session_id?: string;
265
+ include_terminal?: boolean;
266
+ include_phase_closed?: boolean;
267
+ exposure_kind?: ReceiptExposureKind;
268
+ grace_days?: number;
269
+ }): Promise<ReceiptLedgerResult<{
270
+ memberships: ReceiptMembership[];
271
+ }>>;
272
+ export declare function queryHistoricalOutcomes(directory: string, entryIds?: string[], graceDays?: number): Promise<ReceiptLedgerResult<{
273
+ memberships: ReceiptMembership[];
274
+ }>>;
275
+ /**
276
+ * Compact the authoritative receipt journal under its dedicated lock.
277
+ * Read-only queries intentionally never rewrite receipt state, so maintenance
278
+ * callers and focused recovery tests use this explicit mutation boundary.
279
+ */
280
+ export declare function compactKnowledgeReceiptLedger(directory: string): Promise<ReceiptLedgerResult<{
281
+ compacted: true;
282
+ }>>;
283
+ export declare const recordPhaseCloseIntent: (directory: string, phase: string, sessionId?: string, taskId?: string) => Promise<ReceiptLedgerResult<{
284
+ event_id: string;
285
+ }>>;
286
+ export declare const commitPhaseClosed: (directory: string, phase: string, sessionId?: string, taskId?: string) => Promise<ReceiptLedgerResult<{
287
+ event_id: string;
288
+ }>>;
289
+ export declare function reconcilePhaseClose(directory: string, phase: string, durablePlanClosed: boolean, sessionId?: string, taskId?: string): Promise<ReceiptLedgerResult<{
290
+ reconciled: boolean;
291
+ }>>;
292
+ export declare function ensureLegacyCutover(directory: string, graceDays?: number): Promise<ReceiptLedgerResult<{
293
+ completed: true;
294
+ }>>;
295
+ export declare const _internals: {
296
+ nowMs: () => number;
297
+ writeSnapshot: typeof writeSnapshot;
298
+ atomicWriteFsynced: typeof atomicWriteFsynced;
299
+ /** Test-only migration fixture for pre-atomic marker-only state. */
300
+ commitApplicationMarkerBatch: typeof commitApplicationMarkerBatch;
301
+ maxJournalRecords: number;
302
+ maxArchiveRecords: number;
303
+ maxArchiveBytes: number;
304
+ };
305
+ export {};
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Best-effort observability projection for authoritative receipt transitions.
3
+ * The V2 journal remains authoritative; telemetry runs best-effort after commit.
4
+ */
5
+ import { emit } from '../telemetry.js';
6
+ import type { ReceiptOutcome } from './knowledge-receipt-validator.js';
7
+ export type KnowledgeReceiptObservedTransition = 'membership_committed' | 'empty_retrieval_committed' | 'terminal_committed' | 'terminal_attempt_rejected' | 'terminal_attempt_idempotent' | 'authorized_transition_committed' | 'application_marker_committed' | 'phase_close_intent' | 'phase_closed' | 'legacy_imported' | 'legacy_unverifiable' | 'cutover_completed' | 'checkpoint';
8
+ export type KnowledgeReceiptObservationReasonCode = 'committed' | 'idempotent' | 'trace_not_found' | 'id_not_in_trace' | 'wrong_session' | 'wrong_phase' | 'wrong_task' | 'duplicate_conflicting_terminal' | 'event_id_conflict' | 'invalid_outcome' | 'empty_receipt' | 'lock_timeout' | 'store_unavailable' | 'store_corrupt' | 'legacy_unverifiable' | 'unauthorized_transition';
9
+ export interface KnowledgeReceiptTransitionObservation {
10
+ transition: KnowledgeReceiptObservedTransition;
11
+ reasonCode: KnowledgeReceiptObservationReasonCode;
12
+ schemaVersion: number;
13
+ knowledgeTraceId?: string;
14
+ knowledgeEntryId?: string;
15
+ sessionId?: string;
16
+ taskId?: string;
17
+ phase?: string;
18
+ /** Domain value only; never projected to the generic observability outcome. */
19
+ receiptOutcome?: ReceiptOutcome;
20
+ /** Bounded domain code only; arbitrary prose is deliberately rejected. */
21
+ receiptSource?: string;
22
+ }
23
+ /** Emit bounded diagnostics fail-open after an authoritative transition. */
24
+ export declare function emitKnowledgeReceiptTransition(observation: KnowledgeReceiptTransitionObservation): void;
25
+ /** Dependency seam for focused fail-open tests. */
26
+ export declare const _internals: {
27
+ emit: typeof emit;
28
+ };
@@ -1,29 +1,13 @@
1
1
  /**
2
- * Shared receipt validator (issue #1849).
2
+ * Shared V2 receipt validator and atomic terminal committer (issue #2031).
3
3
  *
4
- * One validator that enforces the terminal-receipt contract for BOTH the
5
- * `knowledge_receipt` tool AND the `delegate-ack-collector`. Reads the
6
- * authoritative event log and rejects forged / expired / conflicting /
7
- * non-trace receipts while keeping idempotent retries free of double-counting.
8
- *
9
- * Authority contract (per issue #1849 §3):
10
- * - trace/result delivery proves shown/retrieved only;
11
- * - a validated terminal receipt is the durable audit outcome;
12
- * - applied counters derive ONLY from validated `applied` receipts;
13
- * - ignored/contradicted/no_relevant remain visible but are not application credit.
14
- *
15
- * Uniqueness grain: ONE terminal per (trace_id, knowledge_id). A trace surfaces a
16
- * set of entries; for each entry at most one terminal outcome is accepted.
17
- * Idempotent retry of the SAME outcome is accepted (not re-emitted, not
18
- * double-counted); a DIFFERENT outcome for the same (trace_id, knowledge_id)
19
- * is a conflicting-terminal rejection. The delegate ack path legitimately
20
- * emits multiple terminals per trace (one per shown directive) — that is fine
21
- * because each directive has a distinct knowledge_id.
4
+ * Both the knowledge_receipt tool and delegate/reviewer collectors use this
5
+ * adapter. Correctness is fail-closed: membership validation, idempotency and
6
+ * terminal commit occur under the dedicated receipt-ledger lock before any
7
+ * diagnostic or promotion projection is written.
22
8
  */
23
- import { type KnowledgeEvent, type RetrievedEvent } from './knowledge-events.js';
24
- /** Terminal outcomes the validator accepts. */
9
+ import type { KnowledgeEvent, RetrievedEvent } from './knowledge-events.js';
25
10
  export type ReceiptOutcome = 'applied' | 'ignored' | 'contradicted' | 'violated' | 'n_a' | 'no_relevant';
26
- /** A single item being filed in a receipt. */
27
11
  export interface ReceiptItem {
28
12
  id: string;
29
13
  outcome: Exclude<ReceiptOutcome, 'no_relevant'>;
@@ -31,31 +15,26 @@ export interface ReceiptItem {
31
15
  }
32
16
  export interface ReceiptValidationContext {
33
17
  directory: string;
34
- /** The retrieval trace this receipt accounts for, or `'none'`. */
35
18
  trace_id: string;
36
19
  session_id: string;
37
20
  task_id?: string;
38
21
  phase?: string;
39
22
  agent: string;
23
+ cohort_id?: string;
24
+ source_link_id?: string;
25
+ grace_days?: number;
40
26
  items: ReceiptItem[];
41
- /** True when the receipt asserts nothing relevant was surfaced. */
42
27
  no_relevant_knowledge: boolean;
43
28
  }
44
- export type ReceiptRejectReason = 'trace_not_found' | 'id_not_in_trace' | 'wrong_session' | 'expired' | 'duplicate_conflicting_terminal' | 'invalid_outcome' | 'empty_receipt';
29
+ export type ReceiptRejectReason = 'trace_not_found' | 'id_not_in_trace' | 'wrong_session' | 'wrong_phase' | 'wrong_task' | 'expired' | 'duplicate_conflicting_terminal' | 'invalid_outcome' | 'empty_receipt' | 'lock_timeout' | 'store_unavailable' | 'store_corrupt' | 'legacy_unverifiable';
45
30
  export type ReceiptValidationResult = {
46
31
  ok: true;
47
- /** Items that should be freshly emitted (excludes idempotent skips). */
48
32
  accepted: ReceiptItem[];
49
- /** Items already recorded with the same outcome — skip emitting. */
50
33
  idempotent_skips: ReceiptItem[];
51
- /** The matched retrieval trace, or null for the real-empty (`'none'`) path. */
52
34
  trace: RetrievedEvent | null;
53
- /** True when this receipt closes the loop with a `no_relevant` terminal. */
54
35
  closes_no_relevant: boolean;
55
- /**
56
- * Per-item rejections when SOME items were accepted but others were not
57
- * (id_not_in_trace / conflicting). Present only when non-empty.
58
- */
36
+ authoritative_event_ids: Record<string, string>;
37
+ no_relevant_event_id?: string;
59
38
  rejected_items?: Array<{
60
39
  item: ReceiptItem;
61
40
  reason: ReceiptRejectReason;
@@ -65,31 +44,15 @@ export type ReceiptValidationResult = {
65
44
  rejected: true;
66
45
  reason: ReceiptRejectReason;
67
46
  detail: string;
68
- /** Items rejected by per-item checks (id_not_in_trace / conflicting). */
69
47
  rejected_items?: Array<{
70
48
  item: ReceiptItem;
71
49
  reason: ReceiptRejectReason;
72
50
  }>;
73
51
  };
74
- /**
75
- * Receipt validity window. A receipt must be filed within this many
76
- * milliseconds of the retrieval trace's timestamp. Generous constant (30 min)
77
- * covers slow agents. NOTE: this is a compile-time constant, NOT configurable
78
- * via the config schema — raise an issue if runtime configurability is needed.
79
- */
80
- export declare const RECEIPT_VALIDITY_MS: number;
81
- /** The `trace_id` sentinel meaning "no retrieval occurred". */
82
52
  export declare const NO_TRACE_SENTINEL = "none";
83
- /**
84
- * Validate a receipt against the authoritative event log. Never throws — any
85
- * internal error fails open by accepting the items (the agent's work must not
86
- * be blocked by a validator crash). Rejections are AUDITED by the caller via
87
- * the returned reason; the validator itself does not write audit events to
88
- * keep it side-effect-free and testable.
89
- */
90
53
  export declare function validateReceipt(ctx: ReceiptValidationContext): Promise<ReceiptValidationResult>;
91
54
  declare function findTrace(events: KnowledgeEvent[], traceId: string): RetrievedEvent | null;
92
- declare function isTerminalReceipt(e: KnowledgeEvent): boolean;
55
+ declare function isTerminalReceipt(event: KnowledgeEvent): boolean;
93
56
  export declare const _internals: {
94
57
  findTrace: typeof findTrace;
95
58
  isTerminalReceipt: typeof isTerminalReceipt;
@@ -173,7 +173,12 @@ export declare function inferTags(lesson: string): string[];
173
173
  export declare function bumpKnowledgeConfidenceBatch(directory: string, deltas: Array<{
174
174
  id: string;
175
175
  delta: number;
176
- }>, options?: ConfidenceFloorOptions): Promise<void>;
176
+ receipt_events?: Array<{
177
+ event_id: string;
178
+ timestamp: string;
179
+ outcome: 'applied' | 'violated' | 'ignored';
180
+ }>;
181
+ }>, options?: ConfidenceFloorOptions): Promise<number>;
177
182
  /** Options for the G2 confidence-floor action in bumpKnowledgeConfidenceBatch. */
178
183
  export interface ConfidenceFloorOptions {
179
184
  /** Action when a just-bumped entry sits at the confidence floor with a
@@ -262,6 +262,16 @@ export interface KnowledgeEntryBase extends ActionableDirectiveFields {
262
262
  * (rewrite/demote/confidence-delta). Prevents compounding under concurrent
263
263
  * cohort postmortems that claim the same batch. */
264
264
  last_curated_generation?: number;
265
+ /**
266
+ * Exact-once checkpoint for receipt-driven confidence feedback. Stored in the
267
+ * same atomic knowledge-entry rewrite as the confidence delta so a crash
268
+ * before the external projection cursor is written cannot apply the same V2
269
+ * terminal twice.
270
+ */
271
+ receipt_feedback_cursors?: Record<string, {
272
+ timestamp: string;
273
+ event_id: string;
274
+ }>;
265
275
  }
266
276
  /**
267
277
  * Current knowledge schema marker. v1 entries are still parseable and
@@ -454,6 +464,8 @@ export interface KnowledgeConfig {
454
464
  max_encounter_score: number;
455
465
  /** Default N-phase TTL for knowledge entries. Default: 10 */
456
466
  default_max_phases: number;
467
+ /** Days to retain closed authoritative receipt state before archival. Default: 7 */
468
+ receipt_close_grace_days: number;
457
469
  /** N-phase TTL for 'todo' category entries. Default: 3 */
458
470
  todo_max_phases: number;
459
471
  /** Enable age-based sweep of knowledge entries. Default: true */
@@ -21,6 +21,7 @@ export interface DirectiveGateResult {
21
21
  blocked: boolean;
22
22
  unresolved: Array<{
23
23
  id: string;
24
+ trace_id?: string;
24
25
  reason: DirectiveBlockReason;
25
26
  }>;
26
27
  overridden: string[];
@@ -32,6 +33,7 @@ export interface DirectiveGateResult {
32
33
  */
33
34
  export declare function evaluatePhaseCriticalDirectives(params: {
34
35
  directory: string;
36
+ sessionId?: string;
35
37
  phaseLabel?: string;
36
38
  acceptViolations?: string[];
37
39
  }): Promise<DirectiveGateResult>;
@@ -39,6 +41,6 @@ export declare function evaluatePhaseCriticalDirectives(params: {
39
41
  * Record an architect override for accepted critical violations. Each accepted
40
42
  * id is logged as an `override` event with the written justification.
41
43
  */
42
- export declare function recordDirectiveOverrides(directory: string, ids: string[], justification: string, sessionId: string | undefined): Promise<void>;
44
+ export declare function recordDirectiveOverrides(directory: string, ids: string[], justification: string, sessionId: string | undefined, phaseLabel?: string): Promise<void>;
43
45
  /** Build a structured, human-readable block message for unresolved criticals. */
44
46
  export declare function formatDirectiveBlockMessage(unresolved: DirectiveGateResult['unresolved']): string;
@@ -6,15 +6,15 @@
6
6
  * reviewer must verify) and the phase-complete gate (Task 2.4 — which CRITICAL
7
7
  * IDs must reach a terminal outcome before the phase advances).
8
8
  *
9
- * The window is defined by the retrieval event's `phase` label: every
10
- * `retrieved` event (auto_injection AND delegate_inject) carries the plan phase
11
- * label, so a single equality filter gives a consistent set across consumers.
9
+ * The window is defined by each authoritative receipt membership's `phase`
10
+ * label. Legacy retrieval events are imported by the V2 ledger at cutover, so a
11
+ * single equality filter gives a consistent set across consumers.
12
12
  * Passing an empty/undefined phase collects directives across all phases (used
13
13
  * only as a permissive fallback).
14
14
  */
15
15
  import type { DirectiveToVerify } from '../agents/reviewer-directive-compliance.js';
16
16
  import type { KnowledgeEntryBase } from './knowledge-types.js';
17
- /** Collect the directive IDs surfaced by `retrieved` events in the phase window. */
17
+ /** Collect unique entry IDs from authoritative memberships in the phase window. */
18
18
  export declare function collectPhaseDirectiveIds(directory: string, phaseLabel?: string): Promise<string[]>;
19
19
  /** Load all knowledge entries (swarm + hive) indexed by id. */
20
20
  export declare function readEntriesById(directory: string): Promise<Map<string, KnowledgeEntryBase>>;
@@ -165,6 +165,8 @@ export interface PrFeedbackStageACheckReceipt {
165
165
  feedbackItemId: string;
166
166
  target: string;
167
167
  expectedBehavior: string;
168
+ /** Typed proof kind (issue #2131 criterion C4); optional for records persisted before it existed. */
169
+ proofKind?: string;
168
170
  }>;
169
171
  durationMs: number;
170
172
  }
@@ -201,7 +203,7 @@ interface PrFeedbackReadyToPublishRecord {
201
203
  remoteRef: string;
202
204
  validatedAt: string;
203
205
  }
204
- export type PrWorkflowCompletionStatus = 'completed' | 'ready-to-publish';
206
+ export type PrWorkflowCompletionStatus = 'completed' | 'ready-to-publish' | 'verified-no-change';
205
207
  export type PrReviewValidationPhase = 'council' | 'reviewer' | 'critic';
206
208
  export type PrReviewArtifactBoundary = 'post_explorer' | 'post_reviewer' | 'post_critic';
207
209
  type PrReviewArtifactRecord = {
@@ -340,6 +342,14 @@ export interface PrWorkflowGateState {
340
342
  prFeedbackStageA?: PrFeedbackStageARecord;
341
343
  prFeedbackGateBatches?: PrFeedbackGateBatchRecord[];
342
344
  prFeedbackReadyToPublish?: PrFeedbackReadyToPublishRecord;
345
+ /**
346
+ * Issue #2131 criterion C2: count of controlled base-sync/rebind transitions.
347
+ * Each rebind moves the immutable intake head to a new verified remote PR
348
+ * head after merge/rebase/conflict repair and invalidates every
349
+ * ancestry-bound receipt (Stage A, verification, gate batches) so the full
350
+ * mechanical ladder re-runs on the new ancestry.
351
+ */
352
+ prFeedbackRebindCount?: number;
343
353
  prFeedbackScopes?: PrFeedbackScopeDeclarationRecord[];
344
354
  }
345
355
  export declare function activatePrWorkflow(directory: string, sessionID: string, mode: PrWorkflowMode, options?: {
@@ -407,6 +417,29 @@ export declare function abortPrWorkflow(directory: string, sessionID: string, op
407
417
  }>;
408
418
  /** Bind an active PR workflow to one immutable PR head. */
409
419
  export declare function bindPrWorkflowHead(directory: string, sessionID: string, prHeadSha: string): Promise<PrWorkflowGateState>;
420
+ /**
421
+ * Controlled base-sync/rebind transition for PR_FEEDBACK (issue #2131
422
+ * criterion C2). After a merge/rebase used to resolve base drift or conflicts,
423
+ * the local history is no longer a direct child of the original intake head and
424
+ * the ordinary publication path can never be satisfied. Instead of an ad-hoc
425
+ * abort, this transition moves the immutable intake head to a NEW verified
426
+ * remote PR head and invalidates every ancestry-bound receipt (Stage A,
427
+ * verification batches, ordered gates), forcing the full mechanical ladder to
428
+ * re-run against the new ancestry.
429
+ *
430
+ * Fail-closed semantics:
431
+ * 1. Only an active PR_FEEDBACK gate bound to a head may rebind.
432
+ * 2. Refuses while publication is armed — an armed gate must complete (the
433
+ * immutable-commit binding must not be dropped silently).
434
+ * 3. Refuses while PR workflow lanes are in flight.
435
+ * 4. The new head must differ from the current intake head (a no-op rebind
436
+ * would silently launder receipts).
437
+ * 5. The current checkout must equal the new head, and the PR-feedback
438
+ * tracking-checkout discipline is re-asserted for it.
439
+ * 6. The immutable feedback inventory is preserved (item ownership
440
+ * continuity); only ancestry-bound receipts are invalidated.
441
+ */
442
+ export declare function rebindPrFeedbackHead(directory: string, sessionID: string, prHeadSha: string): Promise<PrWorkflowGateState>;
410
443
  /** Bind an active PR_REVIEW workflow to one immutable merge-base scope. */
411
444
  export declare function bindPrReviewBase(directory: string, sessionID: string, options: {
412
445
  prHeadSha: string;