opencode-swarm 7.155.0 → 7.157.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 (91) hide show
  1. package/dist/background/workspace-snapshot.d.ts +28 -0
  2. package/dist/cli/{coder-settlement-2kdtysrg.js → coder-settlement-dz2x352d.js} +9 -9
  3. package/dist/cli/{config-doctor-s6p9aqfv.js → config-doctor-4jxf9w9e.js} +3 -3
  4. package/dist/cli/{core-ev2ebc4v.js → core-xf2f087t.js} +2 -2
  5. package/dist/cli/{curation-policy-jabphe51.js → curation-policy-72qx868r.js} +4 -4
  6. package/dist/cli/{curator-llm-factory-kd8v16jj.js → curator-llm-factory-7mfvey3x.js} +31 -31
  7. package/dist/cli/{curator-adp0dsv4.js → curator-pjjw3ja4.js} +31 -31
  8. package/dist/cli/{dispatch-w0rzasz3.js → dispatch-7r46tfr9.js} +10 -8
  9. package/dist/cli/{evidence-summary-service-kpjpd86j.js → evidence-summary-service-5ffkbs50.js} +12 -12
  10. package/dist/cli/{gate-evidence-etbcms2v.js → gate-evidence-ne9rbdtb.js} +5 -5
  11. package/dist/cli/guardrail-explain-b9vr4ta3.js +67 -0
  12. package/dist/cli/{guardrail-log-614g1pta.js → guardrail-log-hrt36jz5.js} +5 -5
  13. package/dist/cli/{guardrail-reset-0wdj53cp.js → guardrail-reset-pggm9hx4.js} +31 -31
  14. package/dist/cli/{hashing-mjwn6j4y.js → hashing-r4hbav6j.js} +1 -1
  15. package/dist/cli/{hive-promoter-b1wv52fs.js → hive-promoter-7vxm11sm.js} +31 -31
  16. package/dist/cli/{index-caqe8x14.js → index-12e2hztp.js} +1 -1
  17. package/dist/cli/{index-rb4t72we.js → index-1dzy1j4v.js} +2 -2
  18. package/dist/cli/{index-79qymsxf.js → index-2e60kmzg.js} +1 -1
  19. package/dist/cli/{index-vnn7qq8c.js → index-3f7hqtgg.js} +62 -1
  20. package/dist/cli/{index-qzqpq75z.js → index-3qpr16k2.js} +52 -33
  21. package/dist/cli/{index-qj9jrjvr.js → index-3vqdt1sx.js} +5 -5
  22. package/dist/cli/{index-c590qxts.js → index-4kd1nqd2.js} +8 -3
  23. package/dist/cli/{index-34wn2ztk.js → index-4w20thrc.js} +22 -4
  24. package/dist/cli/{index-26cvxrym.js → index-61nkp124.js} +2 -2
  25. package/dist/cli/{index-6bqqzfbe.js → index-6sbx96v6.js} +2 -2
  26. package/dist/cli/{index-zvp68qx6.js → index-79k7p589.js} +1 -1
  27. package/dist/cli/{index-ketfp4rv.js → index-8n602qc2.js} +4 -4
  28. package/dist/cli/{index-fjcm6wwf.js → index-91ybfvy2.js} +1 -1
  29. package/dist/cli/{index-wwv3cbv1.js → index-93ymj3j5.js} +5 -5
  30. package/dist/cli/{index-myt57pht.js → index-9r7gp6cp.js} +5 -1
  31. package/dist/cli/{index-85p1850w.js → index-b5xm177r.js} +1 -1
  32. package/dist/cli/{index-0q8kywcf.js → index-dwkrdpz2.js} +1 -1
  33. package/dist/cli/{index-veajr5x7.js → index-ebratyzr.js} +1 -1
  34. package/dist/cli/{index-kgdbtwfm.js → index-g0j2hnse.js} +5 -5
  35. package/dist/cli/{index-2gfe61qp.js → index-gk6wpq41.js} +5259 -1394
  36. package/dist/cli/{index-aqg7c1z9.js → index-gpf3cjre.js} +1 -1
  37. package/dist/cli/{index-ctsct3hy.js → index-j3egsxa1.js} +6 -6
  38. package/dist/cli/{index-xn23xnnk.js → index-n6ayyadp.js} +4 -4
  39. package/dist/cli/{index-t3xqpece.js → index-n7gv8m7v.js} +4 -4
  40. package/dist/cli/{index-mm7ase9k.js → index-nd22bsnt.js} +6 -2
  41. package/dist/cli/{index-c9nabqzd.js → index-ngn6jmad.js} +2 -2
  42. package/dist/cli/{index-xdy28ngt.js → index-nwkr6tvv.js} +17 -1
  43. package/dist/cli/{index-spbxf9vn.js → index-p0by16z8.js} +2 -2
  44. package/dist/cli/{index-dw2q720x.js → index-q94gt4n9.js} +3 -3
  45. package/dist/cli/{index-kyc2c7hq.js → index-t0kxka8n.js} +2 -2
  46. package/dist/cli/{index-e90g4dsw.js → index-tvtvhjh0.js} +4 -4
  47. package/dist/cli/{index-y8552snf.js → index-txdagbh7.js} +6 -1
  48. package/dist/cli/{index-egnpzfe3.js → index-vbqssmbs.js} +6 -6
  49. package/dist/cli/{index-ew6fykvv.js → index-xe6zbfps.js} +1 -1
  50. package/dist/cli/{index-x9tbe9v7.js → index-zq7pw6qg.js} +2 -2
  51. package/dist/cli/index.js +31 -31
  52. package/dist/cli/{knowledge-escalator-z09aqvfe.js → knowledge-escalator-d65mctqy.js} +10 -10
  53. package/dist/cli/{knowledge-events-03f1rwm8.js → knowledge-events-6aet71sp.js} +8 -8
  54. package/dist/cli/{knowledge-link-4frk38w8.js → knowledge-link-z9cchqdj.js} +3 -3
  55. package/dist/cli/{knowledge-store-sn28k13f.js → knowledge-store-vvgxbakx.js} +4 -4
  56. package/dist/cli/{knowledge-validator-rwrt3yja.js → knowledge-validator-4fb6pbpn.js} +6 -6
  57. package/dist/cli/{model-preflight-b95w8wxy.js → model-preflight-cv9kvw8h.js} +1 -1
  58. package/dist/cli/{pending-delegations-qe16vfrj.js → pending-delegations-f52jtanf.js} +1 -1
  59. package/dist/cli/{pr-subscriptions-00evnffe.js → pr-subscriptions-76vg2xya.js} +2 -2
  60. package/dist/cli/{runner-k1rkbjm8.js → runner-eagt6gf8.js} +5 -5
  61. package/dist/cli/{scan-cursor-h3mfzjc9.js → scan-cursor-q3530gc8.js} +5 -5
  62. package/dist/cli/{schema-c37h5xw4.js → schema-5zc62306.js} +6 -2
  63. package/dist/cli/{scope-persistence-35z42pj5.js → scope-persistence-fzqf115q.js} +7 -7
  64. package/dist/cli/{skill-generator-60px2mvb.js → skill-generator-kh1z90tm.js} +12 -12
  65. package/dist/cli/{workspace-snapshot-8269e1p9.js → workspace-snapshot-yq0tc49d.js} +9 -1
  66. package/dist/cli/{worktree-collision-ownership-2pc20ypq.js → worktree-collision-ownership-2qxjtxt6.js} +3 -3
  67. package/dist/cli/{worktree-isolation-w4yamc3b.js → worktree-isolation-40v34p0s.js} +31 -31
  68. package/dist/commands/command-dispatch.d.ts +2 -1
  69. package/dist/commands/harness.d.ts +14 -0
  70. package/dist/commands/index.d.ts +3 -1
  71. package/dist/commands/registry.d.ts +115 -2
  72. package/dist/config/schema.d.ts +34 -0
  73. package/dist/harness/contracts.d.ts +492 -0
  74. package/dist/harness/factory.d.ts +72 -0
  75. package/dist/harness/hash.d.ts +4 -0
  76. package/dist/harness/index.d.ts +6 -0
  77. package/dist/harness/patch.d.ts +3 -0
  78. package/dist/harness/public-api.d.ts +105 -0
  79. package/dist/harness/source-candidate.d.ts +45 -0
  80. package/dist/harness/store.d.ts +256 -0
  81. package/dist/hooks/pr-workflow-gate.d.ts +291 -3
  82. package/dist/index.d.ts +2 -0
  83. package/dist/index.js +320 -296
  84. package/dist/lang/manifest-files.d.ts +25 -0
  85. package/dist/security/write-authority.d.ts +2 -1
  86. package/dist/tools/index.d.ts +1 -0
  87. package/dist/tools/invalidate-pr-feedback-publication.d.ts +20 -0
  88. package/dist/tools/manifest.d.ts +1 -0
  89. package/dist/tools/tool-metadata.d.ts +4 -0
  90. package/package.json +1 -1
  91. package/dist/cli/guardrail-explain-wqb5h7kk.js +0 -67
@@ -0,0 +1,45 @@
1
+ import { lstatSync } from 'node:fs';
2
+ import type { HarnessEvolutionConfig } from '../config/schema.js';
3
+ import { type HarnessCandidateFileV1, type HarnessCandidateManifestV1 } from './contracts.js';
4
+ export type HarnessSourceCandidateFileV1 = HarnessCandidateFileV1;
5
+ export type HarnessSourceCandidateV1 = HarnessCandidateManifestV1 & {
6
+ /** Inert evidence only. No production API applies this patch. */
7
+ patch?: string;
8
+ };
9
+ type ValidationFailureCode = 'ALLOWLIST_EMPTY' | 'INVALID_BASE_SHA' | 'STALE_BASE' | 'PATCH_TOO_LARGE' | 'UNSUPPORTED_PATCH' | 'PATH_REJECTED' | 'PATH_NOT_ALLOWLISTED' | 'PROTECTED_PATH' | 'GIT_FAILED' | 'UNTRACKED_PATH' | 'UNSUPPORTED_TRACKED_MODE' | 'SYMLINK_PATH' | 'HARDLINK_PATH' | 'BINARY_FILE' | 'FILE_TOO_LARGE' | 'TOTAL_TOO_LARGE' | 'FILE_COUNT_EXCEEDED' | 'LINE_COUNT_EXCEEDED' | 'PATH_CHANGED_DURING_VALIDATION' | 'PATCH_DOES_NOT_APPLY';
10
+ export type SourceCandidateValidationResult = {
11
+ ok: true;
12
+ candidate: HarnessSourceCandidateV1;
13
+ } | {
14
+ ok: false;
15
+ code: ValidationFailureCode;
16
+ reason: string;
17
+ };
18
+ interface GitCommandResult {
19
+ ok: boolean;
20
+ code: number;
21
+ stdout: string;
22
+ stderr: string;
23
+ }
24
+ interface GitBinaryCommandResult {
25
+ ok: boolean;
26
+ code: number;
27
+ stdout: Uint8Array;
28
+ stderr: string;
29
+ }
30
+ export declare function validateSourceCandidate(args: {
31
+ directory: string;
32
+ config: HarnessEvolutionConfig;
33
+ candidateId: string;
34
+ baseSha: string;
35
+ origin: string;
36
+ patch: string;
37
+ }): Promise<SourceCandidateValidationResult>;
38
+ declare function runGitCommand(directory: string, args: string[]): Promise<GitCommandResult>;
39
+ declare function runGitBinaryCommand(directory: string, args: string[], maxOutputBytes?: number): Promise<GitBinaryCommandResult>;
40
+ export declare const _internals: {
41
+ runGitCommand: typeof runGitCommand;
42
+ runGitBinaryCommand: typeof runGitBinaryCommand;
43
+ lstatSync: typeof lstatSync;
44
+ };
45
+ export {};
@@ -0,0 +1,256 @@
1
+ import { type WriteApprovalRequest } from '../security/write-authority.js';
2
+ import { type BlueprintPatchV1, type HarnessBlueprintV1, type PromptArtifactV1 } from './contracts.js';
3
+ import type { HarnessSourceCandidateV1 } from './source-candidate.js';
4
+ type RetainedCandidateBinding = {
5
+ candidateId: string;
6
+ manifestHash: string;
7
+ };
8
+ export interface StoredHarnessCandidateV1 {
9
+ v: 1;
10
+ candidate: HarnessSourceCandidateV1;
11
+ promptArtifacts?: PromptArtifactV1[];
12
+ baseBlueprint?: HarnessBlueprintV1;
13
+ targetBlueprint?: HarnessBlueprintV1;
14
+ blueprintPatch?: BlueprintPatchV1;
15
+ recordedAt: string;
16
+ }
17
+ export interface HarnessVersionV1 {
18
+ v: 1;
19
+ versionId: string;
20
+ candidateId: string;
21
+ manifestHash: string;
22
+ allowedPathDigest: string;
23
+ generation: number;
24
+ sourceKind: 'activation' | 'rollback';
25
+ parentVersionId: string | null;
26
+ restoredFromVersionId: string | null;
27
+ approvalFactId: string;
28
+ blueprint?: HarnessBlueprintV1;
29
+ recordedAt: string;
30
+ }
31
+ export interface HarnessCurrentProjectionV1 {
32
+ v: 1;
33
+ currentVersionId: string | null;
34
+ currentCandidateId: string | null;
35
+ currentManifestHash: string | null;
36
+ currentHash: string;
37
+ generation: number;
38
+ versionIds: string[];
39
+ updatedAt: string;
40
+ ledgerHeadSegment: string | null;
41
+ ledgerHeadSeq: number;
42
+ ledgerHeadHash: string;
43
+ }
44
+ export interface HarnessLedgerRecordV1 {
45
+ v: 1;
46
+ seq: number;
47
+ timestamp: string;
48
+ kind: 'candidate_recorded' | 'activated' | 'rolled_back' | 'recovered_tail' | 'compacted';
49
+ candidateId: string;
50
+ versionId: string | null;
51
+ parentVersionId: string | null;
52
+ restoredFromVersionId: string | null;
53
+ approvalFactId: string | null;
54
+ payloadHash: string;
55
+ generation: number;
56
+ currentHashBefore: string;
57
+ currentHashAfter: string;
58
+ nextCurrentVersionId: string | null;
59
+ nextCurrentCandidateId: string | null;
60
+ nextCurrentManifestHash: string | null;
61
+ nextVersionIds: string[];
62
+ nextUpdatedAt: string;
63
+ ledgerSegment: string;
64
+ prunedVersionIds: string[];
65
+ recoverySegment: string | null;
66
+ recoveredBytes: number | null;
67
+ retainedCandidates: RetainedCandidateBinding[];
68
+ compactedRecords: number | null;
69
+ hashBefore: string;
70
+ hashAfter: string;
71
+ }
72
+ export type RecordHarnessCandidateResult = {
73
+ status: 'recorded';
74
+ candidate: StoredHarnessCandidateV1;
75
+ retentionReconciled: boolean;
76
+ retentionFailures: string[];
77
+ } | {
78
+ status: 'conflict';
79
+ reason: string;
80
+ };
81
+ export type ActivateHarnessCandidateResult = {
82
+ status: 'activated';
83
+ version: HarnessVersionV1;
84
+ current: HarnessCurrentProjectionV1;
85
+ projectionReconciled: boolean;
86
+ prunedArtifactsReconciled: boolean;
87
+ prunedArtifactFailures: string[];
88
+ retentionReconciled: boolean;
89
+ retentionFailures: string[];
90
+ } | {
91
+ status: 'candidate_not_found';
92
+ reason: string;
93
+ } | {
94
+ status: 'candidate_not_activatable';
95
+ reason: string;
96
+ } | {
97
+ status: 'consumer_mismatch';
98
+ reason: string;
99
+ } | {
100
+ status: 'approval_required';
101
+ reason: string;
102
+ } | {
103
+ status: 'retention_conflict';
104
+ reason: string;
105
+ maxVersions: number;
106
+ requiredVersionIds: string[];
107
+ } | {
108
+ status: 'stale_current';
109
+ reason: string;
110
+ };
111
+ export type RollbackHarnessVersionResult = {
112
+ status: 'rolled_back';
113
+ version: HarnessVersionV1;
114
+ current: HarnessCurrentProjectionV1;
115
+ projectionReconciled: boolean;
116
+ prunedArtifactsReconciled: boolean;
117
+ prunedArtifactFailures: string[];
118
+ retentionReconciled: boolean;
119
+ retentionFailures: string[];
120
+ } | {
121
+ status: 'version_not_found';
122
+ reason: string;
123
+ } | {
124
+ status: 'consumer_mismatch';
125
+ reason: string;
126
+ } | {
127
+ status: 'approval_required';
128
+ reason: string;
129
+ } | {
130
+ status: 'retention_conflict';
131
+ reason: string;
132
+ maxVersions: number;
133
+ requiredVersionIds: string[];
134
+ } | {
135
+ status: 'stale_current';
136
+ reason: string;
137
+ };
138
+ export type SaveHarnessVersionResult = {
139
+ status: 'saved';
140
+ version: HarnessVersionV1;
141
+ } | {
142
+ status: 'conflict';
143
+ reason: string;
144
+ };
145
+ export interface HarnessHistoryResult {
146
+ records: HarnessLedgerRecordV1[];
147
+ truncated: boolean;
148
+ quarantinePath: string | null;
149
+ totalRecordCount: number;
150
+ limit: number;
151
+ totalSegments: number;
152
+ }
153
+ export type HarnessLedgerAuditResult = {
154
+ outcome: 'ok';
155
+ records: HarnessLedgerRecordV1[];
156
+ truncated: boolean;
157
+ quarantinePath: string | null;
158
+ totalSegments: number;
159
+ } | {
160
+ outcome: 'scope_exceeded';
161
+ maxSegments: number;
162
+ totalSegments: number;
163
+ replayBoundExceeded?: true;
164
+ maxReplayRecords?: number;
165
+ };
166
+ export declare class HarnessStoreIntegrityError extends Error {
167
+ readonly artifactPath: string;
168
+ readonly code = "HARNESS_STORE_INTEGRITY";
169
+ constructor(artifactPath: string, message: string);
170
+ }
171
+ export declare class HarnessReplayBoundExceededError extends Error {
172
+ readonly maxReplayRecords: number;
173
+ readonly code = "HARNESS_REPLAY_BOUND_EXCEEDED";
174
+ constructor(maxReplayRecords: number);
175
+ }
176
+ declare function appendLedgerLine(directory: string, line: string, expectedSegmentName?: string): void;
177
+ declare function removeVersionArtifact(filePath: string): void;
178
+ declare function writeCurrentProjection(directory: string, current: HarnessCurrentProjectionV1): Promise<void>;
179
+ declare function removeCandidateArtifact(directory: string): void;
180
+ declare function removeLedgerArtifact(target: string): void;
181
+ export declare function buildHarnessActivationApprovalRequest(args: {
182
+ targetSessionId: string;
183
+ candidate: StoredHarnessCandidateV1;
184
+ expectedCurrentHash: string | null;
185
+ expectedCurrentGeneration: number;
186
+ targetContentHash: string;
187
+ allowedPathDigest: string;
188
+ }): WriteApprovalRequest;
189
+ export declare function buildHarnessRollbackApprovalRequest(args: {
190
+ targetSessionId: string;
191
+ currentVersionId: string;
192
+ targetVersionId: string;
193
+ expectedCurrentHash: string;
194
+ expectedCurrentGeneration: number;
195
+ targetContentHash: string;
196
+ allowedPathDigest: string;
197
+ }): WriteApprovalRequest;
198
+ export declare function recordHarnessCandidate(args: {
199
+ directory: string;
200
+ candidate: StoredHarnessCandidateV1;
201
+ maxReplayRecords?: number;
202
+ maxInactiveCandidates?: number;
203
+ }): Promise<RecordHarnessCandidateResult>;
204
+ export declare function saveHarnessVersion(args: {
205
+ directory: string;
206
+ version: HarnessVersionV1;
207
+ }): Promise<SaveHarnessVersionResult>;
208
+ export declare function loadHarnessCurrent(directory: string, maxReplayRecords?: number): Promise<HarnessCurrentProjectionV1>;
209
+ /** Explicitly reconcile the derived projection; read paths never mutate state. */
210
+ export declare function reconcileHarnessCurrent(directory: string, maxReplayRecords?: number): Promise<HarnessCurrentProjectionV1>;
211
+ export declare function loadHarnessCandidate(directory: string, candidateId: string, maxReplayRecords?: number): Promise<StoredHarnessCandidateV1 | null>;
212
+ export declare function loadHarnessPromptArtifact(directory: string, candidateId: string, promptHash: string): PromptArtifactV1 | null;
213
+ export declare function loadHarnessVersion(directory: string, versionId: string): Promise<HarnessVersionV1 | null>;
214
+ export declare function listHarnessHistory(directory: string, options?: number | {
215
+ maxReplayRecords?: number;
216
+ limit?: number;
217
+ }): Promise<HarnessHistoryResult>;
218
+ export declare function auditHarnessLedger(directory: string, options: {
219
+ maxReplayRecords?: number;
220
+ maxSegments: number;
221
+ }): Promise<HarnessLedgerAuditResult>;
222
+ export declare function recoverHarnessCorruptTail(directory: string, maxReplayRecords?: number): Promise<HarnessHistoryResult>;
223
+ export declare function activateHarnessCandidate(args: {
224
+ directory: string;
225
+ candidateId: string;
226
+ consumerSessionId: string;
227
+ targetSessionId?: string;
228
+ expectedCurrentHash: string | null;
229
+ expectedCurrentGeneration: number;
230
+ targetContentHash: string;
231
+ allowedPathDigest: string;
232
+ maxVersions?: number;
233
+ maxReplayRecords?: number;
234
+ maxInactiveCandidates?: number;
235
+ }): Promise<ActivateHarnessCandidateResult>;
236
+ export declare function rollbackHarnessVersion(args: {
237
+ directory: string;
238
+ targetVersionId: string;
239
+ consumerSessionId: string;
240
+ targetSessionId?: string;
241
+ expectedCurrentHash: string;
242
+ expectedCurrentGeneration: number;
243
+ targetContentHash: string;
244
+ allowedPathDigest: string;
245
+ maxVersions?: number;
246
+ maxReplayRecords?: number;
247
+ maxInactiveCandidates?: number;
248
+ }): Promise<RollbackHarnessVersionResult>;
249
+ export declare const _storeInternals: {
250
+ appendLedgerLine: typeof appendLedgerLine;
251
+ writeCurrentProjection: typeof writeCurrentProjection;
252
+ removeVersionArtifact: typeof removeVersionArtifact;
253
+ removeCandidateArtifact: typeof removeCandidateArtifact;
254
+ removeLedgerArtifact: typeof removeLedgerArtifact;
255
+ };
256
+ export {};
@@ -4,7 +4,7 @@ import { type CandidateSeverity, type FindingsSeverity, type RowFormatFamily } f
4
4
  import { type LaneOutputArtifact } from '../background/lane-output-store.js';
5
5
  import { type BackgroundDelegationRecord, type BackgroundDelegationResult, type BackgroundDelegationWorkflowLaneFailureClass, type BackgroundDelegationWorkflowLaneRecovery, findByBatchId, sweepStaleDelegations } from '../background/pending-delegations.js';
6
6
  import { type PrReviewInlineTriggerRow } from '../background/pr-review-trigger-contract.js';
7
- import { type RevisionDigestResult, resolveCommitCountSince, resolveCommitCountSinceAsync, resolveCurrentGitHead, resolveCurrentGitHeadAsync, resolveCurrentUpstreamPushTarget, resolveCurrentUpstreamPushTargetAsync, resolveCurrentUpstreamRemoteRef, resolveExactRemoteBranchHead, resolveExactRemoteBranchHeadAsync, resolveIsExactSingleChildCommit, resolveIsExactSingleChildCommitAsync, resolveIsWorkingTreeClean, resolveIsWorkingTreeCleanAsync, resolvePrReviewDiffStats, resolvePrReviewDiffStatsAsync, resolvePrWorkflowRevisionDigest, resolvePrWorkflowRevisionDigestDetailed, resolveRemoteRefsContainingHead, resolveRemoteRefsContainingHeadAsync } from '../background/workspace-snapshot.js';
7
+ import { type RevisionDigestResult, resolveCommitCountSince, resolveCommitCountSinceAsync, resolveCurrentGitHead, resolveCurrentGitHeadAsync, resolveCurrentLocalHeadRefAsync, resolveCurrentUpstreamPushTarget, resolveCurrentUpstreamPushTargetAsync, resolveCurrentUpstreamRemoteRef, resolveExactRemoteBranchHead, resolveExactRemoteBranchHeadAsync, resolveIsExactSingleChildCommit, resolveIsExactSingleChildCommitAsync, resolveIsWorkingTreeClean, resolveIsWorkingTreeCleanAsync, resolvePrReviewDiffStats, resolvePrReviewDiffStatsAsync, resolvePrWorkflowRevisionDigest, resolvePrWorkflowRevisionDigestDetailed, resolveRemoteRefsContainingHead, resolveRemoteRefsContainingHeadAsync, resolveRemoteUrlIdentity, resolveRemoteUrlIdentityAsync } from '../background/workspace-snapshot.js';
8
8
  import { type PrReviewResilienceConfig } from '../config/schema.js';
9
9
  import { classifyPrWorkflowGitState, type PrWorkflowGitState } from '../git/pr-workflow-state.js';
10
10
  import { classifyPrReviewCircuitSignal, type PrReviewCircuitLegacyRecord, type PrReviewCircuitRecordV2 } from './pr-review-resilience-circuit.js';
@@ -259,6 +259,94 @@ interface PrFeedbackReadyToPublishRecord {
259
259
  remoteRef: string;
260
260
  validatedAt: string;
261
261
  }
262
+ /**
263
+ * Issue #2108: durable publication-generation state machine. The legacy
264
+ * {@link PrFeedbackReadyToPublishRecord} above becomes a derived mirror that
265
+ * is present exactly while the active generation is `{armed, push_in_flight}`
266
+ * (or a legacy record awaits migration), so a rolled-back binary keeps
267
+ * enforcing the armed window instead of turning permissive.
268
+ */
269
+ export type PrFeedbackPublicationGenerationState = 'reviewing' | 'armed' | 'invalidated' | 'push_in_flight' | 'published' | 'cancelled_without_publication';
270
+ export interface PrFeedbackPublicationEvidenceJoin {
271
+ stageAValidatedAt: string;
272
+ batches: Array<{
273
+ phase: PrFeedbackGatePhase;
274
+ batchId: string;
275
+ laneId: string;
276
+ }>;
277
+ }
278
+ export interface PrFeedbackPublicationGeneration {
279
+ schemaVersion: 1;
280
+ generation: number;
281
+ state: PrFeedbackPublicationGenerationState;
282
+ /** Canonical workspace identity at arming (`canonicalWorkspaceIdentity`). */
283
+ workspaceIdentity: string;
284
+ sessionID: string;
285
+ /** HTTPS PR URL bound at arming (PR identity disclosure), when present. */
286
+ prTargetUrl?: string;
287
+ /** Immutable intake head the approved commit descends from. */
288
+ intakeHeadSha: string;
289
+ /** Local branch ref resolved at arming. */
290
+ localHeadRef: string;
291
+ /** Exact approved local head commit. */
292
+ localHead: string;
293
+ remoteName: string;
294
+ /** Credential-redacted remote URL identity (`git remote get-url`). */
295
+ remoteUrlIdentity?: string;
296
+ remoteBranchRef: string;
297
+ remoteRef: string;
298
+ revisionDigest: string;
299
+ /** The exact receipt set that authorized this generation. */
300
+ evidence: PrFeedbackPublicationEvidenceJoin;
301
+ invalidationReason?: string;
302
+ supersededByGeneration?: number;
303
+ createdAt: string;
304
+ armedAt?: string;
305
+ invalidatedAt?: string;
306
+ publishedAt?: string;
307
+ cancelledAt?: string;
308
+ }
309
+ export type PrFeedbackPushAttemptOutcome = 'completed' | 'rejected' | 'uncertain' | 'cancelled';
310
+ export interface PrFeedbackPushAttempt {
311
+ attemptId: string;
312
+ generation: number;
313
+ sessionID: string;
314
+ callID?: string;
315
+ /** SHA-256 over the canonical intent JSON. */
316
+ intentDigest: string;
317
+ intent: {
318
+ remote: string;
319
+ sourceSha: string;
320
+ destRef: string;
321
+ };
322
+ prePush: {
323
+ localHead: string;
324
+ worktreeClean: boolean;
325
+ remoteName: string;
326
+ remoteBranchRef: string;
327
+ observedRemoteHead: string | null;
328
+ };
329
+ startedAt: string;
330
+ result?: {
331
+ outcome: PrFeedbackPushAttemptOutcome;
332
+ exitStatus: number | 'not-observed';
333
+ /** Bounded (<=500 chars) and secret-redacted. */
334
+ diagnostic: string;
335
+ postPush: {
336
+ localHead: string | null;
337
+ observedRemoteHead: string | null;
338
+ };
339
+ completedAt: string;
340
+ };
341
+ }
342
+ export interface PrFeedbackPublicationState {
343
+ schemaVersion: 1;
344
+ active?: PrFeedbackPublicationGeneration;
345
+ /** Bounded superseded-generation summaries (last 4). */
346
+ history: PrFeedbackPublicationGeneration[];
347
+ /** Bounded attempt records for the active generation (last 8). */
348
+ attempts: PrFeedbackPushAttempt[];
349
+ }
262
350
  export type PrWorkflowCompletionStatus = 'completed' | 'ready-to-publish' | 'verified-no-change';
263
351
  export type PrReviewValidationPhase = 'council' | 'reviewer' | 'critic';
264
352
  export type PrReviewArtifactBoundary = 'post_explorer' | 'post_reviewer' | 'post_critic';
@@ -427,6 +515,13 @@ export interface PrWorkflowGateState {
427
515
  prFeedbackStageA?: PrFeedbackStageARecord;
428
516
  prFeedbackGateBatches?: PrFeedbackGateBatchRecord[];
429
517
  prFeedbackReadyToPublish?: PrFeedbackReadyToPublishRecord;
518
+ /**
519
+ * Issue #2108: audited publication generations + push attempts. The
520
+ * authoritative publication state machine; `prFeedbackReadyToPublish`
521
+ * above is its derived rollback mirror. Optional so pre-#2108 state (and
522
+ * older binaries, via the root `.passthrough()`) loads unchanged.
523
+ */
524
+ prFeedbackPublication?: PrFeedbackPublicationState;
430
525
  /**
431
526
  * Issue #2131 criterion C2: count of controlled base-sync/rebind transitions.
432
527
  * Each rebind moves the immutable intake head to a new verified remote PR
@@ -707,8 +802,18 @@ export declare function settlePresumedStalePrWorkflowLanes(directory: string, se
707
802
  */
708
803
  export declare function abortPrWorkflow(directory: string, sessionID: string, options?: {
709
804
  expectedMode?: PrWorkflowMode;
710
- kind: 'recovery' | 'force';
805
+ kind: 'recovery' | 'force' | 'cancel-publication';
711
806
  reason: string;
807
+ /**
808
+ * Issue #2108: the explicit cancellation-without-publication arm. While
809
+ * an armed/push_in_flight/invalidated publication generation exists,
810
+ * this arm (and ONLY this arm — mutually exclusive with `force`) may
811
+ * clear the workflow: it records the generation as
812
+ * `cancelled_without_publication` with the observed remote head and a
813
+ * REQUIRED reason, and never manufactures push authority. Plain
814
+ * `recovery`/`force` aborts remain refused while armed.
815
+ */
816
+ cancelPublication?: boolean;
712
817
  }): Promise<{
713
818
  mode: PrWorkflowMode;
714
819
  prHeadSha?: string;
@@ -860,6 +965,174 @@ export declare function recordPrFeedbackGateBatch(directory: string, sessionID:
860
965
  export declare function assertPrFeedbackGatePhaseSettled(directory: string, sessionID: string, phase: PrFeedbackGatePhase): Promise<PrWorkflowGateState>;
861
966
  /** Require every ordered feedback gate on one unchanged revision. */
862
967
  export declare function assertPrFeedbackReadyToPublish(directory: string, sessionID: string): Promise<PrWorkflowGateState>;
968
+ /** Build the evidence join for a freshly armed generation. */
969
+ declare function buildPublicationEvidenceJoin(state: PrWorkflowGateState, currentDigest: string): PrFeedbackPublicationEvidenceJoin | null;
970
+ /**
971
+ * Snapshot of the publication container with bounded history trimming.
972
+ * History keeps the last {@link MAX_PUBLICATION_HISTORY_GENERATIONS}
973
+ * superseded generations; attempts belong to the active generation only.
974
+ */
975
+ declare function nextPublicationContainer(previous: PrFeedbackPublicationState | undefined, active: PrFeedbackPublicationGeneration | undefined, historyAppends?: PrFeedbackPublicationGeneration[], attempts?: PrFeedbackPushAttempt[]): PrFeedbackPublicationState;
976
+ /**
977
+ * The audited invalidation transition (issue #2108 §4/§5). Supersedes every
978
+ * content-dependent approval of the active generation — Stage A result,
979
+ * verification batches, ordered-gate batches, scope declarations — by
980
+ * removing them from ACTIVE state (the underlying lane artifacts remain in
981
+ * their own stores; the superseded join is pinned in the generation record),
982
+ * marks the generation `invalidated`, clears the rollback mirror, and appends
983
+ * the audit event. Never deletes the generation itself or its history.
984
+ *
985
+ * `driftReverification` (auto-detected drift) re-proves the drifted component
986
+ * under the session lock before writing, so a TOCTOU between the unlocked
987
+ * snapshot and this write cannot invalidate on stale evidence.
988
+ */
989
+ declare function invalidatePublicationGeneration(directory: string, sessionID: string, reason: string, options?: {
990
+ drift?: {
991
+ component: string;
992
+ detail: string;
993
+ };
994
+ driftReverification?: boolean;
995
+ finalizeInFlightAs?: PrFeedbackPushAttemptOutcome;
996
+ }): Promise<PrWorkflowPublicationTransitionResult>;
997
+ interface PrWorkflowPublicationTransitionResult {
998
+ generation: PrFeedbackPublicationGeneration;
999
+ state: PrWorkflowGateState;
1000
+ }
1001
+ /**
1002
+ * Migrate a legacy armed record (pre-#2108 state) into the generation state
1003
+ * machine, conservatively: every identity component must recompute and match
1004
+ * under the session lock, and the active receipts must be present and bound
1005
+ * to the mirror's digest. Any mismatch or failure persists generation 1 as
1006
+ * `invalidated` with a `legacy-migration-*` reason — never silently armed.
1007
+ * No-op when no legacy record exists (returns the current state unchanged).
1008
+ */
1009
+ declare function ensurePublicationGenerationCurrent(directory: string, sessionID: string): Promise<PrWorkflowGateState | null>;
1010
+ /**
1011
+ * The reaper (issue #2108 §3): finalize any result-less push attempt before
1012
+ * another armed-window interaction proceeds. Recovers restarts and missed
1013
+ * `tool.execute.after` observations as `uncertain` and re-observes the remote
1014
+ * head, so `push_in_flight` can never wedge a generation.
1015
+ */
1016
+ declare function reconcileForeignInFlightAttempt(directory: string, sessionID: string, currentCallId?: string): Promise<PrWorkflowGateState | null>;
1017
+ /**
1018
+ * Controller-facing invalidation/rework transition (issue #2108 §4): the
1019
+ * explicit declaration that approved content must change, which opens the
1020
+ * mutation path by superseding every content-dependent approval of the
1021
+ * current armed generation. Requires a non-empty reason. Refuses when no
1022
+ * live window exists and reports already-invalidated as an informative
1023
+ * diagnostic (idempotent no-op is NOT silently accepted — the caller should
1024
+ * see the current state).
1025
+ */
1026
+ export declare function invalidatePrFeedbackPublication(directory: string, sessionID: string, reason: string): Promise<PrFeedbackPublicationGeneration>;
1027
+ /**
1028
+ * Operator-facing publication summary for `pr_workflow_status` (issue #2108):
1029
+ * generation, state, target, attempts, invalidation reason, and the
1030
+ * state-appropriate recovery instruction. Returns null when the workflow has
1031
+ * no publication state to describe.
1032
+ */
1033
+ export declare function describePrWorkflowPublicationSection(state: PrWorkflowGateState): string | null;
1034
+ /**
1035
+ * Issue #2108 safety boundary — "fail closed on corrupt, MISSING, ambiguous,
1036
+ * copied, cross-workspace, or conflicting generation state" and "a manual
1037
+ * state-file edit … cannot clear the authorization requirement": when the
1038
+ * gate state file for a session is absent (e.g. deleted by hand while a
1039
+ * generation was live) but the retained events window shows a LIVE
1040
+ * publication generation for that session — an `armed` or
1041
+ * `push_attempt_started` event with no later terminal (`published`,
1042
+ * `cancelled`, `invalidated`) — publication-capable commands fail closed
1043
+ * until an audited terminal lands. The events store is the append-only audit
1044
+ * authority the state-file deletion cannot touch; when the trail is empty or
1045
+ * compacted past the event the guard is silent (it never invents a dangling
1046
+ * generation from absent evidence).
1047
+ */
1048
+ export declare function findDanglingLivePublicationGeneration(directory: string, sessionID: string): {
1049
+ generation: number;
1050
+ } | null;
1051
+ /** Typed rejection taxonomy for a standalone `git push` command. */
1052
+ export type ExactPushIntentRejection = 'shell-syntax' | 'token-shape' | 'flag-or-option' | 'credential-bearing-remote' | 'invalid-source-sha' | 'invalid-dest-ref' | 'delete-refspec' | 'wildcard-refspec' | 'remote-mismatch' | 'branch-mismatch' | 'source-mismatch' | 'unbound-target';
1053
+ export interface ExactPushIntent {
1054
+ remote: string;
1055
+ sourceSha: string;
1056
+ destRef: string;
1057
+ }
1058
+ export interface ExactPushIntentParseResult {
1059
+ ok: boolean;
1060
+ intent?: ExactPushIntent;
1061
+ /** SHA-256 over the canonical intent JSON (persisted in attempt records). */
1062
+ digest?: string;
1063
+ reason?: ExactPushIntentRejection;
1064
+ }
1065
+ /**
1066
+ * Fold an audited invalidation into a PENDING single-write state transition
1067
+ * (the Stage A re-record and inventory-amendment disarm sites, issue #2108
1068
+ * R3.3): when the pending state still carries a live publication window, the
1069
+ * generation is marked `invalidated` with the given reason, the rollback
1070
+ * mirror and the remaining ancestry-bound receipts (verifications, gate
1071
+ * batches, scope declarations) are superseded in the SAME atomic write, and
1072
+ * any result-less attempt is finalized `uncertain`. A fresh `prFeedbackStageA`
1073
+ * the pending write itself is recording survives — it is evidence recorded
1074
+ * after the invalidation moment. No-op when no live window exists (the
1075
+ * normal unarmed flow keeps its existing behavior).
1076
+ *
1077
+ * Returns the pending state plus the audit-event payload; the CALLER appends
1078
+ * the event only AFTER its persistState succeeds (PR #2422 review PRR-023:
1079
+ * an event must never claim an invalidation whose state write failed — the
1080
+ * abort path's retraction discipline, applied here at the source).
1081
+ */
1082
+ declare function supersedeLivePublicationInPendingState(pending: PrWorkflowGateState, reason: string): {
1083
+ state: PrWorkflowGateState;
1084
+ invalidationEvent: Record<string, unknown> | null;
1085
+ };
1086
+ /**
1087
+ * Parse a standalone push command into a typed intent BEFORE any shell
1088
+ * execution. The only publish-capable intent is the exact armed tuple —
1089
+ * `git push <remote> <localHead>:refs/heads/<branch>` — with NO flags, NO
1090
+ * extra refspecs, NO wildcard/delete/mirror/tag forms, and NO
1091
+ * credential-bearing remote token. This is a structural refactor of the
1092
+ * previous single-regex defense with the SAME accepted grammar (nothing that
1093
+ * the regex rejected is accepted here); every rejection is now explicit,
1094
+ * typed, and auditable. Remote and branch compare case-SENSITIVELY (git ref
1095
+ * semantics); the source SHA compares exactly, as before.
1096
+ */
1097
+ declare function parseExactBoundPushIntent(command: string, armed: {
1098
+ remoteName: string;
1099
+ remoteBranchRef: string;
1100
+ localHead: string;
1101
+ }): ExactPushIntentParseResult;
1102
+ /**
1103
+ * Durable attempt-start before the exact bound push is permitted to execute
1104
+ * (issue #2108 §3), all under ONE session-lock acquisition: re-verify the
1105
+ * armed identity, observe the remote head, and either (a) record an
1106
+ * attempt whose result is already `completed` because the remote is observed
1107
+ * at the approved head (no-op push; the observation — not an exit code — is
1108
+ * the truth), or (b) persist the attempt-start and move the generation to
1109
+ * `push_in_flight` BEFORE the push can run.
1110
+ */
1111
+ declare function admitPrFeedbackPushAttempt(directory: string, sessionID: string, callID: string | undefined, intent: ExactPushIntent, intentDigest: string): Promise<{
1112
+ kind: 'started' | 'already-published-remotely';
1113
+ }>;
1114
+ /**
1115
+ * Record the result of an admitted push from the `tool.execute.after` chain
1116
+ * (issue #2108 §3). Fail-open by design: a missed observation is recovered by
1117
+ * the reaper as `uncertain`; publication truth always comes from
1118
+ * complete_pr_workflow's direct remote verification, never from an exit code
1119
+ * alone. Exported for the single `tool.execute.after` guard in `src/index.ts`.
1120
+ */
1121
+ export declare function recordPrFeedbackPushAttemptResult(directory: string, input: {
1122
+ sessionID: string;
1123
+ callID?: string;
1124
+ tool: string;
1125
+ }, command: string, output: unknown): Promise<void>;
1126
+ /**
1127
+ * Cancellation without publication (issue #2108 §6): a terminal no-publish
1128
+ * transition. Finalizes any in-flight attempt as `cancelled`, discloses the
1129
+ * observed remote head, marks the generation `cancelled_without_publication`,
1130
+ * appends the audit event, and NEVER manufactures push authority. Used only
1131
+ * by `abortPrWorkflow`'s explicit `cancelPublication` arm. Returns the NEW
1132
+ * state revision when a state write landed (the abort clear must CAS against
1133
+ * it), or null when the generation state was absent/unreadable.
1134
+ */
1135
+ declare function cancelPrFeedbackPublication(directory: string, sessionID: string, reason: string): Promise<number | null>;
863
1136
  export declare function resolvePrReviewWriterRunId(directory: string, sessionID: string, requestedRunId?: string): Promise<string>;
864
1137
  export declare function markPrReviewTriggerEvaluationComplete(directory: string, sessionID: string, runId: string, artifactPath: string): Promise<PrWorkflowGateState>;
865
1138
  /** Freeze one exact inline trigger ledger across every micro dispatch. */
@@ -898,7 +1171,7 @@ export declare function validatePrFeedbackScopeBinding(directory: string, bindin
898
1171
  workflowSessionId?: string;
899
1172
  workflowRevisionDigest?: string;
900
1173
  }): Promise<boolean>;
901
- export declare function enforcePrWorkflowToolBefore(directory: string, sessionID: string, toolName: string, args: Record<string, unknown> | undefined, generatedAgentNames?: readonly string[]): Promise<void>;
1174
+ export declare function enforcePrWorkflowToolBefore(directory: string, sessionID: string, toolName: string, args: Record<string, unknown> | undefined, generatedAgentNames?: readonly string[], callID?: string): Promise<void>;
902
1175
  /** Validate the terminal PR workflow contract before removing its durable gate. */
903
1176
  export declare function completePrWorkflow(directory: string, sessionID: string, expectedMode: PrWorkflowMode, prHeadSha: string): Promise<PrWorkflowCompletionStatus>;
904
1177
  export declare const _test_exports: {
@@ -985,6 +1258,21 @@ export declare const _test_exports: {
985
1258
  resolveCurrentUpstreamPushTarget: typeof resolveCurrentUpstreamPushTarget;
986
1259
  resolveCurrentUpstreamPushTargetAsync: typeof resolveCurrentUpstreamPushTargetAsync;
987
1260
  resolveCurrentUpstreamRemoteRef: typeof resolveCurrentUpstreamRemoteRef;
1261
+ resolveCurrentLocalHeadRefAsync: typeof resolveCurrentLocalHeadRefAsync;
1262
+ resolveRemoteUrlIdentity: typeof resolveRemoteUrlIdentity;
1263
+ resolveRemoteUrlIdentityAsync: typeof resolveRemoteUrlIdentityAsync;
1264
+ parseExactBoundPushIntent: typeof parseExactBoundPushIntent;
1265
+ admitPrFeedbackPushAttempt: typeof admitPrFeedbackPushAttempt;
1266
+ recordPrFeedbackPushAttemptResult: typeof recordPrFeedbackPushAttemptResult;
1267
+ reconcileForeignInFlightAttempt: typeof reconcileForeignInFlightAttempt;
1268
+ ensurePublicationGenerationCurrent: typeof ensurePublicationGenerationCurrent;
1269
+ invalidatePublicationGeneration: typeof invalidatePublicationGeneration;
1270
+ invalidatePrFeedbackPublication: typeof invalidatePrFeedbackPublication;
1271
+ cancelPrFeedbackPublication: typeof cancelPrFeedbackPublication;
1272
+ buildPublicationEvidenceJoin: typeof buildPublicationEvidenceJoin;
1273
+ nextPublicationContainer: typeof nextPublicationContainer;
1274
+ supersedeLivePublicationInPendingState: typeof supersedeLivePublicationInPendingState;
1275
+ describePrWorkflowPublicationSection: typeof describePrWorkflowPublicationSection;
988
1276
  resolveExactRemoteBranchHead: typeof resolveExactRemoteBranchHead;
989
1277
  resolveExactRemoteBranchHeadAsync: typeof resolveExactRemoteBranchHeadAsync;
990
1278
  resolveCommitCountSince: typeof resolveCommitCountSince;
package/dist/index.d.ts CHANGED
@@ -63,3 +63,5 @@ export type { EvaluatePrReviewRecoveryV1Options } from './evaluation/pr-review-r
63
63
  export { evaluatePrReviewRecoveryV1 } from './evaluation/pr-review-recovery.js';
64
64
  export type { EvaluateCandidateV1Options, EvaluateCandidateV1Result, } from './evaluation/public-api.js';
65
65
  export { evaluateCandidateV1, evaluationV1, } from './evaluation/public-api.js';
66
+ export type { AgentBlueprintV1, BlueprintPatchV1, HarnessBlueprintV1, HarnessCandidateManifestV1, OrchestrationSpecV1, PromptArtifactV1, ToolSpecV1, } from './harness/contracts.js';
67
+ export { harnessMutationV1 } from './harness/public-api.js';