opencode-swarm 7.156.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.
- package/dist/background/workspace-snapshot.d.ts +28 -0
- package/dist/cli/{coder-settlement-jm7024zm.js → coder-settlement-dz2x352d.js} +9 -9
- package/dist/cli/{config-doctor-q9v8yscr.js → config-doctor-4jxf9w9e.js} +3 -3
- package/dist/cli/{core-ev3bn503.js → core-xf2f087t.js} +2 -2
- package/dist/cli/{curation-policy-jabphe51.js → curation-policy-72qx868r.js} +4 -4
- package/dist/cli/{curator-llm-factory-cnatbky1.js → curator-llm-factory-7mfvey3x.js} +30 -30
- package/dist/cli/{curator-dnjf9ser.js → curator-pjjw3ja4.js} +30 -30
- package/dist/cli/{evidence-summary-service-5drv65qh.js → evidence-summary-service-5ffkbs50.js} +11 -11
- package/dist/cli/{gate-evidence-dcyvst7g.js → gate-evidence-ne9rbdtb.js} +5 -5
- package/dist/cli/{guardrail-explain-z8f6qhz2.js → guardrail-explain-b9vr4ta3.js} +31 -31
- package/dist/cli/{guardrail-log-zwec6ann.js → guardrail-log-hrt36jz5.js} +5 -5
- package/dist/cli/{guardrail-reset-ga6e11r9.js → guardrail-reset-pggm9hx4.js} +30 -30
- package/dist/cli/{hive-promoter-mpez5tqh.js → hive-promoter-7vxm11sm.js} +30 -30
- package/dist/cli/{index-fpg4tzf7.js → index-12e2hztp.js} +1 -1
- package/dist/cli/{index-sm2t1awr.js → index-1dzy1j4v.js} +2 -2
- package/dist/cli/{index-b91qwpms.js → index-2e60kmzg.js} +1 -1
- package/dist/cli/{index-vnn7qq8c.js → index-3f7hqtgg.js} +62 -1
- package/dist/cli/{index-17h6ewqp.js → index-3qpr16k2.js} +32 -32
- package/dist/cli/{index-98j6z038.js → index-3vqdt1sx.js} +5 -5
- package/dist/cli/{index-wn0xm2e8.js → index-4kd1nqd2.js} +8 -3
- package/dist/cli/{index-5w87j6j4.js → index-4w20thrc.js} +2 -2
- package/dist/cli/{index-5r3zrw81.js → index-61nkp124.js} +2 -2
- package/dist/cli/{index-6bqqzfbe.js → index-6sbx96v6.js} +2 -2
- package/dist/cli/{index-mdypz60w.js → index-79k7p589.js} +1 -1
- package/dist/cli/{index-00hyhg47.js → index-8n602qc2.js} +4 -4
- package/dist/cli/{index-fjcm6wwf.js → index-91ybfvy2.js} +1 -1
- package/dist/cli/{index-q2khkey7.js → index-93ymj3j5.js} +5 -5
- package/dist/cli/{index-myt57pht.js → index-9r7gp6cp.js} +5 -1
- package/dist/cli/{index-85p1850w.js → index-b5xm177r.js} +1 -1
- package/dist/cli/{index-0q8kywcf.js → index-dwkrdpz2.js} +1 -1
- package/dist/cli/{index-g37454vj.js → index-ebratyzr.js} +1 -1
- package/dist/cli/{index-6g6qwr8z.js → index-g0j2hnse.js} +5 -5
- package/dist/cli/{index-ppx8bnzd.js → index-gk6wpq41.js} +1463 -402
- package/dist/cli/{index-aqg7c1z9.js → index-gpf3cjre.js} +1 -1
- package/dist/cli/{index-dfmr6pj5.js → index-j3egsxa1.js} +6 -6
- package/dist/cli/{index-sfdg1xg5.js → index-n6ayyadp.js} +4 -4
- package/dist/cli/{index-fd7wj6fy.js → index-n7gv8m7v.js} +4 -4
- package/dist/cli/{index-68098cfj.js → index-nd22bsnt.js} +2 -2
- package/dist/cli/{index-gthnsbzf.js → index-ngn6jmad.js} +1 -1
- package/dist/cli/{index-xdy28ngt.js → index-nwkr6tvv.js} +17 -1
- package/dist/cli/{index-za6bb2fd.js → index-p0by16z8.js} +2 -2
- package/dist/cli/{index-164c64z8.js → index-q94gt4n9.js} +3 -3
- package/dist/cli/{index-4m3j9q9z.js → index-t0kxka8n.js} +1 -1
- package/dist/cli/{index-9n555qz4.js → index-tvtvhjh0.js} +4 -4
- package/dist/cli/{index-zdgdf0e9.js → index-vbqssmbs.js} +6 -6
- package/dist/cli/{index-ew6fykvv.js → index-xe6zbfps.js} +1 -1
- package/dist/cli/{index-kxk8cnx7.js → index-zq7pw6qg.js} +2 -2
- package/dist/cli/index.js +30 -30
- package/dist/cli/{knowledge-escalator-cq4e6v2j.js → knowledge-escalator-d65mctqy.js} +10 -10
- package/dist/cli/{knowledge-events-sr5fqqaq.js → knowledge-events-6aet71sp.js} +8 -8
- package/dist/cli/{knowledge-link-4frk38w8.js → knowledge-link-z9cchqdj.js} +3 -3
- package/dist/cli/{knowledge-store-2dww3dqz.js → knowledge-store-vvgxbakx.js} +4 -4
- package/dist/cli/{knowledge-validator-yprsj4ye.js → knowledge-validator-4fb6pbpn.js} +6 -6
- package/dist/cli/{model-preflight-b95w8wxy.js → model-preflight-cv9kvw8h.js} +1 -1
- package/dist/cli/{pending-delegations-7qvag076.js → pending-delegations-f52jtanf.js} +1 -1
- package/dist/cli/{pr-subscriptions-00evnffe.js → pr-subscriptions-76vg2xya.js} +2 -2
- package/dist/cli/{runner-gheaxd5r.js → runner-eagt6gf8.js} +4 -4
- package/dist/cli/{scan-cursor-6awybk8b.js → scan-cursor-q3530gc8.js} +5 -5
- package/dist/cli/{schema-bf3smw7k.js → schema-5zc62306.js} +2 -2
- package/dist/cli/{scope-persistence-kc42c6ph.js → scope-persistence-fzqf115q.js} +7 -7
- package/dist/cli/{skill-generator-9k1ztt7c.js → skill-generator-kh1z90tm.js} +12 -12
- package/dist/cli/{workspace-snapshot-8269e1p9.js → workspace-snapshot-yq0tc49d.js} +9 -1
- package/dist/cli/{worktree-collision-ownership-ej10dhwe.js → worktree-collision-ownership-2qxjtxt6.js} +3 -3
- package/dist/cli/{worktree-isolation-r7qqy6ca.js → worktree-isolation-40v34p0s.js} +30 -30
- package/dist/commands/registry.d.ts +1 -1
- package/dist/hooks/pr-workflow-gate.d.ts +291 -3
- package/dist/index.js +72 -70
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/invalidate-pr-feedback-publication.d.ts +20 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/tool-metadata.d.ts +4 -0
- package/package.json +1 -1
|
@@ -6,21 +6,22 @@ import {
|
|
|
6
6
|
resolveExecutableFromPath,
|
|
7
7
|
runEvaluation,
|
|
8
8
|
runExternalTool
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-t0kxka8n.js";
|
|
10
10
|
import {
|
|
11
11
|
finalizeShellAuditForClose,
|
|
12
12
|
isPolicyProtectedPath,
|
|
13
|
+
normalizeToolName,
|
|
13
14
|
normalizeToolNameLowerCase,
|
|
14
15
|
protectedRoots,
|
|
15
16
|
redactDecisionLineForArchive,
|
|
16
17
|
stableCanonicalStringify
|
|
17
|
-
} from "./index-
|
|
18
|
+
} from "./index-4kd1nqd2.js";
|
|
18
19
|
import {
|
|
19
20
|
detectStraySwarmDirs,
|
|
20
21
|
readDoctorArtifact,
|
|
21
22
|
removeStraySwarmDir,
|
|
22
23
|
runConfigDoctor
|
|
23
|
-
} from "./index-
|
|
24
|
+
} from "./index-nd22bsnt.js";
|
|
24
25
|
import {
|
|
25
26
|
MAX_TRANSIENT_RETRIES,
|
|
26
27
|
archiveEvidence,
|
|
@@ -67,7 +68,7 @@ import {
|
|
|
67
68
|
validateProjectRoot,
|
|
68
69
|
validateSymlinkBoundary,
|
|
69
70
|
validateTargetWithinRoot
|
|
70
|
-
} from "./index-
|
|
71
|
+
} from "./index-93ymj3j5.js";
|
|
71
72
|
import {
|
|
72
73
|
EvaluationTaskV1Schema,
|
|
73
74
|
GateAuditManifestV1Schema,
|
|
@@ -84,7 +85,7 @@ import {
|
|
|
84
85
|
saveGateAuditResult,
|
|
85
86
|
savePromotionDecision,
|
|
86
87
|
saveTaskSetSnapshot
|
|
87
|
-
} from "./index-
|
|
88
|
+
} from "./index-ngn6jmad.js";
|
|
88
89
|
import {
|
|
89
90
|
loadDatabaseCtor
|
|
90
91
|
} from "./index-134d35c1.js";
|
|
@@ -110,12 +111,12 @@ import {
|
|
|
110
111
|
} from "./index-txdagbh7.js";
|
|
111
112
|
import {
|
|
112
113
|
readRecentEscalations
|
|
113
|
-
} from "./index-
|
|
114
|
+
} from "./index-g0j2hnse.js";
|
|
114
115
|
import {
|
|
115
116
|
alreadyCuratedThisGeneration,
|
|
116
117
|
claimNextScanBatch,
|
|
117
118
|
resolveCohortId
|
|
118
|
-
} from "./index-
|
|
119
|
+
} from "./index-1dzy1j4v.js";
|
|
119
120
|
import {
|
|
120
121
|
CURATOR_INIT_PROMPT,
|
|
121
122
|
CURATOR_PHASE_PROMPT,
|
|
@@ -139,7 +140,7 @@ import {
|
|
|
139
140
|
listActive,
|
|
140
141
|
subscribe,
|
|
141
142
|
unsubscribe
|
|
142
|
-
} from "./index-
|
|
143
|
+
} from "./index-91ybfvy2.js";
|
|
143
144
|
import {
|
|
144
145
|
clearWorktreeMergeStatus,
|
|
145
146
|
getAllWorktreeMergeFailures,
|
|
@@ -151,12 +152,12 @@ import {
|
|
|
151
152
|
listCoderSettlementWalStates,
|
|
152
153
|
recoverCoderSettlement,
|
|
153
154
|
recoverStaleCoderSettlements
|
|
154
|
-
} from "./index-
|
|
155
|
+
} from "./index-vbqssmbs.js";
|
|
155
156
|
import {
|
|
156
157
|
WORKTREE_LIFECYCLE_LOCK_FILE,
|
|
157
158
|
recordWorktreeProvisioningOwner,
|
|
158
159
|
removeWorktreeProvisioningOwner
|
|
159
|
-
} from "./index-
|
|
160
|
+
} from "./index-dwkrdpz2.js";
|
|
160
161
|
import {
|
|
161
162
|
BUNDLED_PROJECT_SKILL_ROOT,
|
|
162
163
|
DEFAULT_SKILL_MIN_CONFIDENCE,
|
|
@@ -177,7 +178,7 @@ import {
|
|
|
177
178
|
retireSkill,
|
|
178
179
|
selectCandidateEntries,
|
|
179
180
|
syncBundledProjectSkillsIfMissingAsync
|
|
180
|
-
} from "./index-
|
|
181
|
+
} from "./index-n6ayyadp.js";
|
|
181
182
|
import {
|
|
182
183
|
appendUnactionable,
|
|
183
184
|
quarantineEntry,
|
|
@@ -188,11 +189,11 @@ import {
|
|
|
188
189
|
validateActionableFields,
|
|
189
190
|
validateLesson,
|
|
190
191
|
validateSkillPath
|
|
191
|
-
} from "./index-
|
|
192
|
+
} from "./index-tvtvhjh0.js";
|
|
192
193
|
import {
|
|
193
194
|
authorizeCuration,
|
|
194
195
|
buildConfigFingerprintInput
|
|
195
|
-
} from "./index-
|
|
196
|
+
} from "./index-gpf3cjre.js";
|
|
196
197
|
import {
|
|
197
198
|
cohortConfigFingerprint
|
|
198
199
|
} from "./index-rtry5xyf.js";
|
|
@@ -223,12 +224,12 @@ import {
|
|
|
223
224
|
transitionTaskWorkflowEvidence,
|
|
224
225
|
withTaskEvidenceTransaction,
|
|
225
226
|
writeWorkflowWalFile
|
|
226
|
-
} from "./index-
|
|
227
|
+
} from "./index-61nkp124.js";
|
|
227
228
|
import {
|
|
228
229
|
makeWorktreeBranchName,
|
|
229
230
|
provisionWorktree,
|
|
230
231
|
removeWorktree
|
|
231
|
-
} from "./index-
|
|
232
|
+
} from "./index-p0by16z8.js";
|
|
232
233
|
import {
|
|
233
234
|
DEFAULT_STALE_DELEGATION_TIMEOUT_MS,
|
|
234
235
|
DELEGATION_COMPACTION_HIGH_WATER_BYTES,
|
|
@@ -243,7 +244,7 @@ import {
|
|
|
243
244
|
scanBackgroundCoderReservationsForAdmission,
|
|
244
245
|
scanDelegationsForRecovery,
|
|
245
246
|
sweepStaleDelegations
|
|
246
|
-
} from "./index-
|
|
247
|
+
} from "./index-12e2hztp.js";
|
|
247
248
|
import {
|
|
248
249
|
compositeSessionKey,
|
|
249
250
|
sessionKeySuffix
|
|
@@ -254,6 +255,7 @@ import {
|
|
|
254
255
|
resolveCommitCountSinceAsync,
|
|
255
256
|
resolveCurrentGitHead,
|
|
256
257
|
resolveCurrentGitHeadAsync,
|
|
258
|
+
resolveCurrentLocalHeadRefAsync,
|
|
257
259
|
resolveCurrentUpstreamPushTarget,
|
|
258
260
|
resolveCurrentUpstreamPushTargetAsync,
|
|
259
261
|
resolveCurrentUpstreamRemoteRef,
|
|
@@ -271,15 +273,17 @@ import {
|
|
|
271
273
|
resolvePrWorkflowRevisionDigestDetailedAsync,
|
|
272
274
|
resolveRemoteRefsContainingHead,
|
|
273
275
|
resolveRemoteRefsContainingHeadAsync,
|
|
276
|
+
resolveRemoteUrlIdentity,
|
|
277
|
+
resolveRemoteUrlIdentityAsync,
|
|
274
278
|
switchPrFeedbackTrackingCandidateAsync
|
|
275
|
-
} from "./index-
|
|
279
|
+
} from "./index-3f7hqtgg.js";
|
|
276
280
|
import {
|
|
277
281
|
MAX_PENDING_SCOPE_BINDINGS,
|
|
278
282
|
canonicalWorkspaceIdentity,
|
|
279
283
|
clearAllScopes,
|
|
280
284
|
clearScopeBindingFromDisk,
|
|
281
285
|
clearScopeBindings
|
|
282
|
-
} from "./index-
|
|
286
|
+
} from "./index-n7gv8m7v.js";
|
|
283
287
|
import {
|
|
284
288
|
appendLedgerEvent,
|
|
285
289
|
computePlanHash,
|
|
@@ -294,7 +298,7 @@ import {
|
|
|
294
298
|
readPlanEpochIdentity,
|
|
295
299
|
replayFromLedgerWithStatus,
|
|
296
300
|
takeSnapshotEvent
|
|
297
|
-
} from "./index-
|
|
301
|
+
} from "./index-79k7p589.js";
|
|
298
302
|
import {
|
|
299
303
|
CORE_EVENT_LOCKED,
|
|
300
304
|
appendCoreEventSync,
|
|
@@ -304,7 +308,7 @@ import {
|
|
|
304
308
|
hasSpecDriftAuditEvent,
|
|
305
309
|
hasTaskRepairAuditEvent,
|
|
306
310
|
readCoreEvents
|
|
307
|
-
} from "./index-
|
|
311
|
+
} from "./index-nwkr6tvv.js";
|
|
308
312
|
import {
|
|
309
313
|
sanitizeDiagnosticText
|
|
310
314
|
} from "./index-556ja8an.js";
|
|
@@ -353,7 +357,7 @@ import {
|
|
|
353
357
|
transactFile,
|
|
354
358
|
transactKnowledge,
|
|
355
359
|
wordBigrams
|
|
356
|
-
} from "./index-
|
|
360
|
+
} from "./index-j3egsxa1.js";
|
|
357
361
|
import {
|
|
358
362
|
MAX_EVENT_LOG_ENTRIES,
|
|
359
363
|
_internals as _internals2,
|
|
@@ -369,10 +373,10 @@ import {
|
|
|
369
373
|
recordKnowledgeEvent,
|
|
370
374
|
recordPhaseCloseIntent,
|
|
371
375
|
resolveKnowledgeEventsPath
|
|
372
|
-
} from "./index-
|
|
376
|
+
} from "./index-3vqdt1sx.js";
|
|
373
377
|
import {
|
|
374
378
|
resolveWorktreeIsolationConfig
|
|
375
|
-
} from "./index-
|
|
379
|
+
} from "./index-q94gt4n9.js";
|
|
376
380
|
import {
|
|
377
381
|
RetrospectiveEvidenceSchema
|
|
378
382
|
} from "./index-gprxjmm7.js";
|
|
@@ -395,7 +399,7 @@ import {
|
|
|
395
399
|
init_loader,
|
|
396
400
|
loadPluginConfig,
|
|
397
401
|
loadPluginConfigWithMeta
|
|
398
|
-
} from "./index-
|
|
402
|
+
} from "./index-2e60kmzg.js";
|
|
399
403
|
import {
|
|
400
404
|
DEFAULT_HARNESS_EVOLUTION_CONFIG,
|
|
401
405
|
DEFAULT_PR_REVIEW_RESILIENCE_CONFIG,
|
|
@@ -411,7 +415,7 @@ import {
|
|
|
411
415
|
package_default,
|
|
412
416
|
resolveAutoReviewConfig,
|
|
413
417
|
stripKnownSwarmPrefix
|
|
414
|
-
} from "./index-
|
|
418
|
+
} from "./index-4w20thrc.js";
|
|
415
419
|
import {
|
|
416
420
|
AGENT_TOOL_MAP,
|
|
417
421
|
ALL_AGENT_NAMES,
|
|
@@ -425,7 +429,7 @@ import {
|
|
|
425
429
|
init_agent_names,
|
|
426
430
|
init_constants,
|
|
427
431
|
init_tool_metadata
|
|
428
|
-
} from "./index-
|
|
432
|
+
} from "./index-9r7gp6cp.js";
|
|
429
433
|
import {
|
|
430
434
|
init_git_executable,
|
|
431
435
|
resolveGitExecutable,
|
|
@@ -451,10 +455,10 @@ import {
|
|
|
451
455
|
resolveLinkDir,
|
|
452
456
|
sanitizeLinkId,
|
|
453
457
|
writeLinkPointer
|
|
454
|
-
} from "./index-
|
|
458
|
+
} from "./index-b5xm177r.js";
|
|
455
459
|
import {
|
|
456
460
|
atomicWriteFile
|
|
457
|
-
} from "./index-
|
|
461
|
+
} from "./index-xe6zbfps.js";
|
|
458
462
|
import {
|
|
459
463
|
KNOWLEDGE_SCHEMA_VERSION,
|
|
460
464
|
OUTCOME_BLOCK_THRESHOLD,
|
|
@@ -466,7 +470,7 @@ import {
|
|
|
466
470
|
atomicWriteSwarmFileSync,
|
|
467
471
|
matchTempGrammar,
|
|
468
472
|
parseTargetBasename
|
|
469
|
-
} from "./index-
|
|
473
|
+
} from "./index-6sbx96v6.js";
|
|
470
474
|
import {
|
|
471
475
|
assertProjectRoot,
|
|
472
476
|
hasExplicitProjectBoundary,
|
|
@@ -6915,7 +6919,7 @@ async function commitTaskTerminalUnderPlanLock(options) {
|
|
|
6915
6919
|
|
|
6916
6920
|
// src/hooks/pr-workflow-gate.ts
|
|
6917
6921
|
init_zod();
|
|
6918
|
-
import { createHash as
|
|
6922
|
+
import { createHash as createHash7, randomUUID as randomUUID2 } from "crypto";
|
|
6919
6923
|
import { readFileSync as readFileSync5, statSync as statSync5 } from "fs";
|
|
6920
6924
|
import * as fsp2 from "fs/promises";
|
|
6921
6925
|
import * as path12 from "path";
|
|
@@ -9121,6 +9125,108 @@ var _internals15 = {
|
|
|
9121
9125
|
parsePorcelainV2: parsePorcelainV2Snapshot
|
|
9122
9126
|
};
|
|
9123
9127
|
|
|
9128
|
+
// src/memory/redaction.ts
|
|
9129
|
+
import { createHash as createHash6 } from "crypto";
|
|
9130
|
+
var SECRET_PATTERNS = [
|
|
9131
|
+
{ type: "openai_api_key", pattern: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
|
|
9132
|
+
{
|
|
9133
|
+
type: "github_token",
|
|
9134
|
+
pattern: /\b(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}\b/g
|
|
9135
|
+
},
|
|
9136
|
+
{ type: "aws_access_key_id", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
9137
|
+
{
|
|
9138
|
+
type: "private_key_block",
|
|
9139
|
+
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g
|
|
9140
|
+
},
|
|
9141
|
+
{
|
|
9142
|
+
type: "authorization_bearer",
|
|
9143
|
+
pattern: /\bAuthorization\s*:\s*Bearer\s+[A-Za-z0-9._~+/=-]{12,}/gi
|
|
9144
|
+
},
|
|
9145
|
+
{
|
|
9146
|
+
type: "env_secret",
|
|
9147
|
+
pattern: /\b(?:[A-Z][A-Z0-9]+_)+(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi
|
|
9148
|
+
},
|
|
9149
|
+
{ type: "gitlab_token", pattern: /\bgl(?:pat|ptt)-[A-Za-z0-9_-]{15,}\b/g },
|
|
9150
|
+
{ type: "slack_token", pattern: /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g },
|
|
9151
|
+
{
|
|
9152
|
+
type: "jwt_token",
|
|
9153
|
+
pattern: /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g
|
|
9154
|
+
},
|
|
9155
|
+
{
|
|
9156
|
+
type: "aws_secret_access_key",
|
|
9157
|
+
pattern: /\b(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY|secret_access_key|SecretAccessKey)"?\s*[=:]\s*["']?[A-Za-z0-9/+=]{40}\b/g
|
|
9158
|
+
},
|
|
9159
|
+
{
|
|
9160
|
+
type: "aws_secret_access_key_context",
|
|
9161
|
+
pattern: /\bAKIA[0-9A-Z]{16}\b[^\n]{0,200}?\b[A-Za-z0-9/+=]{40}\b/g
|
|
9162
|
+
},
|
|
9163
|
+
{
|
|
9164
|
+
type: "stripe_secret_key",
|
|
9165
|
+
pattern: /\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\b/g
|
|
9166
|
+
},
|
|
9167
|
+
{ type: "google_api_key", pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g },
|
|
9168
|
+
{
|
|
9169
|
+
type: "openssh_private_key_block",
|
|
9170
|
+
pattern: /-----BEGIN[ ]OPENSSH[ ]PRIVATE[ ]KEY-----[\s\S]*?-----END[ ]OPENSSH[ ]PRIVATE[ ]KEY-----/g
|
|
9171
|
+
}
|
|
9172
|
+
];
|
|
9173
|
+
var REDACTION_POLICY_SALT = 2;
|
|
9174
|
+
function computeRedactionPolicyVersion(policy) {
|
|
9175
|
+
return REDACTION_POLICY_SALT * 1e6 + SECRET_PATTERNS.length * 2 + (policy.rejectDurableSecrets ? 1 : 0) + (policy.detectPii ? 4 : 0) + (policy.rejectDurablePii ? 8 : 0) + (policy.piiDetector === "ner" ? 16 : 0);
|
|
9176
|
+
}
|
|
9177
|
+
var FINGERPRINT_ALGORITHM_VERSION = 2;
|
|
9178
|
+
var LEGACY_FINGERPRINT_ALGORITHM_VERSION = 1;
|
|
9179
|
+
var _internals16 = {
|
|
9180
|
+
currentAlgorithmVersion: FINGERPRINT_ALGORITHM_VERSION
|
|
9181
|
+
};
|
|
9182
|
+
function classifyStoredFingerprintAlgorithmVersion(rawStoredVersion, currentVersion = _internals16.currentAlgorithmVersion) {
|
|
9183
|
+
const storedVersion = rawStoredVersion === undefined ? LEGACY_FINGERPRINT_ALGORITHM_VERSION : rawStoredVersion;
|
|
9184
|
+
if (typeof storedVersion !== "number" || !Number.isFinite(storedVersion)) {
|
|
9185
|
+
return { status: "unknown" };
|
|
9186
|
+
}
|
|
9187
|
+
return storedVersion === currentVersion ? { status: "comparable" } : { status: "mismatch", storedVersion, currentVersion };
|
|
9188
|
+
}
|
|
9189
|
+
function computeMemoryCohortFingerprint(input) {
|
|
9190
|
+
const canonical = stableCanonicalStringify(input);
|
|
9191
|
+
return createHash6("sha256").update(canonical).digest("hex").slice(0, 12);
|
|
9192
|
+
}
|
|
9193
|
+
function buildMemoryCohortFingerprintInput(config) {
|
|
9194
|
+
return {
|
|
9195
|
+
provider: config.provider,
|
|
9196
|
+
redaction_policy_version: computeRedactionPolicyVersion({
|
|
9197
|
+
rejectDurableSecrets: config.redaction.rejectDurableSecrets,
|
|
9198
|
+
detectPii: config.redaction.detectPii,
|
|
9199
|
+
rejectDurablePii: config.redaction.rejectDurablePii,
|
|
9200
|
+
piiDetector: config.redaction.piiDetector
|
|
9201
|
+
}),
|
|
9202
|
+
embedding_model: config.embeddings.model,
|
|
9203
|
+
embedding_dimension: config.embeddings.dimension,
|
|
9204
|
+
embedding_version: config.embeddings.version ?? "default"
|
|
9205
|
+
};
|
|
9206
|
+
}
|
|
9207
|
+
function findSecrets(text) {
|
|
9208
|
+
const findings = [];
|
|
9209
|
+
for (const { type, pattern } of SECRET_PATTERNS) {
|
|
9210
|
+
pattern.lastIndex = 0;
|
|
9211
|
+
for (const match of text.matchAll(pattern)) {
|
|
9212
|
+
if (match[0])
|
|
9213
|
+
findings.push({ type, match: match[0] });
|
|
9214
|
+
}
|
|
9215
|
+
}
|
|
9216
|
+
return findings;
|
|
9217
|
+
}
|
|
9218
|
+
function containsSecret(text) {
|
|
9219
|
+
return findSecrets(text).length > 0;
|
|
9220
|
+
}
|
|
9221
|
+
function redactSecrets(text) {
|
|
9222
|
+
let redacted = text;
|
|
9223
|
+
for (const { type, pattern } of SECRET_PATTERNS) {
|
|
9224
|
+
pattern.lastIndex = 0;
|
|
9225
|
+
redacted = redacted.replace(pattern, `[REDACTED:${type}]`);
|
|
9226
|
+
}
|
|
9227
|
+
return redacted;
|
|
9228
|
+
}
|
|
9229
|
+
|
|
9124
9230
|
// src/hooks/pr-workflow-gate.ts
|
|
9125
9231
|
init_tool_metadata();
|
|
9126
9232
|
init_logger();
|
|
@@ -9229,6 +9335,10 @@ var PR_REVIEW_MICRO_LANE_FLOORS = {
|
|
|
9229
9335
|
M: 6,
|
|
9230
9336
|
L: PR_REVIEW_REQUIRED_MICRO_LANE_IDS.length
|
|
9231
9337
|
};
|
|
9338
|
+
var MAX_PUBLICATION_HISTORY_GENERATIONS = 4;
|
|
9339
|
+
var MAX_PUBLICATION_ATTEMPTS = 8;
|
|
9340
|
+
var MAX_PUSH_ATTEMPT_DIAGNOSTIC_CHARS = 500;
|
|
9341
|
+
var PUBLICATION_SCHEMA_VERSION = 1;
|
|
9232
9342
|
var GATE_SCHEMA_VERSION = 1;
|
|
9233
9343
|
var MAX_TRACKED_SESSIONS3 = 200;
|
|
9234
9344
|
var MAX_WORKFLOW_BATCHES = 128;
|
|
@@ -9375,6 +9485,86 @@ var PrFeedbackReadyToPublishRecordSchema = exports_external.object({
|
|
|
9375
9485
|
remoteRef: exports_external.string().startsWith("refs/remotes/"),
|
|
9376
9486
|
validatedAt: exports_external.string().min(1)
|
|
9377
9487
|
}).strict();
|
|
9488
|
+
var PrFeedbackPublicationEvidenceJoinSchema = exports_external.object({
|
|
9489
|
+
stageAValidatedAt: exports_external.string().min(1),
|
|
9490
|
+
batches: exports_external.array(exports_external.object({
|
|
9491
|
+
phase: exports_external.enum([
|
|
9492
|
+
"stage-b-reviewer",
|
|
9493
|
+
"stage-b-test",
|
|
9494
|
+
"closeout-reviewer",
|
|
9495
|
+
"closeout-critic"
|
|
9496
|
+
]),
|
|
9497
|
+
batchId: exports_external.string().min(1),
|
|
9498
|
+
laneId: exports_external.string().min(1)
|
|
9499
|
+
}).strict())
|
|
9500
|
+
}).strict();
|
|
9501
|
+
var PrFeedbackPublicationGenerationSchema = exports_external.object({
|
|
9502
|
+
schemaVersion: exports_external.literal(PUBLICATION_SCHEMA_VERSION),
|
|
9503
|
+
generation: exports_external.number().int().positive(),
|
|
9504
|
+
state: exports_external.enum([
|
|
9505
|
+
"reviewing",
|
|
9506
|
+
"armed",
|
|
9507
|
+
"invalidated",
|
|
9508
|
+
"push_in_flight",
|
|
9509
|
+
"published",
|
|
9510
|
+
"cancelled_without_publication"
|
|
9511
|
+
]),
|
|
9512
|
+
workspaceIdentity: exports_external.string().min(1),
|
|
9513
|
+
sessionID: exports_external.string().min(1),
|
|
9514
|
+
prTargetUrl: exports_external.string().min(1).optional(),
|
|
9515
|
+
intakeHeadSha: exports_external.string().min(1),
|
|
9516
|
+
localHeadRef: exports_external.string().min(1),
|
|
9517
|
+
localHead: exports_external.string().min(1),
|
|
9518
|
+
remoteName: exports_external.string().min(1),
|
|
9519
|
+
remoteUrlIdentity: exports_external.string().min(1).optional(),
|
|
9520
|
+
remoteBranchRef: exports_external.string().startsWith("refs/heads/"),
|
|
9521
|
+
remoteRef: exports_external.string().startsWith("refs/remotes/"),
|
|
9522
|
+
revisionDigest: exports_external.string().min(1),
|
|
9523
|
+
evidence: PrFeedbackPublicationEvidenceJoinSchema,
|
|
9524
|
+
invalidationReason: exports_external.string().min(1).optional(),
|
|
9525
|
+
supersededByGeneration: exports_external.number().int().positive().optional(),
|
|
9526
|
+
createdAt: exports_external.string().min(1),
|
|
9527
|
+
armedAt: exports_external.string().min(1).optional(),
|
|
9528
|
+
invalidatedAt: exports_external.string().min(1).optional(),
|
|
9529
|
+
publishedAt: exports_external.string().min(1).optional(),
|
|
9530
|
+
cancelledAt: exports_external.string().min(1).optional()
|
|
9531
|
+
}).strict();
|
|
9532
|
+
var PrFeedbackPushAttemptSchema = exports_external.object({
|
|
9533
|
+
attemptId: exports_external.string().min(1),
|
|
9534
|
+
generation: exports_external.number().int().positive(),
|
|
9535
|
+
sessionID: exports_external.string().min(1),
|
|
9536
|
+
callID: exports_external.string().min(1).optional(),
|
|
9537
|
+
intentDigest: exports_external.string().regex(/^[0-9a-f]{64}$/),
|
|
9538
|
+
intent: exports_external.object({
|
|
9539
|
+
remote: exports_external.string().min(1),
|
|
9540
|
+
sourceSha: exports_external.string().min(1),
|
|
9541
|
+
destRef: exports_external.string().startsWith("refs/heads/")
|
|
9542
|
+
}).strict(),
|
|
9543
|
+
prePush: exports_external.object({
|
|
9544
|
+
localHead: exports_external.string().min(1),
|
|
9545
|
+
worktreeClean: exports_external.boolean(),
|
|
9546
|
+
remoteName: exports_external.string().min(1),
|
|
9547
|
+
remoteBranchRef: exports_external.string().startsWith("refs/heads/"),
|
|
9548
|
+
observedRemoteHead: exports_external.string().min(1).nullable()
|
|
9549
|
+
}).strict(),
|
|
9550
|
+
startedAt: exports_external.string().min(1),
|
|
9551
|
+
result: exports_external.object({
|
|
9552
|
+
outcome: exports_external.enum(["completed", "rejected", "uncertain", "cancelled"]),
|
|
9553
|
+
exitStatus: exports_external.union([exports_external.number().int(), exports_external.literal("not-observed")]),
|
|
9554
|
+
diagnostic: exports_external.string().max(MAX_PUSH_ATTEMPT_DIAGNOSTIC_CHARS),
|
|
9555
|
+
postPush: exports_external.object({
|
|
9556
|
+
localHead: exports_external.string().min(1).nullable(),
|
|
9557
|
+
observedRemoteHead: exports_external.string().min(1).nullable()
|
|
9558
|
+
}).strict(),
|
|
9559
|
+
completedAt: exports_external.string().min(1)
|
|
9560
|
+
}).strict().optional()
|
|
9561
|
+
}).strict();
|
|
9562
|
+
var PrFeedbackPublicationStateSchema = exports_external.object({
|
|
9563
|
+
schemaVersion: exports_external.literal(PUBLICATION_SCHEMA_VERSION),
|
|
9564
|
+
active: PrFeedbackPublicationGenerationSchema.optional(),
|
|
9565
|
+
history: exports_external.array(PrFeedbackPublicationGenerationSchema).max(MAX_PUBLICATION_HISTORY_GENERATIONS),
|
|
9566
|
+
attempts: exports_external.array(PrFeedbackPushAttemptSchema).max(MAX_PUBLICATION_ATTEMPTS)
|
|
9567
|
+
}).strict();
|
|
9378
9568
|
var PrFeedbackInventoryAmendmentRecordSchema = exports_external.object({
|
|
9379
9569
|
entry: exports_external.string().min(1),
|
|
9380
9570
|
amendedAt: exports_external.string().min(1),
|
|
@@ -9483,6 +9673,7 @@ var PrWorkflowGateStateSchema = exports_external.object({
|
|
|
9483
9673
|
prFeedbackStageA: PrFeedbackStageARecordSchema.optional(),
|
|
9484
9674
|
prFeedbackGateBatches: exports_external.array(PrFeedbackGateBatchRecordSchema).max(MAX_WORKFLOW_BATCHES).optional(),
|
|
9485
9675
|
prFeedbackReadyToPublish: PrFeedbackReadyToPublishRecordSchema.optional(),
|
|
9676
|
+
prFeedbackPublication: PrFeedbackPublicationStateSchema.optional(),
|
|
9486
9677
|
prFeedbackRebindCount: exports_external.number().int().nonnegative().optional(),
|
|
9487
9678
|
prFeedbackScopes: exports_external.array(PrFeedbackScopeDeclarationRecordSchema).max(MAX_WORKFLOW_BATCHES).optional()
|
|
9488
9679
|
}).passthrough();
|
|
@@ -9785,14 +9976,49 @@ async function finalizeOverriddenProbeRetainedLanes(directory, sessionID, correl
|
|
|
9785
9976
|
}
|
|
9786
9977
|
async function abortPrWorkflow(directory, sessionID, options = { kind: "recovery", reason: "" }) {
|
|
9787
9978
|
const recovery = await readPrWorkflowGateStateForRecovery(directory, sessionID);
|
|
9788
|
-
if (!recovery)
|
|
9979
|
+
if (!recovery) {
|
|
9980
|
+
if (options.cancelPublication) {
|
|
9981
|
+
if (!options.reason.trim()) {
|
|
9982
|
+
throw new Error("BLOCKED: cancel_publication requires a non-empty reason; the cancellation reason is part of the durable audit trail");
|
|
9983
|
+
}
|
|
9984
|
+
const dangling = findDanglingLivePublicationGeneration(directory, sessionID);
|
|
9985
|
+
if (!dangling)
|
|
9986
|
+
throw noActiveGateError(sessionID);
|
|
9987
|
+
appendPublicationEvent(directory, {
|
|
9988
|
+
type: "pr_feedback_publication_cancelled",
|
|
9989
|
+
sessionID: normalizeSessionID(sessionID),
|
|
9990
|
+
generation: dangling.generation,
|
|
9991
|
+
reason: options.reason.trim(),
|
|
9992
|
+
stateFileAbsent: true
|
|
9993
|
+
});
|
|
9994
|
+
return {
|
|
9995
|
+
mode: "PR_FEEDBACK",
|
|
9996
|
+
openLanes: 0,
|
|
9997
|
+
stateSalvaged: false,
|
|
9998
|
+
stateSalvageDisclosure: "The gate state file was already absent; the live publication generation in the audit trail was recorded as cancelled_without_publication (event-only terminal)."
|
|
9999
|
+
};
|
|
10000
|
+
}
|
|
9789
10001
|
throw noActiveGateError(sessionID);
|
|
10002
|
+
}
|
|
9790
10003
|
const state = recovery.state;
|
|
10004
|
+
let cancelRevision = null;
|
|
9791
10005
|
if (options.expectedMode && state.mode !== options.expectedMode) {
|
|
9792
10006
|
throw wrongModeError(state, options.expectedMode);
|
|
9793
10007
|
}
|
|
9794
|
-
if (
|
|
9795
|
-
|
|
10008
|
+
if (options.cancelPublication) {
|
|
10009
|
+
if (options.kind === "force") {
|
|
10010
|
+
throw new Error('BLOCKED: cancel_publication cannot be combined with kind "force"; use kind "cancel-publication" with a reason');
|
|
10011
|
+
}
|
|
10012
|
+
if (!options.reason.trim()) {
|
|
10013
|
+
throw new Error("BLOCKED: cancel_publication requires a non-empty reason; the cancellation reason is part of the durable audit trail");
|
|
10014
|
+
}
|
|
10015
|
+
if (state.mode !== "PR_FEEDBACK" || !state.prFeedbackReadyToPublish && !recovery.armedShapeUnreadable && !state.prFeedbackPublication?.active) {
|
|
10016
|
+
throw new Error("BLOCKED: cancel_publication applies only to a PR_FEEDBACK workflow with a publication generation (armed, push_in_flight, or invalidated)");
|
|
10017
|
+
}
|
|
10018
|
+
cancelRevision = await cancelPrFeedbackPublication(directory, sessionID, options.reason.trim());
|
|
10019
|
+
}
|
|
10020
|
+
if ((state.prFeedbackReadyToPublish || recovery.armedShapeUnreadable) && !options.cancelPublication) {
|
|
10021
|
+
throw new Error(`BLOCKED: ${state.mode} is armed for publication; abort is blocked. Complete the workflow with complete_pr_workflow (or push the bound commit first) before aborting, or use the audited cancellation (abort_pr_workflow with cancel_publication and a reason).` + (recovery.armedShapeUnreadable ? " The publication-arming record is itself unreadable, so it is treated as armed (fail-closed)." : ""));
|
|
9796
10022
|
}
|
|
9797
10023
|
const laneSettlement = await settlePresumedStalePrWorkflowLanes(directory, state.sessionID);
|
|
9798
10024
|
const probeRetainedLanes = laneSettlement.probedAliveLaneIds ?? [];
|
|
@@ -9841,7 +10067,7 @@ async function abortPrWorkflow(directory, sessionID, options = { kind: "recovery
|
|
|
9841
10067
|
const casEscape = recovery.salvaged && !recovery.revisionSalvageable;
|
|
9842
10068
|
await _test_exports2.beforeAbortClear?.();
|
|
9843
10069
|
try {
|
|
9844
|
-
await clearPrWorkflowGateState(directory, sessionID, casEscape ? undefined : state.revision, { allowSalvagedRead: recovery.salvaged });
|
|
10070
|
+
await clearPrWorkflowGateState(directory, sessionID, casEscape ? undefined : cancelRevision ?? state.revision, { allowSalvagedRead: recovery.salvaged });
|
|
9845
10071
|
} catch (error2) {
|
|
9846
10072
|
try {
|
|
9847
10073
|
appendCoreEventSync(directory, {
|
|
@@ -10079,7 +10305,7 @@ async function readAndVerifyCoverageDisclosure(directory, state) {
|
|
|
10079
10305
|
throw new Error("BLOCKED: PR_REVIEW partial base coverage disclosure path does not match its bound run");
|
|
10080
10306
|
}
|
|
10081
10307
|
const raw = await readBoundedSwarmRegularFile(directory, relativePath, PR_REVIEW_COVERAGE_DISCLOSURE_MAX_BYTES, "PR_REVIEW partial base coverage disclosure");
|
|
10082
|
-
const digest2 =
|
|
10308
|
+
const digest2 = createHash7("sha256").update(raw, "utf8").digest("hex");
|
|
10083
10309
|
if (digest2 !== expectedDigest) {
|
|
10084
10310
|
throw new Error("BLOCKED: PR_REVIEW partial base coverage disclosure digest does not match durable state");
|
|
10085
10311
|
}
|
|
@@ -10159,6 +10385,897 @@ async function assertPrReviewValidationSettled(directory, sessionID, phase, gate
|
|
|
10159
10385
|
}
|
|
10160
10386
|
return state;
|
|
10161
10387
|
}
|
|
10388
|
+
var PR_FEEDBACK_PHASE_ORDER = [
|
|
10389
|
+
"stage-b-reviewer",
|
|
10390
|
+
"stage-b-test",
|
|
10391
|
+
"closeout-reviewer",
|
|
10392
|
+
"closeout-critic"
|
|
10393
|
+
];
|
|
10394
|
+
async function verifyPublicationIdentityComponent(directory, state, active, component) {
|
|
10395
|
+
switch (component) {
|
|
10396
|
+
case "digest": {
|
|
10397
|
+
try {
|
|
10398
|
+
const digest2 = await currentPrFeedbackRevisionDigest(directory, state);
|
|
10399
|
+
return digest2 === active.revisionDigest ? { kind: "intact" } : {
|
|
10400
|
+
kind: "drift",
|
|
10401
|
+
component,
|
|
10402
|
+
detail: `approved revision digest ${active.revisionDigest} vs current ${digest2}`
|
|
10403
|
+
};
|
|
10404
|
+
} catch (error2) {
|
|
10405
|
+
return {
|
|
10406
|
+
kind: "unresolvable",
|
|
10407
|
+
component,
|
|
10408
|
+
detail: String(error2?.message ?? error2)
|
|
10409
|
+
};
|
|
10410
|
+
}
|
|
10411
|
+
}
|
|
10412
|
+
case "head": {
|
|
10413
|
+
const head = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
|
|
10414
|
+
if (!head)
|
|
10415
|
+
return {
|
|
10416
|
+
kind: "unresolvable",
|
|
10417
|
+
component,
|
|
10418
|
+
detail: "HEAD resolution returned empty"
|
|
10419
|
+
};
|
|
10420
|
+
return head === active.localHead ? { kind: "intact" } : {
|
|
10421
|
+
kind: "drift",
|
|
10422
|
+
component,
|
|
10423
|
+
detail: `approved head ${active.localHead} vs current ${head}`
|
|
10424
|
+
};
|
|
10425
|
+
}
|
|
10426
|
+
case "worktree": {
|
|
10427
|
+
const clean = await _test_exports2.resolveIsWorkingTreeCleanAsync(directory);
|
|
10428
|
+
if (clean !== true && clean !== false)
|
|
10429
|
+
return {
|
|
10430
|
+
kind: "unresolvable",
|
|
10431
|
+
component,
|
|
10432
|
+
detail: "clean-status resolution failed"
|
|
10433
|
+
};
|
|
10434
|
+
return clean === true ? { kind: "intact" } : {
|
|
10435
|
+
kind: "drift",
|
|
10436
|
+
component,
|
|
10437
|
+
detail: "working tree or index is dirty"
|
|
10438
|
+
};
|
|
10439
|
+
}
|
|
10440
|
+
case "upstream": {
|
|
10441
|
+
const target = await _test_exports2.resolveCurrentUpstreamPushTargetAsync(directory);
|
|
10442
|
+
if (!target)
|
|
10443
|
+
return {
|
|
10444
|
+
kind: "unresolvable",
|
|
10445
|
+
component,
|
|
10446
|
+
detail: "upstream target resolution returned empty"
|
|
10447
|
+
};
|
|
10448
|
+
return target.remoteName === active.remoteName && target.remoteBranchRef === active.remoteBranchRef && target.remoteTrackingRef === active.remoteRef ? { kind: "intact" } : {
|
|
10449
|
+
kind: "drift",
|
|
10450
|
+
component,
|
|
10451
|
+
detail: `approved target ${active.remoteName}/${active.remoteBranchRef}/${active.remoteRef} vs current ${target.remoteName}/${target.remoteBranchRef}/${target.remoteTrackingRef}`
|
|
10452
|
+
};
|
|
10453
|
+
}
|
|
10454
|
+
case "remote-url": {
|
|
10455
|
+
if (!active.remoteUrlIdentity) {
|
|
10456
|
+
return {
|
|
10457
|
+
kind: "unresolvable",
|
|
10458
|
+
component,
|
|
10459
|
+
detail: "armed generation carries no remote URL identity"
|
|
10460
|
+
};
|
|
10461
|
+
}
|
|
10462
|
+
const url = await _test_exports2.resolveRemoteUrlIdentityAsync(directory, active.remoteName);
|
|
10463
|
+
if (!url)
|
|
10464
|
+
return {
|
|
10465
|
+
kind: "unresolvable",
|
|
10466
|
+
component,
|
|
10467
|
+
detail: `remote "${active.remoteName}" URL could not be resolved`
|
|
10468
|
+
};
|
|
10469
|
+
return url === active.remoteUrlIdentity ? { kind: "intact" } : {
|
|
10470
|
+
kind: "drift",
|
|
10471
|
+
component,
|
|
10472
|
+
detail: `approved remote URL identity ${active.remoteUrlIdentity} vs current ${url}`
|
|
10473
|
+
};
|
|
10474
|
+
}
|
|
10475
|
+
case "workspace-identity": {
|
|
10476
|
+
const identity = canonicalWorkspaceIdentity(directory);
|
|
10477
|
+
if (!identity)
|
|
10478
|
+
return {
|
|
10479
|
+
kind: "unresolvable",
|
|
10480
|
+
component,
|
|
10481
|
+
detail: "canonical workspace identity could not be resolved"
|
|
10482
|
+
};
|
|
10483
|
+
return identity === active.workspaceIdentity ? { kind: "intact" } : {
|
|
10484
|
+
kind: "drift",
|
|
10485
|
+
component,
|
|
10486
|
+
detail: `generation is bound to a different workspace`
|
|
10487
|
+
};
|
|
10488
|
+
}
|
|
10489
|
+
case "evidence-join": {
|
|
10490
|
+
return publicationEvidenceJoinIntact(state, active) ? { kind: "intact" } : {
|
|
10491
|
+
kind: "drift",
|
|
10492
|
+
component,
|
|
10493
|
+
detail: "the receipt set recorded at arming is no longer the active one"
|
|
10494
|
+
};
|
|
10495
|
+
}
|
|
10496
|
+
default:
|
|
10497
|
+
return { kind: "unresolvable", component, detail: "unknown component" };
|
|
10498
|
+
}
|
|
10499
|
+
}
|
|
10500
|
+
var PUBLICATION_IDENTITY_COMPONENTS = [
|
|
10501
|
+
"digest",
|
|
10502
|
+
"head",
|
|
10503
|
+
"worktree",
|
|
10504
|
+
"upstream",
|
|
10505
|
+
"remote-url",
|
|
10506
|
+
"workspace-identity"
|
|
10507
|
+
];
|
|
10508
|
+
async function checkPublicationIdentity(directory, state, active) {
|
|
10509
|
+
for (const component of PUBLICATION_IDENTITY_COMPONENTS) {
|
|
10510
|
+
const check = await verifyPublicationIdentityComponent(directory, state, active, component);
|
|
10511
|
+
if (check.kind !== "intact")
|
|
10512
|
+
return check;
|
|
10513
|
+
}
|
|
10514
|
+
if (!publicationEvidenceJoinIntact(state, active)) {
|
|
10515
|
+
return {
|
|
10516
|
+
kind: "drift",
|
|
10517
|
+
component: "evidence-join",
|
|
10518
|
+
detail: "the receipt set recorded at arming is no longer the active one"
|
|
10519
|
+
};
|
|
10520
|
+
}
|
|
10521
|
+
return { kind: "intact" };
|
|
10522
|
+
}
|
|
10523
|
+
function publicationEvidenceJoinIntact(state, active) {
|
|
10524
|
+
if (state.prFeedbackStageA?.validatedAt !== active.evidence.stageAValidatedAt)
|
|
10525
|
+
return false;
|
|
10526
|
+
for (const join11 of active.evidence.batches) {
|
|
10527
|
+
const batch = [...state.prFeedbackGateBatches ?? []].reverse().find((candidate) => candidate.phase === join11.phase);
|
|
10528
|
+
if (!batch || batch.batchId !== join11.batchId || batch.laneId !== join11.laneId)
|
|
10529
|
+
return false;
|
|
10530
|
+
}
|
|
10531
|
+
return true;
|
|
10532
|
+
}
|
|
10533
|
+
function buildPublicationEvidenceJoin(state, currentDigest) {
|
|
10534
|
+
const stageA = state.prFeedbackStageA;
|
|
10535
|
+
if (!stageA || stageA.revisionDigest !== currentDigest || !stageA.validatedAt)
|
|
10536
|
+
return null;
|
|
10537
|
+
const batches = [];
|
|
10538
|
+
for (const phase of PR_FEEDBACK_PHASE_ORDER) {
|
|
10539
|
+
const batch = [...state.prFeedbackGateBatches ?? []].reverse().find((candidate) => candidate.phase === phase && candidate.revisionDigest === currentDigest);
|
|
10540
|
+
if (!batch)
|
|
10541
|
+
return null;
|
|
10542
|
+
batches.push({ phase, batchId: batch.batchId, laneId: batch.laneId });
|
|
10543
|
+
}
|
|
10544
|
+
return { stageAValidatedAt: stageA.validatedAt, batches };
|
|
10545
|
+
}
|
|
10546
|
+
function appendPublicationEvent(directory, event) {
|
|
10547
|
+
try {
|
|
10548
|
+
appendCoreEventSync(directory, { ...event, timestamp: isoNow() });
|
|
10549
|
+
} catch {}
|
|
10550
|
+
}
|
|
10551
|
+
function boundPublicationDiagnostic(text) {
|
|
10552
|
+
const redacted = redactSecrets(text);
|
|
10553
|
+
return redacted.length > MAX_PUSH_ATTEMPT_DIAGNOSTIC_CHARS ? `${redacted.slice(0, MAX_PUSH_ATTEMPT_DIAGNOSTIC_CHARS - 3)}...` : redacted;
|
|
10554
|
+
}
|
|
10555
|
+
function nextPublicationContainer(previous, active, historyAppends = [], attempts = []) {
|
|
10556
|
+
const history = [...previous?.history ?? [], ...historyAppends].slice(-MAX_PUBLICATION_HISTORY_GENERATIONS);
|
|
10557
|
+
return {
|
|
10558
|
+
schemaVersion: PUBLICATION_SCHEMA_VERSION,
|
|
10559
|
+
active,
|
|
10560
|
+
history,
|
|
10561
|
+
attempts: attempts.slice(-MAX_PUBLICATION_ATTEMPTS)
|
|
10562
|
+
};
|
|
10563
|
+
}
|
|
10564
|
+
async function invalidatePublicationGeneration(directory, sessionID, reason, options = {}) {
|
|
10565
|
+
const normalizedSessionID = normalizeSessionID(sessionID);
|
|
10566
|
+
return withSessionStateMutation(directory, normalizedSessionID, async () => {
|
|
10567
|
+
const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
|
|
10568
|
+
if (!state || state.mode !== "PR_FEEDBACK") {
|
|
10569
|
+
throw new Error("BLOCKED: PR_FEEDBACK publication invalidation requires an active PR_FEEDBACK gate");
|
|
10570
|
+
}
|
|
10571
|
+
return applyPublicationInvalidationWhileLocked(directory, state, reason, options);
|
|
10572
|
+
});
|
|
10573
|
+
}
|
|
10574
|
+
async function applyPublicationInvalidationWhileLocked(directory, state, reason, options = {}) {
|
|
10575
|
+
{
|
|
10576
|
+
const active = state.prFeedbackPublication?.active;
|
|
10577
|
+
const legacyRecord = active ? undefined : state.prFeedbackReadyToPublish;
|
|
10578
|
+
if (!active && !legacyRecord) {
|
|
10579
|
+
throw new Error("BLOCKED: no armed publication generation to invalidate");
|
|
10580
|
+
}
|
|
10581
|
+
if (active && active.state !== "armed" && active.state !== "push_in_flight") {
|
|
10582
|
+
throw new Error(`BLOCKED: publication generation ${active.generation} is already ${active.state}`);
|
|
10583
|
+
}
|
|
10584
|
+
if (options.driftReverification && options.drift && active) {
|
|
10585
|
+
const recheck = await verifyPublicationIdentityComponent(directory, state, active, options.drift.component);
|
|
10586
|
+
if (recheck.kind !== "drift") {
|
|
10587
|
+
throw new Error(`BLOCKED: PR_FEEDBACK publication drift on ${options.drift.component} did not re-confirm under the state lock (${recheck.kind}); no invalidation was recorded \u2014 retry from current state`);
|
|
10588
|
+
}
|
|
10589
|
+
options.drift = { component: recheck.component, detail: recheck.detail };
|
|
10590
|
+
}
|
|
10591
|
+
const now = isoNow();
|
|
10592
|
+
let attempts = (state.prFeedbackPublication?.attempts ?? []).map((attempt) => attempt.result ? attempt : {
|
|
10593
|
+
...attempt,
|
|
10594
|
+
result: {
|
|
10595
|
+
outcome: options.finalizeInFlightAs ?? "uncertain",
|
|
10596
|
+
exitStatus: "not-observed",
|
|
10597
|
+
diagnostic: `finalized by publication invalidation (${reason})`,
|
|
10598
|
+
postPush: { localHead: null, observedRemoteHead: null },
|
|
10599
|
+
completedAt: now
|
|
10600
|
+
}
|
|
10601
|
+
});
|
|
10602
|
+
let invalidated;
|
|
10603
|
+
if (active) {
|
|
10604
|
+
invalidated = {
|
|
10605
|
+
...active,
|
|
10606
|
+
state: "invalidated",
|
|
10607
|
+
invalidatedAt: now,
|
|
10608
|
+
invalidationReason: reason
|
|
10609
|
+
};
|
|
10610
|
+
} else if (legacyRecord) {
|
|
10611
|
+
invalidated = {
|
|
10612
|
+
schemaVersion: PUBLICATION_SCHEMA_VERSION,
|
|
10613
|
+
generation: 1,
|
|
10614
|
+
state: "invalidated",
|
|
10615
|
+
workspaceIdentity: canonicalWorkspaceIdentity(directory) ?? "unresolvable",
|
|
10616
|
+
sessionID: state.sessionID,
|
|
10617
|
+
intakeHeadSha: state.prHeadSha ?? "unknown",
|
|
10618
|
+
localHeadRef: "unknown",
|
|
10619
|
+
localHead: legacyRecord.localHead,
|
|
10620
|
+
remoteName: legacyRecord.remoteName,
|
|
10621
|
+
remoteUrlIdentity: undefined,
|
|
10622
|
+
remoteBranchRef: legacyRecord.remoteBranchRef,
|
|
10623
|
+
remoteRef: legacyRecord.remoteRef,
|
|
10624
|
+
revisionDigest: legacyRecord.revisionDigest,
|
|
10625
|
+
evidence: {
|
|
10626
|
+
stageAValidatedAt: state.prFeedbackStageA?.validatedAt ?? "unknown",
|
|
10627
|
+
batches: (state.prFeedbackGateBatches ?? []).map((batch) => ({
|
|
10628
|
+
phase: batch.phase,
|
|
10629
|
+
batchId: batch.batchId,
|
|
10630
|
+
laneId: batch.laneId
|
|
10631
|
+
}))
|
|
10632
|
+
},
|
|
10633
|
+
invalidationReason: reason,
|
|
10634
|
+
createdAt: legacyRecord.validatedAt,
|
|
10635
|
+
armedAt: legacyRecord.validatedAt,
|
|
10636
|
+
invalidatedAt: now
|
|
10637
|
+
};
|
|
10638
|
+
} else {
|
|
10639
|
+
throw new Error("BLOCKED: no armed publication generation to invalidate");
|
|
10640
|
+
}
|
|
10641
|
+
if (!active) {
|
|
10642
|
+
attempts = [];
|
|
10643
|
+
}
|
|
10644
|
+
const nextState = {
|
|
10645
|
+
...state,
|
|
10646
|
+
updatedAt: now,
|
|
10647
|
+
prFeedbackStageA: undefined,
|
|
10648
|
+
prFeedbackVerifications: undefined,
|
|
10649
|
+
prFeedbackGateBatches: undefined,
|
|
10650
|
+
prFeedbackScopes: undefined,
|
|
10651
|
+
prFeedbackReadyToPublish: undefined,
|
|
10652
|
+
prFeedbackPublication: nextPublicationContainer(state.prFeedbackPublication, invalidated, [], attempts)
|
|
10653
|
+
};
|
|
10654
|
+
await writeStateWhileLocked(directory, nextState);
|
|
10655
|
+
appendPublicationEvent(directory, {
|
|
10656
|
+
type: "pr_feedback_publication_invalidated",
|
|
10657
|
+
sessionID: state.sessionID,
|
|
10658
|
+
generation: invalidated.generation,
|
|
10659
|
+
reason,
|
|
10660
|
+
previousState: active?.state ?? "armed",
|
|
10661
|
+
drift: options.drift ?? null,
|
|
10662
|
+
revisionDigest: invalidated.revisionDigest,
|
|
10663
|
+
localHead: invalidated.localHead,
|
|
10664
|
+
remoteName: invalidated.remoteName,
|
|
10665
|
+
remoteBranchRef: invalidated.remoteBranchRef,
|
|
10666
|
+
supersededBatchIds: invalidated.evidence.batches.map((b) => b.batchId)
|
|
10667
|
+
});
|
|
10668
|
+
return { generation: invalidated, state: nextState };
|
|
10669
|
+
}
|
|
10670
|
+
}
|
|
10671
|
+
async function ensurePublicationGenerationCurrent(directory, sessionID) {
|
|
10672
|
+
const normalizedSessionID = normalizeSessionID(sessionID);
|
|
10673
|
+
const state = await readPrWorkflowGateState(directory, normalizedSessionID);
|
|
10674
|
+
if (!state || state.mode !== "PR_FEEDBACK")
|
|
10675
|
+
return state;
|
|
10676
|
+
if (state.prFeedbackPublication || !state.prFeedbackReadyToPublish) {
|
|
10677
|
+
return state;
|
|
10678
|
+
}
|
|
10679
|
+
const legacy = state.prFeedbackReadyToPublish;
|
|
10680
|
+
return withSessionStateMutation(directory, normalizedSessionID, async () => {
|
|
10681
|
+
const locked = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
|
|
10682
|
+
if (!locked || locked.mode !== "PR_FEEDBACK")
|
|
10683
|
+
return locked ?? state;
|
|
10684
|
+
if (locked.prFeedbackPublication || !locked.prFeedbackReadyToPublish) {
|
|
10685
|
+
return locked;
|
|
10686
|
+
}
|
|
10687
|
+
const now = isoNow();
|
|
10688
|
+
const base = {
|
|
10689
|
+
schemaVersion: PUBLICATION_SCHEMA_VERSION,
|
|
10690
|
+
generation: 1,
|
|
10691
|
+
sessionID: locked.sessionID,
|
|
10692
|
+
prTargetUrl: locked.prFeedbackTargetUrl,
|
|
10693
|
+
intakeHeadSha: locked.prHeadSha ?? "unknown",
|
|
10694
|
+
revisionDigest: legacy.revisionDigest,
|
|
10695
|
+
evidence: buildPublicationEvidenceJoin(locked, legacy.revisionDigest) ?? {
|
|
10696
|
+
stageAValidatedAt: "unknown",
|
|
10697
|
+
batches: []
|
|
10698
|
+
},
|
|
10699
|
+
createdAt: legacy.validatedAt,
|
|
10700
|
+
armedAt: legacy.validatedAt
|
|
10701
|
+
};
|
|
10702
|
+
const mismatch = async (reason) => {
|
|
10703
|
+
const invalidated = {
|
|
10704
|
+
...base,
|
|
10705
|
+
evidence: base.evidence.batches.length > 0 ? base.evidence : {
|
|
10706
|
+
stageAValidatedAt: locked.prFeedbackStageA?.validatedAt ?? "unknown",
|
|
10707
|
+
batches: (locked.prFeedbackGateBatches ?? []).map((batch) => ({
|
|
10708
|
+
phase: batch.phase,
|
|
10709
|
+
batchId: batch.batchId,
|
|
10710
|
+
laneId: batch.laneId
|
|
10711
|
+
}))
|
|
10712
|
+
},
|
|
10713
|
+
state: "invalidated",
|
|
10714
|
+
workspaceIdentity: canonicalWorkspaceIdentity(directory) ?? "unresolvable",
|
|
10715
|
+
localHeadRef: "unknown",
|
|
10716
|
+
localHead: legacy.localHead,
|
|
10717
|
+
remoteName: legacy.remoteName,
|
|
10718
|
+
remoteUrlIdentity: undefined,
|
|
10719
|
+
remoteBranchRef: legacy.remoteBranchRef,
|
|
10720
|
+
remoteRef: legacy.remoteRef,
|
|
10721
|
+
invalidationReason: reason,
|
|
10722
|
+
invalidatedAt: now
|
|
10723
|
+
};
|
|
10724
|
+
const nextState2 = {
|
|
10725
|
+
...locked,
|
|
10726
|
+
updatedAt: now,
|
|
10727
|
+
prFeedbackStageA: undefined,
|
|
10728
|
+
prFeedbackVerifications: undefined,
|
|
10729
|
+
prFeedbackGateBatches: undefined,
|
|
10730
|
+
prFeedbackScopes: undefined,
|
|
10731
|
+
prFeedbackReadyToPublish: undefined,
|
|
10732
|
+
prFeedbackPublication: nextPublicationContainer(locked.prFeedbackPublication, invalidated)
|
|
10733
|
+
};
|
|
10734
|
+
await writeStateWhileLocked(directory, nextState2);
|
|
10735
|
+
appendPublicationEvent(directory, {
|
|
10736
|
+
type: "pr_feedback_publication_migrated",
|
|
10737
|
+
sessionID: locked.sessionID,
|
|
10738
|
+
generation: 1,
|
|
10739
|
+
outcome: "invalidated",
|
|
10740
|
+
reason
|
|
10741
|
+
});
|
|
10742
|
+
return nextState2;
|
|
10743
|
+
};
|
|
10744
|
+
if (locked.prFeedbackStageA?.revisionDigest !== legacy.revisionDigest || !(locked.prFeedbackGateBatches ?? []).some((batch) => batch.revisionDigest === legacy.revisionDigest)) {
|
|
10745
|
+
return mismatch("legacy-migration-receipt-mismatch");
|
|
10746
|
+
}
|
|
10747
|
+
const workspaceIdentity = canonicalWorkspaceIdentity(directory);
|
|
10748
|
+
if (!workspaceIdentity)
|
|
10749
|
+
return mismatch("legacy-migration-unresolvable");
|
|
10750
|
+
let digest2;
|
|
10751
|
+
try {
|
|
10752
|
+
digest2 = await currentPrFeedbackRevisionDigest(directory, locked);
|
|
10753
|
+
} catch {
|
|
10754
|
+
return mismatch("legacy-migration-unresolvable");
|
|
10755
|
+
}
|
|
10756
|
+
const head = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
|
|
10757
|
+
const target = await _test_exports2.resolveCurrentUpstreamPushTargetAsync(directory);
|
|
10758
|
+
const localHeadRef = await resolveCurrentLocalHeadRefAsync(directory);
|
|
10759
|
+
const remoteUrlIdentity = await _test_exports2.resolveRemoteUrlIdentityAsync(directory, legacy.remoteName);
|
|
10760
|
+
if (digest2 !== legacy.revisionDigest || head !== legacy.localHead || !target || target.remoteName !== legacy.remoteName || target.remoteBranchRef !== legacy.remoteBranchRef || target.remoteTrackingRef !== legacy.remoteRef || !localHeadRef || !remoteUrlIdentity) {
|
|
10761
|
+
return mismatch("legacy-migration-identity-mismatch");
|
|
10762
|
+
}
|
|
10763
|
+
const evidenceJoin = buildPublicationEvidenceJoin(locked, legacy.revisionDigest);
|
|
10764
|
+
if (!evidenceJoin) {
|
|
10765
|
+
return mismatch("legacy-migration-receipt-mismatch");
|
|
10766
|
+
}
|
|
10767
|
+
const upgraded = {
|
|
10768
|
+
...base,
|
|
10769
|
+
evidence: evidenceJoin,
|
|
10770
|
+
state: "armed",
|
|
10771
|
+
workspaceIdentity,
|
|
10772
|
+
localHeadRef,
|
|
10773
|
+
localHead: legacy.localHead,
|
|
10774
|
+
remoteName: legacy.remoteName,
|
|
10775
|
+
remoteUrlIdentity,
|
|
10776
|
+
remoteBranchRef: legacy.remoteBranchRef,
|
|
10777
|
+
remoteRef: legacy.remoteRef
|
|
10778
|
+
};
|
|
10779
|
+
const nextState = {
|
|
10780
|
+
...locked,
|
|
10781
|
+
updatedAt: now,
|
|
10782
|
+
prFeedbackPublication: nextPublicationContainer(locked.prFeedbackPublication, upgraded)
|
|
10783
|
+
};
|
|
10784
|
+
await writeStateWhileLocked(directory, nextState);
|
|
10785
|
+
appendPublicationEvent(directory, {
|
|
10786
|
+
type: "pr_feedback_publication_migrated",
|
|
10787
|
+
sessionID: locked.sessionID,
|
|
10788
|
+
generation: 1,
|
|
10789
|
+
outcome: "armed",
|
|
10790
|
+
reason: "legacy-record-proven-equivalent"
|
|
10791
|
+
});
|
|
10792
|
+
return nextState;
|
|
10793
|
+
});
|
|
10794
|
+
}
|
|
10795
|
+
async function reconcileForeignInFlightAttempt(directory, sessionID, currentCallId) {
|
|
10796
|
+
const normalizedSessionID = normalizeSessionID(sessionID);
|
|
10797
|
+
return withSessionStateMutation(directory, normalizedSessionID, async () => {
|
|
10798
|
+
const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
|
|
10799
|
+
const publication = state?.prFeedbackPublication;
|
|
10800
|
+
const active = publication?.active;
|
|
10801
|
+
if (!state || !publication || !active || active.state !== "push_in_flight" || !publication.attempts.some((attempt) => !attempt.result)) {
|
|
10802
|
+
return state;
|
|
10803
|
+
}
|
|
10804
|
+
const now = isoNow();
|
|
10805
|
+
const localHead = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
|
|
10806
|
+
const observedRemoteHead = await _test_exports2.resolveExactRemoteBranchHeadAsync(directory, active.remoteName, active.remoteBranchRef);
|
|
10807
|
+
const attempts = publication.attempts.map((attempt) => attempt.result ? attempt : {
|
|
10808
|
+
...attempt,
|
|
10809
|
+
result: {
|
|
10810
|
+
outcome: "uncertain",
|
|
10811
|
+
exitStatus: "not-observed",
|
|
10812
|
+
diagnostic: boundPublicationDiagnostic(`recovered without an observed result${currentCallId && attempt.callID === currentCallId ? " (same call)" : ""}`),
|
|
10813
|
+
postPush: { localHead: localHead ?? null, observedRemoteHead },
|
|
10814
|
+
completedAt: now
|
|
10815
|
+
}
|
|
10816
|
+
});
|
|
10817
|
+
const nextState = {
|
|
10818
|
+
...state,
|
|
10819
|
+
updatedAt: now,
|
|
10820
|
+
prFeedbackPublication: nextPublicationContainer(publication, { ...active, state: "armed" }, [], attempts)
|
|
10821
|
+
};
|
|
10822
|
+
await writeStateWhileLocked(directory, nextState);
|
|
10823
|
+
appendPublicationEvent(directory, {
|
|
10824
|
+
type: "pr_feedback_push_attempt_result",
|
|
10825
|
+
sessionID: state.sessionID,
|
|
10826
|
+
generation: active.generation,
|
|
10827
|
+
outcome: "uncertain",
|
|
10828
|
+
by: "reaper",
|
|
10829
|
+
observedRemoteHead
|
|
10830
|
+
});
|
|
10831
|
+
return nextState;
|
|
10832
|
+
});
|
|
10833
|
+
}
|
|
10834
|
+
async function invalidatePrFeedbackPublication(directory, sessionID, reason) {
|
|
10835
|
+
const trimmed = reason.trim();
|
|
10836
|
+
if (!trimmed) {
|
|
10837
|
+
throw new Error("BLOCKED: invalidate_pr_feedback_publication requires a non-empty reason; the reason is part of the durable audit trail");
|
|
10838
|
+
}
|
|
10839
|
+
await ensurePublicationGenerationCurrent(directory, sessionID);
|
|
10840
|
+
await reconcileForeignInFlightAttempt(directory, sessionID);
|
|
10841
|
+
const result = await invalidatePublicationGeneration(directory, sessionID, `controller-rework:${trimmed}`);
|
|
10842
|
+
return result.generation;
|
|
10843
|
+
}
|
|
10844
|
+
function describePrWorkflowPublicationSection(state) {
|
|
10845
|
+
const active = state.prFeedbackPublication?.active;
|
|
10846
|
+
const history = state.prFeedbackPublication?.history ?? [];
|
|
10847
|
+
const attempts = state.prFeedbackPublication?.attempts ?? [];
|
|
10848
|
+
if (!active && !state.prFeedbackReadyToPublish && history.length === 0) {
|
|
10849
|
+
return null;
|
|
10850
|
+
}
|
|
10851
|
+
const lines = [];
|
|
10852
|
+
if (state.prFeedbackReadyToPublish && !active) {
|
|
10853
|
+
lines.push("publication: legacy armed record awaiting generation migration (fail-closed until the next gated interaction migrates it)");
|
|
10854
|
+
}
|
|
10855
|
+
if (active) {
|
|
10856
|
+
lines.push(`publication: generation ${active.generation} state=${active.state}`);
|
|
10857
|
+
lines.push(` approved: ${active.localHead} -> ${active.remoteName} ${active.remoteBranchRef} (digest ${active.revisionDigest.slice(0, 12)}\u2026)`);
|
|
10858
|
+
if (active.remoteUrlIdentity) {
|
|
10859
|
+
lines.push(` remote url identity: ${active.remoteUrlIdentity}`);
|
|
10860
|
+
}
|
|
10861
|
+
if (active.state === "invalidated" && active.invalidationReason) {
|
|
10862
|
+
lines.push(` invalidated because: ${active.invalidationReason}`);
|
|
10863
|
+
}
|
|
10864
|
+
if (active.supersededByGeneration) {
|
|
10865
|
+
lines.push(` superseded by generation ${active.supersededByGeneration}`);
|
|
10866
|
+
}
|
|
10867
|
+
const generationAttempts = attempts.filter((attempt) => attempt.generation === active.generation);
|
|
10868
|
+
if (generationAttempts.length > 0) {
|
|
10869
|
+
const outcomes = generationAttempts.map((attempt) => attempt.result?.outcome ?? "in-flight");
|
|
10870
|
+
lines.push(` push attempts: ${generationAttempts.length} (${outcomes.join(", ")})`);
|
|
10871
|
+
}
|
|
10872
|
+
switch (active.state) {
|
|
10873
|
+
case "armed":
|
|
10874
|
+
lines.push(" next: run the exact approved push, then complete_pr_workflow");
|
|
10875
|
+
break;
|
|
10876
|
+
case "push_in_flight":
|
|
10877
|
+
lines.push(" next: a push attempt is in flight; the next gated interaction reconciles it (uncertain) and re-verifies the remote before any retry");
|
|
10878
|
+
break;
|
|
10879
|
+
case "invalidated":
|
|
10880
|
+
lines.push(" next: rerun Stage A and every independent gate on the corrected content, then arm a fresh generation with complete_pr_workflow; the exact scoped rework path reopens via prepare_pr_feedback_scope");
|
|
10881
|
+
break;
|
|
10882
|
+
case "published":
|
|
10883
|
+
lines.push(" terminal: published (verified remote head)");
|
|
10884
|
+
break;
|
|
10885
|
+
case "cancelled_without_publication":
|
|
10886
|
+
lines.push(" terminal: cancelled without publication");
|
|
10887
|
+
break;
|
|
10888
|
+
default:
|
|
10889
|
+
lines.push(" next: continue the ordered gates");
|
|
10890
|
+
}
|
|
10891
|
+
}
|
|
10892
|
+
if (history.length > 0) {
|
|
10893
|
+
const summary = history.map((generation) => `gen ${generation.generation}: ${generation.state}${generation.supersededByGeneration ? ` -> ${generation.supersededByGeneration}` : ""}`).join("; ");
|
|
10894
|
+
lines.push(` superseded generations: ${summary}`);
|
|
10895
|
+
}
|
|
10896
|
+
lines.push(" audit: full publication trail in the .swarm events store (pr_feedback_publication_*, pr_feedback_push_attempt_*, pr_feedback_published)");
|
|
10897
|
+
return lines.join(`
|
|
10898
|
+
`);
|
|
10899
|
+
}
|
|
10900
|
+
var PUBLICATION_EVENT_TYPES = new Set([
|
|
10901
|
+
"pr_feedback_publication_armed",
|
|
10902
|
+
"pr_feedback_publication_migrated",
|
|
10903
|
+
"pr_feedback_push_attempt_started",
|
|
10904
|
+
"pr_feedback_publication_invalidated",
|
|
10905
|
+
"pr_feedback_published",
|
|
10906
|
+
"pr_feedback_publication_cancelled"
|
|
10907
|
+
]);
|
|
10908
|
+
function findDanglingLivePublicationGeneration(directory, sessionID) {
|
|
10909
|
+
let text;
|
|
10910
|
+
try {
|
|
10911
|
+
text = readCoreEvents(directory).text;
|
|
10912
|
+
} catch {
|
|
10913
|
+
return null;
|
|
10914
|
+
}
|
|
10915
|
+
if (!text.trim())
|
|
10916
|
+
return null;
|
|
10917
|
+
let dangling = null;
|
|
10918
|
+
for (const line of text.split(`
|
|
10919
|
+
`)) {
|
|
10920
|
+
if (!line.trim())
|
|
10921
|
+
continue;
|
|
10922
|
+
let event;
|
|
10923
|
+
try {
|
|
10924
|
+
event = JSON.parse(line);
|
|
10925
|
+
} catch {
|
|
10926
|
+
continue;
|
|
10927
|
+
}
|
|
10928
|
+
if (typeof event.type !== "string" || !PUBLICATION_EVENT_TYPES.has(event.type) || event.sessionID !== sessionID) {
|
|
10929
|
+
continue;
|
|
10930
|
+
}
|
|
10931
|
+
const generation = typeof event.generation === "number" ? event.generation : null;
|
|
10932
|
+
switch (event.type) {
|
|
10933
|
+
case "pr_feedback_publication_armed":
|
|
10934
|
+
case "pr_feedback_push_attempt_started":
|
|
10935
|
+
dangling = generation ? { generation } : dangling;
|
|
10936
|
+
break;
|
|
10937
|
+
case "pr_feedback_publication_migrated":
|
|
10938
|
+
if (event.outcome === "armed") {
|
|
10939
|
+
dangling = generation ? { generation } : dangling;
|
|
10940
|
+
} else {
|
|
10941
|
+
dangling = null;
|
|
10942
|
+
}
|
|
10943
|
+
break;
|
|
10944
|
+
default:
|
|
10945
|
+
dangling = null;
|
|
10946
|
+
break;
|
|
10947
|
+
}
|
|
10948
|
+
}
|
|
10949
|
+
return dangling;
|
|
10950
|
+
}
|
|
10951
|
+
function supersedeLivePublicationInPendingState(pending, reason) {
|
|
10952
|
+
const publication = pending.prFeedbackPublication;
|
|
10953
|
+
const active = publication?.active;
|
|
10954
|
+
const live = pending.prFeedbackReadyToPublish != null || active?.state === "armed" || active?.state === "push_in_flight";
|
|
10955
|
+
if (!live)
|
|
10956
|
+
return { state: pending, invalidationEvent: null };
|
|
10957
|
+
const now = isoNow();
|
|
10958
|
+
const attempts = (publication?.attempts ?? []).map((attempt) => attempt.result ? attempt : {
|
|
10959
|
+
...attempt,
|
|
10960
|
+
result: {
|
|
10961
|
+
outcome: "uncertain",
|
|
10962
|
+
exitStatus: "not-observed",
|
|
10963
|
+
diagnostic: `finalized by publication invalidation (${reason})`,
|
|
10964
|
+
postPush: { localHead: null, observedRemoteHead: null },
|
|
10965
|
+
completedAt: now
|
|
10966
|
+
}
|
|
10967
|
+
});
|
|
10968
|
+
const invalidatedActive = active ? {
|
|
10969
|
+
...active,
|
|
10970
|
+
state: "invalidated",
|
|
10971
|
+
invalidatedAt: now,
|
|
10972
|
+
invalidationReason: reason
|
|
10973
|
+
} : undefined;
|
|
10974
|
+
const nextState = {
|
|
10975
|
+
...pending,
|
|
10976
|
+
updatedAt: now,
|
|
10977
|
+
prFeedbackReadyToPublish: undefined,
|
|
10978
|
+
prFeedbackVerifications: undefined,
|
|
10979
|
+
prFeedbackGateBatches: undefined,
|
|
10980
|
+
prFeedbackScopes: undefined,
|
|
10981
|
+
prFeedbackPublication: active ? nextPublicationContainer(publication, invalidatedActive, [], attempts) : pending.prFeedbackPublication
|
|
10982
|
+
};
|
|
10983
|
+
const invalidationEvent = active ? {
|
|
10984
|
+
type: "pr_feedback_publication_invalidated",
|
|
10985
|
+
sessionID: pending.sessionID,
|
|
10986
|
+
generation: active.generation,
|
|
10987
|
+
reason,
|
|
10988
|
+
previousState: active.state,
|
|
10989
|
+
drift: null,
|
|
10990
|
+
revisionDigest: active.revisionDigest,
|
|
10991
|
+
localHead: active.localHead,
|
|
10992
|
+
remoteName: active.remoteName,
|
|
10993
|
+
remoteBranchRef: active.remoteBranchRef,
|
|
10994
|
+
supersededBatchIds: active.evidence.batches.map((b) => b.batchId)
|
|
10995
|
+
} : null;
|
|
10996
|
+
return { state: nextState, invalidationEvent };
|
|
10997
|
+
}
|
|
10998
|
+
function parseExactBoundPushIntent(command, armed) {
|
|
10999
|
+
if (hasUnsafeShellControlSyntax(command)) {
|
|
11000
|
+
return { ok: false, reason: "shell-syntax" };
|
|
11001
|
+
}
|
|
11002
|
+
if (!armed.remoteBranchRef.startsWith("refs/heads/")) {
|
|
11003
|
+
return { ok: false, reason: "unbound-target" };
|
|
11004
|
+
}
|
|
11005
|
+
const tokens = command.trim().split(/\s+/);
|
|
11006
|
+
if (tokens.length !== 4 || tokens[0].toLowerCase() !== "git" || tokens[1].toLowerCase() !== "push" || tokens.some((token) => /["'\\]/.test(token))) {
|
|
11007
|
+
return { ok: false, reason: "token-shape" };
|
|
11008
|
+
}
|
|
11009
|
+
const [remoteToken, refspecToken] = [tokens[2], tokens[3]];
|
|
11010
|
+
if (remoteToken.startsWith("-") || refspecToken.startsWith("-")) {
|
|
11011
|
+
return { ok: false, reason: "flag-or-option" };
|
|
11012
|
+
}
|
|
11013
|
+
if (/[:@]/.test(remoteToken) || remoteToken.includes("://")) {
|
|
11014
|
+
return { ok: false, reason: "credential-bearing-remote" };
|
|
11015
|
+
}
|
|
11016
|
+
const refspecParts = refspecToken.split(":");
|
|
11017
|
+
if (refspecParts.length !== 2) {
|
|
11018
|
+
return {
|
|
11019
|
+
ok: false,
|
|
11020
|
+
reason: refspecParts.length > 2 ? "token-shape" : "invalid-dest-ref"
|
|
11021
|
+
};
|
|
11022
|
+
}
|
|
11023
|
+
const [sourceToken, destToken] = refspecParts;
|
|
11024
|
+
if (!destToken.startsWith("refs/heads/") || destToken === "refs/heads/") {
|
|
11025
|
+
return { ok: false, reason: "invalid-dest-ref" };
|
|
11026
|
+
}
|
|
11027
|
+
if (sourceToken === "") {
|
|
11028
|
+
return { ok: false, reason: "delete-refspec" };
|
|
11029
|
+
}
|
|
11030
|
+
if (sourceToken.includes("*") || destToken.includes("*")) {
|
|
11031
|
+
return { ok: false, reason: "wildcard-refspec" };
|
|
11032
|
+
}
|
|
11033
|
+
if (remoteToken !== armed.remoteName) {
|
|
11034
|
+
return { ok: false, reason: "remote-mismatch" };
|
|
11035
|
+
}
|
|
11036
|
+
if (sourceToken !== armed.localHead) {
|
|
11037
|
+
return { ok: false, reason: "source-mismatch" };
|
|
11038
|
+
}
|
|
11039
|
+
if (destToken !== armed.remoteBranchRef) {
|
|
11040
|
+
return { ok: false, reason: "branch-mismatch" };
|
|
11041
|
+
}
|
|
11042
|
+
const intent = {
|
|
11043
|
+
remote: remoteToken,
|
|
11044
|
+
sourceSha: sourceToken,
|
|
11045
|
+
destRef: destToken
|
|
11046
|
+
};
|
|
11047
|
+
return {
|
|
11048
|
+
ok: true,
|
|
11049
|
+
intent,
|
|
11050
|
+
digest: createHash7("sha256").update(JSON.stringify(intent), "utf8").digest("hex")
|
|
11051
|
+
};
|
|
11052
|
+
}
|
|
11053
|
+
async function admitPrFeedbackPushAttempt(directory, sessionID, callID, intent, intentDigest) {
|
|
11054
|
+
const normalizedSessionID = normalizeSessionID(sessionID);
|
|
11055
|
+
await withSessionStateMutation(directory, normalizedSessionID, async () => {
|
|
11056
|
+
const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
|
|
11057
|
+
const active = state?.prFeedbackPublication?.active;
|
|
11058
|
+
if (!state || state.mode !== "PR_FEEDBACK" || !active) {
|
|
11059
|
+
throw new Error("BLOCKED: PR_FEEDBACK push admission requires an armed publication generation");
|
|
11060
|
+
}
|
|
11061
|
+
if (active.state !== "armed") {
|
|
11062
|
+
throw new Error(`BLOCKED: PR_FEEDBACK push admission requires the armed state, not ${active.state}`);
|
|
11063
|
+
}
|
|
11064
|
+
const check = await checkPublicationIdentity(directory, state, active);
|
|
11065
|
+
if (check.kind === "unresolvable") {
|
|
11066
|
+
throw new Error(`BLOCKED: PR_FEEDBACK could not verify the armed publication identity component "${check.component}" (${check.detail}); the push was not admitted`);
|
|
11067
|
+
}
|
|
11068
|
+
if (check.kind === "drift") {
|
|
11069
|
+
const invalidation = await applyPublicationInvalidationWhileLocked(directory, state, `drift:${check.component}`, { drift: check });
|
|
11070
|
+
throw new Error(`BLOCKED: PR_FEEDBACK publication generation ${invalidation.generation.generation} was INVALIDATED because approved content identity drifted (${check.component}: ${check.detail}). Rerun Stage A and every independent gate, then arm a fresh generation with complete_pr_workflow.`);
|
|
11071
|
+
}
|
|
11072
|
+
const now = isoNow();
|
|
11073
|
+
if (intent.remote !== active.remoteName || intent.sourceSha !== active.localHead || intent.destRef !== active.remoteBranchRef) {
|
|
11074
|
+
throw new Error("BLOCKED: PR_FEEDBACK push intent does not match the armed publication generation under the state lock; the push was not admitted");
|
|
11075
|
+
}
|
|
11076
|
+
const observedRemoteHead = await _test_exports2.resolveExactRemoteBranchHeadAsync(directory, active.remoteName, active.remoteBranchRef);
|
|
11077
|
+
const localHead = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
|
|
11078
|
+
const worktreeClean = await _test_exports2.resolveIsWorkingTreeCleanAsync(directory);
|
|
11079
|
+
const baseAttempt = {
|
|
11080
|
+
attemptId: randomUUID2(),
|
|
11081
|
+
generation: active.generation,
|
|
11082
|
+
sessionID: state.sessionID,
|
|
11083
|
+
callID,
|
|
11084
|
+
intentDigest,
|
|
11085
|
+
intent: {
|
|
11086
|
+
remote: intent.remote,
|
|
11087
|
+
sourceSha: intent.sourceSha,
|
|
11088
|
+
destRef: intent.destRef
|
|
11089
|
+
},
|
|
11090
|
+
prePush: {
|
|
11091
|
+
localHead: active.localHead,
|
|
11092
|
+
worktreeClean: worktreeClean === true,
|
|
11093
|
+
remoteName: active.remoteName,
|
|
11094
|
+
remoteBranchRef: active.remoteBranchRef,
|
|
11095
|
+
observedRemoteHead
|
|
11096
|
+
},
|
|
11097
|
+
startedAt: now
|
|
11098
|
+
};
|
|
11099
|
+
const remoteAlreadyAtApprovedHead = observedRemoteHead?.toLowerCase() === active.localHead.toLowerCase();
|
|
11100
|
+
if (remoteAlreadyAtApprovedHead) {
|
|
11101
|
+
const attempt = {
|
|
11102
|
+
...baseAttempt,
|
|
11103
|
+
result: {
|
|
11104
|
+
outcome: "completed",
|
|
11105
|
+
exitStatus: "not-observed",
|
|
11106
|
+
diagnostic: "remote branch already observed at the approved head (no-op push)",
|
|
11107
|
+
postPush: {
|
|
11108
|
+
localHead: localHead ?? null,
|
|
11109
|
+
observedRemoteHead: observedRemoteHead ?? null
|
|
11110
|
+
},
|
|
11111
|
+
completedAt: now
|
|
11112
|
+
}
|
|
11113
|
+
};
|
|
11114
|
+
const nextState2 = {
|
|
11115
|
+
...state,
|
|
11116
|
+
updatedAt: now,
|
|
11117
|
+
prFeedbackPublication: nextPublicationContainer(state.prFeedbackPublication, active, [], [...state.prFeedbackPublication?.attempts ?? [], attempt])
|
|
11118
|
+
};
|
|
11119
|
+
await writeStateWhileLocked(directory, nextState2);
|
|
11120
|
+
appendPublicationEvent(directory, {
|
|
11121
|
+
type: "pr_feedback_push_attempt_result",
|
|
11122
|
+
sessionID: state.sessionID,
|
|
11123
|
+
generation: active.generation,
|
|
11124
|
+
outcome: "completed",
|
|
11125
|
+
by: "no-op-observation",
|
|
11126
|
+
observedRemoteHead
|
|
11127
|
+
});
|
|
11128
|
+
return;
|
|
11129
|
+
}
|
|
11130
|
+
const nextState = {
|
|
11131
|
+
...state,
|
|
11132
|
+
updatedAt: now,
|
|
11133
|
+
prFeedbackPublication: nextPublicationContainer(state.prFeedbackPublication, { ...active, state: "push_in_flight" }, [], [...state.prFeedbackPublication?.attempts ?? [], baseAttempt])
|
|
11134
|
+
};
|
|
11135
|
+
await writeStateWhileLocked(directory, nextState);
|
|
11136
|
+
appendPublicationEvent(directory, {
|
|
11137
|
+
type: "pr_feedback_push_attempt_started",
|
|
11138
|
+
sessionID: state.sessionID,
|
|
11139
|
+
generation: active.generation,
|
|
11140
|
+
intentDigest,
|
|
11141
|
+
intent,
|
|
11142
|
+
observedRemoteHead
|
|
11143
|
+
});
|
|
11144
|
+
});
|
|
11145
|
+
const publication = await readPrWorkflowGateState(directory, normalizedSessionID);
|
|
11146
|
+
const attempts = publication?.prFeedbackPublication?.attempts ?? [];
|
|
11147
|
+
const last = attempts[attempts.length - 1];
|
|
11148
|
+
return last?.result?.outcome === "completed" ? { kind: "already-published-remotely" } : { kind: "started" };
|
|
11149
|
+
}
|
|
11150
|
+
function describeToolOutputText(output) {
|
|
11151
|
+
if (typeof output === "string")
|
|
11152
|
+
return output;
|
|
11153
|
+
if (output && typeof output === "object" && "output" in output && typeof output.output === "string") {
|
|
11154
|
+
return output.output;
|
|
11155
|
+
}
|
|
11156
|
+
try {
|
|
11157
|
+
return JSON.stringify(output) ?? "";
|
|
11158
|
+
} catch {
|
|
11159
|
+
return "";
|
|
11160
|
+
}
|
|
11161
|
+
}
|
|
11162
|
+
async function recordPrFeedbackPushAttemptResult(directory, input, command, output) {
|
|
11163
|
+
const normalizedTool = (normalizeToolName(input.tool) ?? input.tool).toLowerCase();
|
|
11164
|
+
if (normalizedTool !== "bash" && normalizedTool !== "shell")
|
|
11165
|
+
return;
|
|
11166
|
+
if (!/^\s*git\s+push/i.test(command))
|
|
11167
|
+
return;
|
|
11168
|
+
const normalizedSessionID = normalizeSessionID(input.sessionID);
|
|
11169
|
+
await withSessionStateMutation(directory, normalizedSessionID, async () => {
|
|
11170
|
+
const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
|
|
11171
|
+
const publication = state?.prFeedbackPublication;
|
|
11172
|
+
const active = publication?.active;
|
|
11173
|
+
if (!state || !publication || !active || active.state !== "push_in_flight" || !input.callID) {
|
|
11174
|
+
return;
|
|
11175
|
+
}
|
|
11176
|
+
const attemptIndex = publication.attempts.findIndex((attempt) => !attempt.result && attempt.callID === input.callID);
|
|
11177
|
+
if (attemptIndex < 0)
|
|
11178
|
+
return;
|
|
11179
|
+
const now = isoNow();
|
|
11180
|
+
const localHead = (await _test_exports2.resolveCurrentGitHeadAsync(directory))?.trim();
|
|
11181
|
+
const observedRemoteHead = await _test_exports2.resolveExactRemoteBranchHeadAsync(directory, active.remoteName, active.remoteBranchRef);
|
|
11182
|
+
const remoteVerifiedAtApprovedHead = observedRemoteHead?.toLowerCase() === active.localHead.toLowerCase();
|
|
11183
|
+
const metadataExit = output?.metadata?.exitCode;
|
|
11184
|
+
const exitStatus = typeof metadataExit === "number" && Number.isInteger(metadataExit) ? metadataExit : "not-observed";
|
|
11185
|
+
let outcome;
|
|
11186
|
+
if (remoteVerifiedAtApprovedHead) {
|
|
11187
|
+
outcome = "completed";
|
|
11188
|
+
} else if (exitStatus !== "not-observed" && exitStatus !== 0) {
|
|
11189
|
+
outcome = "rejected";
|
|
11190
|
+
} else {
|
|
11191
|
+
outcome = "uncertain";
|
|
11192
|
+
}
|
|
11193
|
+
const diagnostic = boundPublicationDiagnostic(remoteVerifiedAtApprovedHead ? `push result observed; remote branch verified at the approved head${exitStatus !== "not-observed" && exitStatus !== 0 ? ` (shell reported nonzero exit ${exitStatus}; the verified remote head is the publication truth)` : ""}` : `push result observed without remote verification at the approved head; exit status ${exitStatus === "not-observed" ? "not observed" : exitStatus}; output: ${describeToolOutputText(output)}`);
|
|
11194
|
+
const attempts = publication.attempts.map((attempt, index) => index === attemptIndex ? {
|
|
11195
|
+
...attempt,
|
|
11196
|
+
result: {
|
|
11197
|
+
outcome,
|
|
11198
|
+
exitStatus,
|
|
11199
|
+
diagnostic,
|
|
11200
|
+
postPush: {
|
|
11201
|
+
localHead: localHead ?? null,
|
|
11202
|
+
observedRemoteHead: observedRemoteHead ?? null
|
|
11203
|
+
},
|
|
11204
|
+
completedAt: now
|
|
11205
|
+
}
|
|
11206
|
+
} : attempt);
|
|
11207
|
+
const nextState = {
|
|
11208
|
+
...state,
|
|
11209
|
+
updatedAt: now,
|
|
11210
|
+
prFeedbackPublication: nextPublicationContainer(publication, { ...active, state: "armed" }, [], attempts)
|
|
11211
|
+
};
|
|
11212
|
+
await writeStateWhileLocked(directory, nextState);
|
|
11213
|
+
appendPublicationEvent(directory, {
|
|
11214
|
+
type: "pr_feedback_push_attempt_result",
|
|
11215
|
+
sessionID: state.sessionID,
|
|
11216
|
+
generation: active.generation,
|
|
11217
|
+
outcome,
|
|
11218
|
+
exitStatus,
|
|
11219
|
+
by: "tool-after",
|
|
11220
|
+
observedRemoteHead
|
|
11221
|
+
});
|
|
11222
|
+
});
|
|
11223
|
+
}
|
|
11224
|
+
async function cancelPrFeedbackPublication(directory, sessionID, reason) {
|
|
11225
|
+
const normalizedSessionID = normalizeSessionID(sessionID);
|
|
11226
|
+
let nextRevision = null;
|
|
11227
|
+
let cancelledGeneration = null;
|
|
11228
|
+
let cancelledAttemptsFinalized = 0;
|
|
11229
|
+
try {
|
|
11230
|
+
await withSessionStateMutation(directory, normalizedSessionID, async () => {
|
|
11231
|
+
const state = await readPrWorkflowGateStateFromDisk(directory, normalizedSessionID);
|
|
11232
|
+
const publication = state?.prFeedbackPublication;
|
|
11233
|
+
const active = publication?.active;
|
|
11234
|
+
if (!state || !publication || !active) {
|
|
11235
|
+
return;
|
|
11236
|
+
}
|
|
11237
|
+
if (active.state !== "armed" && active.state !== "push_in_flight" && active.state !== "invalidated") {
|
|
11238
|
+
return;
|
|
11239
|
+
}
|
|
11240
|
+
const now = isoNow();
|
|
11241
|
+
const observedRemoteHead = await _test_exports2.resolveExactRemoteBranchHeadAsync(directory, active.remoteName, active.remoteBranchRef);
|
|
11242
|
+
const attempts = publication.attempts.map((attempt) => attempt.result ? attempt : {
|
|
11243
|
+
...attempt,
|
|
11244
|
+
result: {
|
|
11245
|
+
outcome: "cancelled",
|
|
11246
|
+
exitStatus: "not-observed",
|
|
11247
|
+
diagnostic: "finalized by publication cancellation",
|
|
11248
|
+
postPush: { localHead: null, observedRemoteHead },
|
|
11249
|
+
completedAt: now
|
|
11250
|
+
}
|
|
11251
|
+
});
|
|
11252
|
+
const cancelled = {
|
|
11253
|
+
...active,
|
|
11254
|
+
state: "cancelled_without_publication",
|
|
11255
|
+
cancelledAt: now,
|
|
11256
|
+
invalidationReason: active.invalidationReason ?? `cancelled:${reason}`
|
|
11257
|
+
};
|
|
11258
|
+
const nextState = {
|
|
11259
|
+
...state,
|
|
11260
|
+
updatedAt: now,
|
|
11261
|
+
prFeedbackReadyToPublish: undefined,
|
|
11262
|
+
prFeedbackPublication: nextPublicationContainer(publication, cancelled, [], attempts)
|
|
11263
|
+
};
|
|
11264
|
+
const written = await writeStateWhileLocked(directory, nextState);
|
|
11265
|
+
nextRevision = written.revision;
|
|
11266
|
+
cancelledGeneration = active.generation;
|
|
11267
|
+
cancelledAttemptsFinalized = attempts.filter((attempt) => attempt.result?.outcome === "cancelled").length;
|
|
11268
|
+
});
|
|
11269
|
+
} catch {}
|
|
11270
|
+
appendPublicationEvent(directory, {
|
|
11271
|
+
type: "pr_feedback_publication_cancelled",
|
|
11272
|
+
sessionID: normalizedSessionID,
|
|
11273
|
+
...cancelledGeneration !== null ? { generation: cancelledGeneration } : {},
|
|
11274
|
+
reason,
|
|
11275
|
+
...cancelledAttemptsFinalized > 0 ? { attemptsFinalized: cancelledAttemptsFinalized } : {}
|
|
11276
|
+
});
|
|
11277
|
+
return nextRevision;
|
|
11278
|
+
}
|
|
10162
11279
|
var PR_REVIEW_HANDOFF_RELATIVE_PATH_PATTERN = /^pr-review\/([A-Za-z0-9][A-Za-z0-9._-]{0,127})\/feedback-handoff\.json$/;
|
|
10163
11280
|
var PR_REVIEW_FEEDBACK_CONSENT_MAX_BYTES = 64 * 1024;
|
|
10164
11281
|
var PR_REVIEW_RUN_RESERVATION_MAX_BYTES = 16 * 1024;
|
|
@@ -10281,7 +11398,7 @@ function prReviewFeedbackConsentRelativePath(runId) {
|
|
|
10281
11398
|
return `pr-review/${runId}/feedback-consent.json`;
|
|
10282
11399
|
}
|
|
10283
11400
|
function hashPrReviewFindingIds(ids) {
|
|
10284
|
-
return
|
|
11401
|
+
return createHash7("sha256").update([...new Set(ids)].sort().join("\x00"), "utf8").digest("hex");
|
|
10285
11402
|
}
|
|
10286
11403
|
async function readPrReviewRunReservation(directory, runId) {
|
|
10287
11404
|
try {
|
|
@@ -10353,7 +11470,7 @@ async function readPrReviewFeedbackHandoffArtifact(directory, relativePath) {
|
|
|
10353
11470
|
}
|
|
10354
11471
|
return {
|
|
10355
11472
|
artifact: parsed.data,
|
|
10356
|
-
digest:
|
|
11473
|
+
digest: createHash7("sha256").update(raw, "utf8").digest("hex")
|
|
10357
11474
|
};
|
|
10358
11475
|
}
|
|
10359
11476
|
var PrReviewFindingProjectionSchema = exports_external.object({
|
|
@@ -10414,7 +11531,7 @@ function assertMatchingPrReviewFeedbackConsent(record, input) {
|
|
|
10414
11531
|
}
|
|
10415
11532
|
}
|
|
10416
11533
|
function workflowIdentity(state) {
|
|
10417
|
-
return state.workflowInstanceId ?? `legacy-${
|
|
11534
|
+
return state.workflowInstanceId ?? `legacy-${createHash7("sha256").update(`${state.sessionID}\x00${state.mode}\x00${state.activatedAt}`).digest("hex").slice(0, 32)}`;
|
|
10418
11535
|
}
|
|
10419
11536
|
function sameHandoffIds(left, right) {
|
|
10420
11537
|
const normalizedLeft = [...new Set(left)].sort();
|
|
@@ -10687,6 +11804,21 @@ var _test_exports2 = {
|
|
|
10687
11804
|
resolveCurrentUpstreamPushTarget,
|
|
10688
11805
|
resolveCurrentUpstreamPushTargetAsync,
|
|
10689
11806
|
resolveCurrentUpstreamRemoteRef,
|
|
11807
|
+
resolveCurrentLocalHeadRefAsync,
|
|
11808
|
+
resolveRemoteUrlIdentity,
|
|
11809
|
+
resolveRemoteUrlIdentityAsync,
|
|
11810
|
+
parseExactBoundPushIntent,
|
|
11811
|
+
admitPrFeedbackPushAttempt,
|
|
11812
|
+
recordPrFeedbackPushAttemptResult,
|
|
11813
|
+
reconcileForeignInFlightAttempt,
|
|
11814
|
+
ensurePublicationGenerationCurrent,
|
|
11815
|
+
invalidatePublicationGeneration,
|
|
11816
|
+
invalidatePrFeedbackPublication,
|
|
11817
|
+
cancelPrFeedbackPublication,
|
|
11818
|
+
buildPublicationEvidenceJoin,
|
|
11819
|
+
nextPublicationContainer,
|
|
11820
|
+
supersedeLivePublicationInPendingState,
|
|
11821
|
+
describePrWorkflowPublicationSection,
|
|
10690
11822
|
resolveExactRemoteBranchHead,
|
|
10691
11823
|
resolveExactRemoteBranchHeadAsync,
|
|
10692
11824
|
resolveCommitCountSince,
|
|
@@ -10778,6 +11910,7 @@ var PR_REVIEW_CONTROLLER_TOOLS = new Set([
|
|
|
10778
11910
|
"write_pr_review_trigger_eval"
|
|
10779
11911
|
]);
|
|
10780
11912
|
var PR_FEEDBACK_CONTROLLER_TOOLS = new Set([
|
|
11913
|
+
"invalidate_pr_feedback_publication",
|
|
10781
11914
|
"prepare_pr_feedback_scope",
|
|
10782
11915
|
"run_pr_feedback_stage_a"
|
|
10783
11916
|
]);
|
|
@@ -10936,6 +12069,16 @@ function normalizePrHeadSha(prHeadSha) {
|
|
|
10936
12069
|
}
|
|
10937
12070
|
return normalized;
|
|
10938
12071
|
}
|
|
12072
|
+
async function currentPrFeedbackRevisionDigest(directory, state) {
|
|
12073
|
+
if (!state.prHeadSha) {
|
|
12074
|
+
throw new Error("BLOCKED: PR_FEEDBACK revision binding requires pr_head_sha");
|
|
12075
|
+
}
|
|
12076
|
+
const resolved = await resolvePrWorkflowRevisionDigestForGate(directory, state.prHeadSha);
|
|
12077
|
+
if (!resolved.ok) {
|
|
12078
|
+
throw new Error("BLOCKED: PR_FEEDBACK could not compute a bounded current-revision digest" + ` for pr_head_sha "${state.prHeadSha}"; ${describePrWorkflowRevisionDigestFailure(resolved)}`);
|
|
12079
|
+
}
|
|
12080
|
+
return resolved.digest;
|
|
12081
|
+
}
|
|
10939
12082
|
function describePrWorkflowRevisionDigestFailure(failure) {
|
|
10940
12083
|
const detail = failure.detail ? ` (${failure.detail})` : "";
|
|
10941
12084
|
switch (failure.reason) {
|
|
@@ -12016,7 +13159,7 @@ function validateReviewerVerdictFields(fields) {
|
|
|
12016
13159
|
return parsed.success ? [...parsed.data] : null;
|
|
12017
13160
|
}
|
|
12018
13161
|
function reviewerVerdictRowDigest(fields) {
|
|
12019
|
-
return
|
|
13162
|
+
return createHash7("sha256").update(fields.join("\x00")).digest("hex");
|
|
12020
13163
|
}
|
|
12021
13164
|
function parseLaneItemVerdicts(text, itemIds, phase, reviewerClaims) {
|
|
12022
13165
|
return parsePrReviewVerdictRows(text, itemIds, phase, reviewerClaims).parsed;
|
|
@@ -12605,10 +13748,13 @@ async function readPrWorkflowGateStateForRecovery(directory, sessionID) {
|
|
|
12605
13748
|
const salvagedUpdatedAt = exports_external.string().min(1).safeParse(rawRecord.updatedAt);
|
|
12606
13749
|
const armedKeyPresent = rawRecord.prFeedbackReadyToPublish !== undefined;
|
|
12607
13750
|
const salvagedArmed = PrFeedbackReadyToPublishRecordSchema.safeParse(rawRecord.prFeedbackReadyToPublish);
|
|
13751
|
+
const publicationKeyPresent = rawRecord.prFeedbackPublication !== undefined;
|
|
13752
|
+
const salvagedPublication = PrFeedbackPublicationStateSchema.safeParse(rawRecord.prFeedbackPublication);
|
|
13753
|
+
const publicationShapeUnreadable = publicationKeyPresent && !salvagedPublication.success;
|
|
12608
13754
|
const salvagedCheckoutRecovery = PrWorkflowCheckoutRecoveryRecordSchema.safeParse(rawRecord.checkoutRecovery);
|
|
12609
|
-
const armedShapeUnreadable = armedKeyPresent && !salvagedArmed.success;
|
|
13755
|
+
const armedShapeUnreadable = armedKeyPresent && !salvagedArmed.success || publicationShapeUnreadable;
|
|
12610
13756
|
const schemaErrors = parsed.error.issues.slice(0, MAX_SALVAGED_SCHEMA_ERRORS).map((issue) => boundSalvagedSchemaError(`${issue.path.join(".") || "(root)"}: ${issue.message}`));
|
|
12611
|
-
const disclosure = `DEGRADED: PR workflow gate state for session "${normalizedSessionID}" failed schema validation ` + `and was SALVAGED for recovery only (abort/status; write and completion paths still refuse it). ` + `Schema errors: ${schemaErrors.join("; ")}.` + (salvagedRevision.success ? "" : " state revision unsalvageable.") + (armedShapeUnreadable ? " prFeedbackReadyToPublish is present but unreadable; treated as ARMED (fail-closed)." : "");
|
|
13757
|
+
const disclosure = `DEGRADED: PR workflow gate state for session "${normalizedSessionID}" failed schema validation ` + `and was SALVAGED for recovery only (abort/status; write and completion paths still refuse it). ` + `Schema errors: ${schemaErrors.join("; ")}.` + (salvagedRevision.success ? "" : " state revision unsalvageable.") + (armedShapeUnreadable ? " prFeedbackReadyToPublish is present but unreadable; treated as ARMED (fail-closed)." : "") + (publicationShapeUnreadable ? " prFeedbackPublication is present but unreadable; treated as ARMED (fail-closed)." : "");
|
|
12612
13758
|
return {
|
|
12613
13759
|
state: {
|
|
12614
13760
|
schemaVersion: GATE_SCHEMA_VERSION,
|
|
@@ -12619,6 +13765,7 @@ async function readPrWorkflowGateStateForRecovery(directory, sessionID) {
|
|
|
12619
13765
|
updatedAt: salvagedUpdatedAt.success ? salvagedUpdatedAt.data : isoNow(),
|
|
12620
13766
|
...salvagedHead.success ? { prHeadSha: salvagedHead.data } : {},
|
|
12621
13767
|
...salvagedArmed.success ? { prFeedbackReadyToPublish: salvagedArmed.data } : {},
|
|
13768
|
+
...salvagedPublication.success ? { prFeedbackPublication: salvagedPublication.data } : {},
|
|
12622
13769
|
...salvagedCheckoutRecovery.success ? { checkoutRecovery: salvagedCheckoutRecovery.data } : {}
|
|
12623
13770
|
},
|
|
12624
13771
|
salvaged: true,
|
|
@@ -12659,7 +13806,7 @@ function workflowGateStateRelativePath(sessionID) {
|
|
|
12659
13806
|
function prWorkflowSessionFileStem(sessionID) {
|
|
12660
13807
|
const normalized = normalizeSessionID(sessionID);
|
|
12661
13808
|
const slug = normalized.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 80) || "session";
|
|
12662
|
-
const digest2 =
|
|
13809
|
+
const digest2 = createHash7("sha256").update(normalized).digest("hex").slice(0, 12);
|
|
12663
13810
|
return `${slug}-${digest2}`;
|
|
12664
13811
|
}
|
|
12665
13812
|
function normalizeSessionID(sessionID) {
|
|
@@ -12829,6 +13976,14 @@ var USAGE = [
|
|
|
12829
13976
|
"Refuses while the workflow is armed for publication (call complete_pr_workflow",
|
|
12830
13977
|
"instead) or while PR workflow lanes are still in flight (collect their results first).",
|
|
12831
13978
|
"",
|
|
13979
|
+
"Armed publication (issue #2108): to CHANGE approved content after arming, the agent",
|
|
13980
|
+
"should use the invalidate_pr_feedback_publication tool (audited invalidation; the",
|
|
13981
|
+
"full Stage A + independent-gate ladder re-runs). To CANCEL an armed PR_FEEDBACK",
|
|
13982
|
+
'workflow without publication, the agent tool supports kind "cancel-publication" with',
|
|
13983
|
+
"cancel_publication: true and a reason \u2014 the publication generation is recorded as",
|
|
13984
|
+
"cancelled_without_publication (terminal; never grants push authority) before the gate",
|
|
13985
|
+
"clears. A plain (recovery or force) abort never clears an armed window.",
|
|
13986
|
+
"",
|
|
12832
13987
|
"Lane liveness (issue #2251): a lane past the 30-minute staleness horizon whose",
|
|
12833
13988
|
"session the host still reports as busy or retrying is RETAINED rather than settled,",
|
|
12834
13989
|
"and keeps blocking every exit. Because nothing ever makes such a lane go idle on a",
|
|
@@ -12881,11 +14036,11 @@ ${USAGE}`;
|
|
|
12881
14036
|
}
|
|
12882
14037
|
|
|
12883
14038
|
// src/services/spec-drift-recovery.ts
|
|
12884
|
-
import { createHash as
|
|
14039
|
+
import { createHash as createHash8 } from "crypto";
|
|
12885
14040
|
import { mkdir as mkdir4, readFile as readFile4, unlink as unlink2 } from "fs/promises";
|
|
12886
14041
|
import { dirname as dirname10 } from "path";
|
|
12887
14042
|
var SPEC_DRIFT_RECOVERY_AGENT = "spec-drift-recovery";
|
|
12888
|
-
var
|
|
14043
|
+
var _internals17 = {
|
|
12889
14044
|
appendEvent,
|
|
12890
14045
|
assertProjectRoot,
|
|
12891
14046
|
bunWrite,
|
|
@@ -12910,7 +14065,7 @@ function now() {
|
|
|
12910
14065
|
return new Date().toISOString();
|
|
12911
14066
|
}
|
|
12912
14067
|
function sha2562(text) {
|
|
12913
|
-
return
|
|
14068
|
+
return createHash8("sha256").update(text, "utf-8").digest("hex");
|
|
12914
14069
|
}
|
|
12915
14070
|
function parseMarker(raw) {
|
|
12916
14071
|
try {
|
|
@@ -12969,22 +14124,22 @@ async function writeWal3(walPath, wal) {
|
|
|
12969
14124
|
}
|
|
12970
14125
|
async function verifySnapshot(snapshotPath, currentSpec) {
|
|
12971
14126
|
if (!currentSpec) {
|
|
12972
|
-
await
|
|
12973
|
-
const stillExists = await
|
|
14127
|
+
await _internals17.unlinkIfExists(snapshotPath);
|
|
14128
|
+
const stillExists = await _internals17.readFileText(snapshotPath) !== null;
|
|
12974
14129
|
if (stillExists) {
|
|
12975
14130
|
throw new Error("spec snapshot verification failed: snapshot still exists after delete");
|
|
12976
14131
|
}
|
|
12977
14132
|
return;
|
|
12978
14133
|
}
|
|
12979
14134
|
await atomicWriteFile(snapshotPath, currentSpec.content);
|
|
12980
|
-
const written = await
|
|
14135
|
+
const written = await _internals17.readFileText(snapshotPath);
|
|
12981
14136
|
if (written !== currentSpec.content) {
|
|
12982
14137
|
throw new Error("spec snapshot verification failed: snapshot content does not match effective spec");
|
|
12983
14138
|
}
|
|
12984
14139
|
}
|
|
12985
14140
|
async function ensureSnapshotEvent(directory, plan, transitionId) {
|
|
12986
|
-
const ledgerPath =
|
|
12987
|
-
const raw = await
|
|
14141
|
+
const ledgerPath = _internals17.validateSwarmPath(directory, "plan-ledger.jsonl");
|
|
14142
|
+
const raw = await _internals17.readFileText(ledgerPath);
|
|
12988
14143
|
if (raw !== null) {
|
|
12989
14144
|
for (const line of raw.split(`
|
|
12990
14145
|
`)) {
|
|
@@ -13004,17 +14159,17 @@ async function ensureSnapshotEvent(directory, plan, transitionId) {
|
|
|
13004
14159
|
}
|
|
13005
14160
|
}
|
|
13006
14161
|
}
|
|
13007
|
-
await
|
|
14162
|
+
await _internals17.takeSnapshotEvent(directory, plan, {
|
|
13008
14163
|
source: "spec_drift_recovery",
|
|
13009
14164
|
approvalMetadata: { specDriftTransitionId: transitionId }
|
|
13010
14165
|
});
|
|
13011
14166
|
}
|
|
13012
14167
|
async function appendEvent(directory, event) {
|
|
13013
|
-
const existing = await
|
|
14168
|
+
const existing = await _internals17.verifyEventPresence(directory, event.type, event.transitionId);
|
|
13014
14169
|
if (existing)
|
|
13015
14170
|
return;
|
|
13016
14171
|
appendCoreEventSync(directory, { ...event }, { dedupeOnAuthorityKey: true });
|
|
13017
|
-
const verified = await
|
|
14172
|
+
const verified = await _internals17.verifyEventPresence(directory, event.type, event.transitionId);
|
|
13018
14173
|
if (!verified) {
|
|
13019
14174
|
throw new Error(`spec drift audit verification failed for transition ${event.transitionId}`);
|
|
13020
14175
|
}
|
|
@@ -13036,7 +14191,7 @@ function buildRecoveryEvent(args) {
|
|
|
13036
14191
|
if (args.mode === "acknowledge") {
|
|
13037
14192
|
return {
|
|
13038
14193
|
type: "spec_drift_acknowledged",
|
|
13039
|
-
timestamp:
|
|
14194
|
+
timestamp: _internals17.now(),
|
|
13040
14195
|
phase: args.phase,
|
|
13041
14196
|
planTitle: args.planTitle,
|
|
13042
14197
|
acknowledgedBy: args.actor === "spec_write" ? "unknown" : args.actor,
|
|
@@ -13048,7 +14203,7 @@ function buildRecoveryEvent(args) {
|
|
|
13048
14203
|
}
|
|
13049
14204
|
return {
|
|
13050
14205
|
type: "spec_drift_repaired",
|
|
13051
|
-
timestamp:
|
|
14206
|
+
timestamp: _internals17.now(),
|
|
13052
14207
|
phase: args.phase,
|
|
13053
14208
|
planTitle: args.planTitle,
|
|
13054
14209
|
repairedBy: args.actor,
|
|
@@ -13059,11 +14214,11 @@ function buildRecoveryEvent(args) {
|
|
|
13059
14214
|
};
|
|
13060
14215
|
}
|
|
13061
14216
|
async function reconcileSpecDrift(directory, options) {
|
|
13062
|
-
|
|
13063
|
-
const markerPath =
|
|
13064
|
-
const walPath =
|
|
13065
|
-
const snapshotPath =
|
|
13066
|
-
const markerMaybe = await
|
|
14217
|
+
_internals17.assertProjectRoot(directory);
|
|
14218
|
+
const markerPath = _internals17.validateSwarmPath(directory, "spec-staleness.json");
|
|
14219
|
+
const walPath = _internals17.validateSwarmPath(directory, "spec-drift-recovery.json");
|
|
14220
|
+
const snapshotPath = _internals17.validateSwarmPath(directory, "spec-snapshot.md");
|
|
14221
|
+
const markerMaybe = await _internals17.readFileText(markerPath);
|
|
13067
14222
|
if (markerMaybe === null) {
|
|
13068
14223
|
return {
|
|
13069
14224
|
status: "no_marker",
|
|
@@ -13071,7 +14226,7 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13071
14226
|
message: "No spec drift detected."
|
|
13072
14227
|
};
|
|
13073
14228
|
}
|
|
13074
|
-
const specLockResult = options.specLockAlreadyHeld ? null : await
|
|
14229
|
+
const specLockResult = options.specLockAlreadyHeld ? null : await _internals17.tryAcquireLock(directory, "spec.md", SPEC_DRIFT_RECOVERY_AGENT, `spec-${options.mode}-${Date.now()}`);
|
|
13075
14230
|
if (specLockResult && !specLockResult.acquired) {
|
|
13076
14231
|
return {
|
|
13077
14232
|
status: "retry_later",
|
|
@@ -13081,7 +14236,7 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13081
14236
|
}
|
|
13082
14237
|
let lockResult;
|
|
13083
14238
|
try {
|
|
13084
|
-
lockResult = await
|
|
14239
|
+
lockResult = await _internals17.tryAcquireLock(directory, "plan.json", SPEC_DRIFT_RECOVERY_AGENT, `${options.mode}-${Date.now()}`);
|
|
13085
14240
|
} catch (error2) {
|
|
13086
14241
|
if (specLockResult?.acquired && specLockResult.lock._release) {
|
|
13087
14242
|
await specLockResult.lock._release().catch(() => {});
|
|
@@ -13107,7 +14262,7 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13107
14262
|
let errorNewHash;
|
|
13108
14263
|
try {
|
|
13109
14264
|
try {
|
|
13110
|
-
const authoritativeMarkerRaw = await
|
|
14265
|
+
const authoritativeMarkerRaw = await _internals17.readFileText(markerPath);
|
|
13111
14266
|
if (authoritativeMarkerRaw === null) {
|
|
13112
14267
|
return {
|
|
13113
14268
|
status: "no_marker",
|
|
@@ -13115,14 +14270,14 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13115
14270
|
message: "No spec drift detected."
|
|
13116
14271
|
};
|
|
13117
14272
|
}
|
|
13118
|
-
const marker =
|
|
14273
|
+
const marker = _internals17.parseMarker(authoritativeMarkerRaw);
|
|
13119
14274
|
if (!marker) {
|
|
13120
14275
|
return buildCorruptMarkerResult(options.mode);
|
|
13121
14276
|
}
|
|
13122
14277
|
errorMarker = marker;
|
|
13123
14278
|
const markerHash = sha2562(authoritativeMarkerRaw);
|
|
13124
|
-
const existingWalRaw = await
|
|
13125
|
-
const existingWal = existingWalRaw === null ? null :
|
|
14279
|
+
const existingWalRaw = await _internals17.readFileText(walPath);
|
|
14280
|
+
const existingWal = existingWalRaw === null ? null : _internals17.parseWal(existingWalRaw);
|
|
13126
14281
|
if (existingWalRaw !== null && !existingWal) {
|
|
13127
14282
|
return {
|
|
13128
14283
|
status: "failed",
|
|
@@ -13132,7 +14287,7 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13132
14287
|
planTitle: marker.planTitle
|
|
13133
14288
|
};
|
|
13134
14289
|
}
|
|
13135
|
-
const currentSpec =
|
|
14290
|
+
const currentSpec = _internals17.readEffectiveSpecSync(directory);
|
|
13136
14291
|
const proposedNewHash = currentSpec?.hash ?? null;
|
|
13137
14292
|
const proposedTransitionId = buildTransitionId(options.mode, markerHash, marker.specHash_plan, proposedNewHash);
|
|
13138
14293
|
const proposedWal = {
|
|
@@ -13147,7 +14302,7 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13147
14302
|
newHash: proposedNewHash,
|
|
13148
14303
|
specContent: currentSpec?.content ?? null,
|
|
13149
14304
|
actor: options.actor,
|
|
13150
|
-
recordedAt:
|
|
14305
|
+
recordedAt: _internals17.now()
|
|
13151
14306
|
};
|
|
13152
14307
|
const markerReplacedDuringPrepared = existingWal?.state === "PREPARED" && existingWal.markerHash !== markerHash;
|
|
13153
14308
|
const wal = existingWal?.state === "PREPARED" || existingWal?.markerHash === markerHash ? existingWal : proposedWal;
|
|
@@ -13156,12 +14311,12 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13156
14311
|
errorTransitionId = transitionId;
|
|
13157
14312
|
errorNewHash = newHash;
|
|
13158
14313
|
if (wal === proposedWal) {
|
|
13159
|
-
await
|
|
14314
|
+
await _internals17.writeWal(walPath, wal);
|
|
13160
14315
|
}
|
|
13161
14316
|
if (wal.newHash === null !== (wal.specContent === null) || wal.specContent !== null && sha2562(wal.specContent) !== wal.newHash) {
|
|
13162
14317
|
throw new Error(`Spec drift recovery WAL ${transitionId} has inconsistent captured spec content`);
|
|
13163
14318
|
}
|
|
13164
|
-
let plan = await
|
|
14319
|
+
let plan = await _internals17.loadPlanJsonOnly(directory);
|
|
13165
14320
|
if (!plan) {
|
|
13166
14321
|
return {
|
|
13167
14322
|
status: "failed",
|
|
@@ -13192,13 +14347,13 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13192
14347
|
}
|
|
13193
14348
|
if (planMatchesOld) {
|
|
13194
14349
|
plan.specHash = newHash ?? undefined;
|
|
13195
|
-
await
|
|
14350
|
+
await _internals17.savePlan(directory, plan, {
|
|
13196
14351
|
planLockAlreadyHeld: true
|
|
13197
14352
|
});
|
|
13198
|
-
plan = await
|
|
14353
|
+
plan = await _internals17.loadPlanJsonOnly(directory) ?? plan;
|
|
13199
14354
|
}
|
|
13200
|
-
await
|
|
13201
|
-
await
|
|
14355
|
+
await _internals17.ensureSnapshotEvent(directory, plan, transitionId);
|
|
14356
|
+
await _internals17.verifySnapshot(snapshotPath, wal.specContent === null ? null : { content: wal.specContent });
|
|
13202
14357
|
const event = buildRecoveryEvent({
|
|
13203
14358
|
mode: wal.mode,
|
|
13204
14359
|
actor: wal.actor,
|
|
@@ -13209,15 +14364,15 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13209
14364
|
previousHash: wal.previousHash,
|
|
13210
14365
|
transitionId
|
|
13211
14366
|
});
|
|
13212
|
-
await
|
|
13213
|
-
await
|
|
14367
|
+
await _internals17.appendEvent(directory, event);
|
|
14368
|
+
await _internals17.writeWal(walPath, { ...wal, state: "COMMITTED" });
|
|
13214
14369
|
}
|
|
13215
14370
|
if (markerReplacedDuringPrepared) {
|
|
13216
14371
|
const preservedMarker = {
|
|
13217
14372
|
...marker,
|
|
13218
14373
|
specHash_plan: newHash,
|
|
13219
14374
|
reason: `prior prepared drift recovery committed before this marker: ${marker.reason}`,
|
|
13220
|
-
timestamp:
|
|
14375
|
+
timestamp: _internals17.now()
|
|
13221
14376
|
};
|
|
13222
14377
|
await atomicWriteFile(markerPath, `${JSON.stringify(preservedMarker, null, 2)}
|
|
13223
14378
|
`);
|
|
@@ -13232,7 +14387,7 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13232
14387
|
transitionId
|
|
13233
14388
|
};
|
|
13234
14389
|
}
|
|
13235
|
-
const latestSpec =
|
|
14390
|
+
const latestSpec = _internals17.readEffectiveSpecSync(directory);
|
|
13236
14391
|
if ((latestSpec?.hash ?? null) !== newHash) {
|
|
13237
14392
|
const refreshedMarker = {
|
|
13238
14393
|
planTitle: wal.planTitle,
|
|
@@ -13240,7 +14395,7 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13240
14395
|
specHash_plan: newHash,
|
|
13241
14396
|
specHash_current: latestSpec?.hash ?? null,
|
|
13242
14397
|
reason: "spec changed while drift recovery was committing",
|
|
13243
|
-
timestamp:
|
|
14398
|
+
timestamp: _internals17.now()
|
|
13244
14399
|
};
|
|
13245
14400
|
await atomicWriteFile(markerPath, `${JSON.stringify(refreshedMarker, null, 2)}
|
|
13246
14401
|
`);
|
|
@@ -13256,8 +14411,8 @@ async function reconcileSpecDrift(directory, options) {
|
|
|
13256
14411
|
};
|
|
13257
14412
|
}
|
|
13258
14413
|
try {
|
|
13259
|
-
await
|
|
13260
|
-
|
|
14414
|
+
await _internals17.unlinkIfExists(markerPath);
|
|
14415
|
+
_internals17.invalidateCachedArtifact(markerPath);
|
|
13261
14416
|
} catch (error2) {
|
|
13262
14417
|
return {
|
|
13263
14418
|
status: "cleanup_pending",
|
|
@@ -13442,7 +14597,7 @@ ${USAGE2}`;
|
|
|
13442
14597
|
|
|
13443
14598
|
// src/security/write-authority.ts
|
|
13444
14599
|
import { AsyncLocalStorage } from "async_hooks";
|
|
13445
|
-
import { createHash as
|
|
14600
|
+
import { createHash as createHash9, randomUUID as randomUUID3 } from "crypto";
|
|
13446
14601
|
import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
|
|
13447
14602
|
import * as path13 from "path";
|
|
13448
14603
|
var DEFAULT_TTL_MS = 30 * 60 * 1000;
|
|
@@ -13549,7 +14704,7 @@ function leastPrivilege(left, right) {
|
|
|
13549
14704
|
return ORIGIN_RANK[left.origin] <= ORIGIN_RANK[right.origin] ? left : right;
|
|
13550
14705
|
}
|
|
13551
14706
|
function computeWriteApprovalHash(input) {
|
|
13552
|
-
return
|
|
14707
|
+
return createHash9("sha256").update(stableSerialize(input)).digest("hex");
|
|
13553
14708
|
}
|
|
13554
14709
|
function getCurrentWriteAuthority() {
|
|
13555
14710
|
const extent = authorityStore.getStore();
|
|
@@ -13754,7 +14909,7 @@ ${USAGE3}`;
|
|
|
13754
14909
|
|
|
13755
14910
|
// src/commands/archive.ts
|
|
13756
14911
|
init_loader();
|
|
13757
|
-
var
|
|
14912
|
+
var _internals18 = {
|
|
13758
14913
|
now: () => new Date
|
|
13759
14914
|
};
|
|
13760
14915
|
function artifactLabel(artifact) {
|
|
@@ -13810,7 +14965,7 @@ async function handleArchiveCommand(directory, args) {
|
|
|
13810
14965
|
const report = await archiveEvidence(directory, maxAgeDays, maxBundles, {
|
|
13811
14966
|
report: true,
|
|
13812
14967
|
dryRun,
|
|
13813
|
-
now:
|
|
14968
|
+
now: _internals18.now(),
|
|
13814
14969
|
cacheMaxBytes,
|
|
13815
14970
|
cacheMaxRecords
|
|
13816
14971
|
});
|
|
@@ -15097,7 +16252,7 @@ var SHELL_METACHARACTERS = /[;|&$`(){}<>!'"]/;
|
|
|
15097
16252
|
var SAFE_LABEL_PATTERN = /^[a-zA-Z0-9_ -]+$/;
|
|
15098
16253
|
var CONTROL_CHAR_PATTERN = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/;
|
|
15099
16254
|
var NON_ASCII_PATTERN = /[^\x20-\x7E]/;
|
|
15100
|
-
var
|
|
16255
|
+
var _internals19 = {
|
|
15101
16256
|
tryAcquireLock,
|
|
15102
16257
|
loadPlan,
|
|
15103
16258
|
gitExec,
|
|
@@ -15240,11 +16395,11 @@ function upsertTaskCompletionCheckpointEntry(directory, log2, entry, maxCheckpoi
|
|
|
15240
16395
|
}
|
|
15241
16396
|
}
|
|
15242
16397
|
function stageAllExcludingSwarm(directory) {
|
|
15243
|
-
|
|
16398
|
+
_internals19.gitExec(["add", "--all", "--", ...NON_SWARM_COMMIT_PATHSPEC], directory);
|
|
15244
16399
|
}
|
|
15245
16400
|
function gitExec(args, cwd) {
|
|
15246
16401
|
for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
|
|
15247
|
-
const result = child_process.spawnSync(
|
|
16402
|
+
const result = child_process.spawnSync(_internals19.resolveGitExecutable(), args, {
|
|
15248
16403
|
cwd,
|
|
15249
16404
|
encoding: "utf-8",
|
|
15250
16405
|
timeout: GIT_TIMEOUT_MS2,
|
|
@@ -15301,7 +16456,7 @@ function isGitRepo2(directory) {
|
|
|
15301
16456
|
}
|
|
15302
16457
|
}
|
|
15303
16458
|
function findCommitByExactSubject(directory, subject) {
|
|
15304
|
-
const output =
|
|
16459
|
+
const output = _internals19.gitExec([
|
|
15305
16460
|
"log",
|
|
15306
16461
|
"HEAD",
|
|
15307
16462
|
"--format=%H%x00%s",
|
|
@@ -15331,7 +16486,7 @@ async function withTaskCompletionLocksResult(input) {
|
|
|
15331
16486
|
attempts++;
|
|
15332
16487
|
let planLockResult;
|
|
15333
16488
|
try {
|
|
15334
|
-
planLockResult = await
|
|
16489
|
+
planLockResult = await _internals19.tryAcquireLock(input.directory, PLAN_LOCK_PATH, CHECKPOINT_AGENT_NAME, `save-task-completion-plan-${input.taskId}`);
|
|
15335
16490
|
} catch (error2) {
|
|
15336
16491
|
if (input.onFailure) {
|
|
15337
16492
|
return input.onFailure(error2);
|
|
@@ -15345,13 +16500,13 @@ async function withTaskCompletionLocksResult(input) {
|
|
|
15345
16500
|
if (attempts >= CHECKPOINT_LOCK_MAX_ATTEMPTS || Date.now() + CHECKPOINT_LOCK_DELAY_MS > deadline) {
|
|
15346
16501
|
break;
|
|
15347
16502
|
}
|
|
15348
|
-
await
|
|
16503
|
+
await _internals19.sleep(CHECKPOINT_LOCK_DELAY_MS);
|
|
15349
16504
|
continue;
|
|
15350
16505
|
}
|
|
15351
16506
|
try {
|
|
15352
16507
|
let checkpointLockResult;
|
|
15353
16508
|
try {
|
|
15354
|
-
checkpointLockResult = await
|
|
16509
|
+
checkpointLockResult = await _internals19.tryAcquireLock(input.directory, CHECKPOINT_LOG_PATH, CHECKPOINT_AGENT_NAME, `save-task-completion-checkpoint-${input.taskId}`);
|
|
15355
16510
|
} catch (error2) {
|
|
15356
16511
|
if (input.onFailure) {
|
|
15357
16512
|
return input.onFailure(error2);
|
|
@@ -15365,7 +16520,7 @@ async function withTaskCompletionLocksResult(input) {
|
|
|
15365
16520
|
if (attempts >= CHECKPOINT_LOCK_MAX_ATTEMPTS || Date.now() + CHECKPOINT_LOCK_DELAY_MS > deadline) {
|
|
15366
16521
|
break;
|
|
15367
16522
|
}
|
|
15368
|
-
await
|
|
16523
|
+
await _internals19.sleep(CHECKPOINT_LOCK_DELAY_MS);
|
|
15369
16524
|
continue;
|
|
15370
16525
|
}
|
|
15371
16526
|
try {
|
|
@@ -15421,7 +16576,7 @@ async function withCheckpointMutationLockResult(input) {
|
|
|
15421
16576
|
attempts++;
|
|
15422
16577
|
let lockResult;
|
|
15423
16578
|
try {
|
|
15424
|
-
lockResult = await
|
|
16579
|
+
lockResult = await _internals19.tryAcquireLock(input.directory, CHECKPOINT_LOG_PATH, CHECKPOINT_AGENT_NAME, input.operationKey);
|
|
15425
16580
|
} catch (error2) {
|
|
15426
16581
|
if (input.onFailure) {
|
|
15427
16582
|
return input.onFailure(error2);
|
|
@@ -15458,7 +16613,7 @@ async function withCheckpointMutationLockResult(input) {
|
|
|
15458
16613
|
if (attempts >= CHECKPOINT_LOCK_MAX_ATTEMPTS || Date.now() + CHECKPOINT_LOCK_DELAY_MS > deadline) {
|
|
15459
16614
|
break;
|
|
15460
16615
|
}
|
|
15461
|
-
await
|
|
16616
|
+
await _internals19.sleep(CHECKPOINT_LOCK_DELAY_MS);
|
|
15462
16617
|
}
|
|
15463
16618
|
if (input.onBusy) {
|
|
15464
16619
|
return input.onBusy(attempts);
|
|
@@ -15483,7 +16638,7 @@ function handleSave(label, directory) {
|
|
|
15483
16638
|
});
|
|
15484
16639
|
}
|
|
15485
16640
|
const timestamp = new Date().toISOString();
|
|
15486
|
-
|
|
16641
|
+
_internals19.stageAllExcludingSwarm(directory);
|
|
15487
16642
|
const hasStagedChanges = (() => {
|
|
15488
16643
|
try {
|
|
15489
16644
|
gitExec(["diff", "--cached", "--quiet"], directory);
|
|
@@ -15581,7 +16736,7 @@ async function handleSaveTaskCompletion(taskId, directory) {
|
|
|
15581
16736
|
directory,
|
|
15582
16737
|
taskId,
|
|
15583
16738
|
run: async () => {
|
|
15584
|
-
const plan = await
|
|
16739
|
+
const plan = await _internals19.loadPlan(directory);
|
|
15585
16740
|
if (!plan) {
|
|
15586
16741
|
return serializeResult("save_task_completion", {
|
|
15587
16742
|
success: false,
|
|
@@ -15601,7 +16756,7 @@ async function handleSaveTaskCompletion(taskId, directory) {
|
|
|
15601
16756
|
error: `save_task_completion failed: task "${taskId}" is ${task.status}, not completed`
|
|
15602
16757
|
});
|
|
15603
16758
|
}
|
|
15604
|
-
await
|
|
16759
|
+
await _internals19.afterTaskEligibilityRead?.(directory, task.id);
|
|
15605
16760
|
const planIdentityHash = derivePlanIdentityHash(plan);
|
|
15606
16761
|
const planId = derivePlanId(plan);
|
|
15607
16762
|
const ledgerEvents = await readLedgerEvents(directory);
|
|
@@ -15637,12 +16792,12 @@ async function handleSaveTaskCompletion(taskId, directory) {
|
|
|
15637
16792
|
message: `Checkpoint task completion already logged for "${descriptor.taskId}"`
|
|
15638
16793
|
});
|
|
15639
16794
|
}
|
|
15640
|
-
const recoveredSha =
|
|
16795
|
+
const recoveredSha = _internals19.findCommitByExactSubject(directory, descriptor.subject);
|
|
15641
16796
|
let committedSha = null;
|
|
15642
16797
|
committedSha = recoveredSha ?? receipt.sha;
|
|
15643
16798
|
if (!committedSha) {
|
|
15644
|
-
|
|
15645
|
-
|
|
16799
|
+
_internals19.stageAllExcludingSwarm(directory);
|
|
16800
|
+
_internals19.gitExec([
|
|
15646
16801
|
"commit",
|
|
15647
16802
|
"--allow-empty",
|
|
15648
16803
|
"-m",
|
|
@@ -15906,7 +17061,7 @@ var IPV4_PRIVATE_192 = /^192\.168\./;
|
|
|
15906
17061
|
var IPV4_ZERO_NETWORK = /^0\./;
|
|
15907
17062
|
var IPV6_LINK_LOCAL = /^fe80:/i;
|
|
15908
17063
|
var IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
|
|
15909
|
-
var
|
|
17064
|
+
var _internals20 = {
|
|
15910
17065
|
spawnSync: (cmd, args, options) => {
|
|
15911
17066
|
const mergedEnv = mergeEnvForChild(options?.env, options?.envOverrides);
|
|
15912
17067
|
return child_process2.spawnSync(cmd, args, {
|
|
@@ -16024,7 +17179,7 @@ function validateAndSanitizeGithubUrl(rawUrl, resource) {
|
|
|
16024
17179
|
}
|
|
16025
17180
|
function detectGitRemote(cwd, laneEnv) {
|
|
16026
17181
|
try {
|
|
16027
|
-
const result =
|
|
17182
|
+
const result = _internals20.spawnSync(resolveGitExecutable(), ["remote", "get-url", "origin"], {
|
|
16028
17183
|
encoding: "utf-8",
|
|
16029
17184
|
stdio: ["ignore", "pipe", "pipe"],
|
|
16030
17185
|
timeout: 5000,
|
|
@@ -16193,7 +17348,7 @@ init_logger();
|
|
|
16193
17348
|
var GIT_TIMEOUT_MS3 = 30000;
|
|
16194
17349
|
var VALIDATION_TIMEOUT_MS = 5 * 60 * 1000;
|
|
16195
17350
|
var OUTPUT_LIMIT_BYTES = 12000;
|
|
16196
|
-
var
|
|
17351
|
+
var _internals21 = {
|
|
16197
17352
|
runExternalTool,
|
|
16198
17353
|
getDefaultBaseBranch,
|
|
16199
17354
|
detectDefaultRemoteBranch,
|
|
@@ -16207,8 +17362,8 @@ var _internals20 = {
|
|
|
16207
17362
|
}
|
|
16208
17363
|
};
|
|
16209
17364
|
async function runGit(args, cwd, timeoutMs = GIT_TIMEOUT_MS3) {
|
|
16210
|
-
const result = await
|
|
16211
|
-
executable:
|
|
17365
|
+
const result = await _internals21.runExternalTool({
|
|
17366
|
+
executable: _internals21.resolveGitExecutable(),
|
|
16212
17367
|
args,
|
|
16213
17368
|
cwd,
|
|
16214
17369
|
timeoutMs,
|
|
@@ -16225,7 +17380,7 @@ async function runGit(args, cwd, timeoutMs = GIT_TIMEOUT_MS3) {
|
|
|
16225
17380
|
}
|
|
16226
17381
|
async function runValidationCommand(cmd, cwd, timeoutMs = VALIDATION_TIMEOUT_MS) {
|
|
16227
17382
|
const [executable, ...args] = cmd;
|
|
16228
|
-
const result = await
|
|
17383
|
+
const result = await _internals21.runExternalTool({
|
|
16229
17384
|
executable,
|
|
16230
17385
|
args,
|
|
16231
17386
|
cwd,
|
|
@@ -16253,9 +17408,9 @@ async function getCurrentBranchOrRef(directory) {
|
|
|
16253
17408
|
return hashResult.stdout.trim();
|
|
16254
17409
|
}
|
|
16255
17410
|
async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated) {
|
|
16256
|
-
const rawBase = path19.join(
|
|
17411
|
+
const rawBase = path19.join(_internals21.osTmpdir(), "swarm-ci-simulate");
|
|
16257
17412
|
await fsPromises.mkdir(rawBase, { recursive: true });
|
|
16258
|
-
const worktreeBase =
|
|
17413
|
+
const worktreeBase = _internals21.fs.realpathSync(rawBase);
|
|
16259
17414
|
const worktreeName = `pr-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
16260
17415
|
const worktreePath = path19.join(worktreeBase, worktreeName);
|
|
16261
17416
|
const addResult = await runGit(["worktree", "add", "--detach", worktreePath, baseBranch], projectRoot);
|
|
@@ -16270,11 +17425,11 @@ async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated)
|
|
|
16270
17425
|
return worktreePath;
|
|
16271
17426
|
}
|
|
16272
17427
|
async function cleanupWorktree(worktreePath, projectRoot) {
|
|
16273
|
-
const rawBase = path19.resolve(
|
|
16274
|
-
const worktreeBase =
|
|
16275
|
-
const resolved =
|
|
16276
|
-
const pathEq =
|
|
16277
|
-
const pathStartsWith =
|
|
17428
|
+
const rawBase = path19.resolve(_internals21.osTmpdir(), "swarm-ci-simulate");
|
|
17429
|
+
const worktreeBase = _internals21.fs.existsSync(rawBase) ? _internals21.fs.realpathSync(rawBase) : rawBase;
|
|
17430
|
+
const resolved = _internals21.fs.existsSync(worktreePath) ? _internals21.fs.realpathSync(worktreePath) : path19.resolve(worktreePath);
|
|
17431
|
+
const pathEq = _internals21.platform === "win32" ? (a, b) => a.toLowerCase() === b.toLowerCase() : (a, b) => a === b;
|
|
17432
|
+
const pathStartsWith = _internals21.platform === "win32" ? (a, b) => a.toLowerCase().startsWith(b.toLowerCase()) : (a, b) => a.startsWith(b);
|
|
16278
17433
|
if (!pathEq(resolved, worktreeBase) && !pathStartsWith(resolved, `${worktreeBase}${path19.sep}`)) {
|
|
16279
17434
|
return `[ci-simulate] refusing to clean up non-contained path ${worktreePath}`;
|
|
16280
17435
|
}
|
|
@@ -16286,11 +17441,11 @@ async function cleanupWorktree(worktreePath, projectRoot) {
|
|
|
16286
17441
|
if (!line.startsWith("worktree "))
|
|
16287
17442
|
return false;
|
|
16288
17443
|
const raw = line.slice("worktree ".length).trim();
|
|
16289
|
-
const canon =
|
|
17444
|
+
const canon = _internals21.fs.existsSync(raw) ? _internals21.fs.realpathSync(raw) : path19.resolve(raw);
|
|
16290
17445
|
return pathEq(canon, resolved);
|
|
16291
17446
|
});
|
|
16292
17447
|
if (!registered) {
|
|
16293
|
-
if (!
|
|
17448
|
+
if (!_internals21.fs.existsSync(resolved))
|
|
16294
17449
|
return null;
|
|
16295
17450
|
return `[ci-simulate] path ${worktreePath} exists but is not a registered git worktree; remove it manually`;
|
|
16296
17451
|
}
|
|
@@ -16389,7 +17544,7 @@ async function handleCiSimulateCommand(directory, args) {
|
|
|
16389
17544
|
steps: []
|
|
16390
17545
|
};
|
|
16391
17546
|
try {
|
|
16392
|
-
const detectedBranch =
|
|
17547
|
+
const detectedBranch = _internals21.detectDefaultRemoteBranch(directory);
|
|
16393
17548
|
let baseBranch = null;
|
|
16394
17549
|
if (explicitBase) {
|
|
16395
17550
|
const verify = await runGit(["rev-parse", "--verify", "--quiet", explicitBase], directory);
|
|
@@ -16866,7 +18021,7 @@ async function boundedSessionCall(call, timeoutMs, timeoutLabel, failureLabel, s
|
|
|
16866
18021
|
})
|
|
16867
18022
|
]);
|
|
16868
18023
|
} catch (error2) {
|
|
16869
|
-
|
|
18024
|
+
_internals22.log(`${failureLabel} for ephemeral session`, {
|
|
16870
18025
|
sessionId,
|
|
16871
18026
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
16872
18027
|
});
|
|
@@ -16878,21 +18033,21 @@ async function boundedSessionCall(call, timeoutMs, timeoutLabel, failureLabel, s
|
|
|
16878
18033
|
async function boundedAbortEphemeralSession(session, sessionId, timeoutMs = DEFAULT_EPHEMERAL_ABORT_TIMEOUT_MS) {
|
|
16879
18034
|
if (typeof session.abort !== "function")
|
|
16880
18035
|
return;
|
|
16881
|
-
await
|
|
18036
|
+
await _internals22.boundedSessionCall(() => session.abort({ path: { id: sessionId } }), timeoutMs, "ephemeral session abort timed out", "ephemeral session abort failed", sessionId);
|
|
16882
18037
|
}
|
|
16883
18038
|
async function boundedDeleteEphemeralSession(session, sessionId, timeoutMs = DEFAULT_EPHEMERAL_TEARDOWN_DELETE_TIMEOUT_MS) {
|
|
16884
|
-
await
|
|
18039
|
+
await _internals22.boundedSessionCall(() => session.delete({ path: { id: sessionId } }), timeoutMs, "ephemeral session delete timed out", "ephemeral session delete failed", sessionId);
|
|
16885
18040
|
}
|
|
16886
18041
|
async function teardownEphemeralSession(session, sessionId, options = {}) {
|
|
16887
18042
|
const abortTimeoutMs = options.abortTimeoutMs ?? DEFAULT_EPHEMERAL_ABORT_TIMEOUT_MS;
|
|
16888
18043
|
const deleteTimeoutMs = options.deleteTimeoutMs ?? DEFAULT_EPHEMERAL_TEARDOWN_DELETE_TIMEOUT_MS;
|
|
16889
18044
|
const skipAbort = options.skipAbort ?? false;
|
|
16890
18045
|
if (!skipAbort) {
|
|
16891
|
-
await
|
|
18046
|
+
await _internals22.boundedAbort(session, sessionId, abortTimeoutMs);
|
|
16892
18047
|
}
|
|
16893
|
-
await
|
|
18048
|
+
await _internals22.boundedDelete(session, sessionId, deleteTimeoutMs);
|
|
16894
18049
|
}
|
|
16895
|
-
var
|
|
18050
|
+
var _internals22 = {
|
|
16896
18051
|
boundedSessionCall,
|
|
16897
18052
|
boundedAbort: boundedAbortEphemeralSession,
|
|
16898
18053
|
boundedDelete: boundedDeleteEphemeralSession,
|
|
@@ -16900,7 +18055,7 @@ var _internals21 = {
|
|
|
16900
18055
|
};
|
|
16901
18056
|
|
|
16902
18057
|
// src/failures/invocation-failure.ts
|
|
16903
|
-
import { createHash as
|
|
18058
|
+
import { createHash as createHash11 } from "crypto";
|
|
16904
18059
|
|
|
16905
18060
|
// src/utils/provider-error-classification.ts
|
|
16906
18061
|
var TRANSIENT_STATUS_CODES = new Set([
|
|
@@ -16937,7 +18092,7 @@ function isQuotaError(signal) {
|
|
|
16937
18092
|
|
|
16938
18093
|
// src/failures/action-identity.ts
|
|
16939
18094
|
init_schema();
|
|
16940
|
-
import { createHash as
|
|
18095
|
+
import { createHash as createHash10 } from "crypto";
|
|
16941
18096
|
var MAX_STRING_INPUT = 512;
|
|
16942
18097
|
var MAX_PUBLIC_FIELD_LENGTH = 128;
|
|
16943
18098
|
var MAX_COLLECTION_ITEMS = 64;
|
|
@@ -16987,11 +18142,11 @@ var SCOPE_KEYS = [
|
|
|
16987
18142
|
"path",
|
|
16988
18143
|
"paths"
|
|
16989
18144
|
];
|
|
16990
|
-
function
|
|
18145
|
+
function normalizeToolName2(tool2) {
|
|
16991
18146
|
return tool2.trim().toLowerCase() || "unknown-tool";
|
|
16992
18147
|
}
|
|
16993
18148
|
function hashString(value) {
|
|
16994
|
-
return
|
|
18149
|
+
return createHash10("sha256").update(value).digest("hex");
|
|
16995
18150
|
}
|
|
16996
18151
|
function readRecord(value) {
|
|
16997
18152
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
@@ -17182,7 +18337,7 @@ function createActionIdentity(input) {
|
|
|
17182
18337
|
]);
|
|
17183
18338
|
const additionalDigest = hashString(JSON.stringify(canonicalizeAdditional(omitKnownKeys(args, knownKeys))));
|
|
17184
18339
|
const normalized = {
|
|
17185
|
-
tool:
|
|
18340
|
+
tool: normalizeToolName2(input.tool),
|
|
17186
18341
|
role,
|
|
17187
18342
|
swarm,
|
|
17188
18343
|
task,
|
|
@@ -17259,7 +18414,7 @@ function boundedUtf8(value, maxBytes = MAX_DISPLAY_BYTES) {
|
|
|
17259
18414
|
return buffer.subarray(0, maxBytes).toString("utf8").replace(/\uFFFD+$/g, "");
|
|
17260
18415
|
}
|
|
17261
18416
|
function hashValue(value) {
|
|
17262
|
-
return
|
|
18417
|
+
return createHash11("sha256").update(value).digest("hex");
|
|
17263
18418
|
}
|
|
17264
18419
|
function redactUrl(match) {
|
|
17265
18420
|
try {
|
|
@@ -17671,7 +18826,7 @@ class ModelDispatchTimeoutError extends Error {
|
|
|
17671
18826
|
this.name = "TimeoutError";
|
|
17672
18827
|
}
|
|
17673
18828
|
}
|
|
17674
|
-
var
|
|
18829
|
+
var _internals23 = {
|
|
17675
18830
|
setTimeout,
|
|
17676
18831
|
clearTimeout
|
|
17677
18832
|
};
|
|
@@ -17681,13 +18836,13 @@ function deadlineError(phase) {
|
|
|
17681
18836
|
async function raceWithTimeout(promise, ms, timeoutError) {
|
|
17682
18837
|
let timer;
|
|
17683
18838
|
const timeoutPromise = new Promise((_, reject) => {
|
|
17684
|
-
timer =
|
|
18839
|
+
timer = _internals23.setTimeout(() => reject(timeoutError), Math.max(0, ms));
|
|
17685
18840
|
});
|
|
17686
18841
|
try {
|
|
17687
18842
|
return await Promise.race([promise, timeoutPromise]);
|
|
17688
18843
|
} finally {
|
|
17689
18844
|
if (timer !== undefined)
|
|
17690
|
-
|
|
18845
|
+
_internals23.clearTimeout(timer);
|
|
17691
18846
|
}
|
|
17692
18847
|
}
|
|
17693
18848
|
function resolveLegacyFallbackModel(resolveFallback, fallbackIndex) {
|
|
@@ -18571,7 +19726,7 @@ async function readLedgerForTransaction(filePath) {
|
|
|
18571
19726
|
}
|
|
18572
19727
|
}
|
|
18573
19728
|
async function readLedgerStrict(directory) {
|
|
18574
|
-
const filePath =
|
|
19729
|
+
const filePath = _internals24.resolveRecommendationLedgerPath(directory);
|
|
18575
19730
|
try {
|
|
18576
19731
|
return parseLedgerJsonl(await readFile6(filePath, "utf-8"));
|
|
18577
19732
|
} catch (err) {
|
|
@@ -18649,7 +19804,7 @@ async function checkRecommendations(directory, candidates) {
|
|
|
18649
19804
|
let ledgerKeys = new Set;
|
|
18650
19805
|
let degraded = false;
|
|
18651
19806
|
try {
|
|
18652
|
-
const entries = await
|
|
19807
|
+
const entries = await _internals24.readLedgerStrict(directory);
|
|
18653
19808
|
ledgerKeys = new Set(entries.map((entry) => entry.crossKey));
|
|
18654
19809
|
} catch (err) {
|
|
18655
19810
|
warn(`[recommendation-ledger] check failed (fail-open, emitting everything): ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -18711,13 +19866,13 @@ async function recordEmittedRecommendations(directory, candidates, options = {})
|
|
|
18711
19866
|
if (!candidates.some(hasIdentity)) {
|
|
18712
19867
|
return { recorded: 0, suppressed: 0, evicted: 0, degraded: false };
|
|
18713
19868
|
}
|
|
18714
|
-
const emittedAt = options.producedAt ??
|
|
19869
|
+
const emittedAt = options.producedAt ?? _internals24.now().toISOString();
|
|
18715
19870
|
let recorded = 0;
|
|
18716
19871
|
let suppressed = 0;
|
|
18717
19872
|
let evicted = 0;
|
|
18718
19873
|
try {
|
|
18719
|
-
const filePath =
|
|
18720
|
-
const wrote = await
|
|
19874
|
+
const filePath = _internals24.resolveRecommendationLedgerPath(directory);
|
|
19875
|
+
const wrote = await _internals24.transactFile(filePath, readLedgerForTransaction, async (target, data) => {
|
|
18721
19876
|
await atomicWriteFile(target, serializeLedger(data));
|
|
18722
19877
|
}, (existing) => {
|
|
18723
19878
|
const seen = new Set(existing.map((entry) => entry.crossKey));
|
|
@@ -18754,7 +19909,7 @@ async function recordEmittedRecommendations(directory, candidates, options = {})
|
|
|
18754
19909
|
return { recorded: 0, suppressed: 0, evicted: 0, degraded: true };
|
|
18755
19910
|
}
|
|
18756
19911
|
}
|
|
18757
|
-
var
|
|
19912
|
+
var _internals24 = {
|
|
18758
19913
|
now: () => new Date,
|
|
18759
19914
|
transactFile,
|
|
18760
19915
|
readLedgerStrict,
|
|
@@ -18985,7 +20140,7 @@ async function reviseSkill(params) {
|
|
|
18985
20140
|
}
|
|
18986
20141
|
if (!params.delegate) {
|
|
18987
20142
|
try {
|
|
18988
|
-
const revised =
|
|
20143
|
+
const revised = _internals25.buildDeterministicRevision(params.currentContent, params.currentVersion, params.violationContexts);
|
|
18989
20144
|
const validation = await validateRevisionCandidate(params, revised, "skill_reviser:deterministic");
|
|
18990
20145
|
if (!validation.passed) {
|
|
18991
20146
|
return {
|
|
@@ -19112,7 +20267,7 @@ async function reviseSkill(params) {
|
|
|
19112
20267
|
};
|
|
19113
20268
|
}
|
|
19114
20269
|
}
|
|
19115
|
-
var
|
|
20270
|
+
var _internals25 = {
|
|
19116
20271
|
reviseSkill,
|
|
19117
20272
|
getSkillVersion,
|
|
19118
20273
|
buildDeterministicRevision,
|
|
@@ -19491,7 +20646,7 @@ function planMerges(active, threshold, maxComparisons, maxMerges) {
|
|
|
19491
20646
|
};
|
|
19492
20647
|
}
|
|
19493
20648
|
async function sweepActiveNearDuplicates(directory, options = {}) {
|
|
19494
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
20649
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-8n602qc2.js");
|
|
19495
20650
|
const { config } = loadPluginConfigWithMeta2(directory);
|
|
19496
20651
|
const sweepConfig = config.learning?.dedup_sweep;
|
|
19497
20652
|
if (sweepConfig?.enabled === false)
|
|
@@ -19607,7 +20762,7 @@ var MAX_CURATOR_PHASE_DIGESTS = 50;
|
|
|
19607
20762
|
var MAX_CURATOR_COMPLIANCE_OBSERVATIONS = 200;
|
|
19608
20763
|
var MAX_CURATOR_RECOMMENDATIONS = 200;
|
|
19609
20764
|
var MAX_LESSON_CHARS = 280;
|
|
19610
|
-
var
|
|
20765
|
+
var _internals26 = {
|
|
19611
20766
|
parseKnowledgeRecommendations,
|
|
19612
20767
|
parseKnowledgeRecommendationsWithDiagnostics,
|
|
19613
20768
|
readCuratorSummary,
|
|
@@ -19742,9 +20897,9 @@ function recordCuratorSkips(directory, skipped) {
|
|
|
19742
20897
|
async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs) {
|
|
19743
20898
|
const observations = [];
|
|
19744
20899
|
try {
|
|
19745
|
-
const skillListResult = await
|
|
19746
|
-
const { entries: usageEntries, coverage } =
|
|
19747
|
-
const allArchivedIds = await
|
|
20900
|
+
const skillListResult = await _internals26.listSkills(directory);
|
|
20901
|
+
const { entries: usageEntries, coverage } = _internals26.readSkillUsageEntriesWithCoverage(directory);
|
|
20902
|
+
const allArchivedIds = await _internals26.getArchivedKnowledgeIds(directory);
|
|
19748
20903
|
let skippedForCoverage = 0;
|
|
19749
20904
|
for (const active of skillListResult.active) {
|
|
19750
20905
|
if (excludeSlugs?.has(active.slug))
|
|
@@ -19771,7 +20926,7 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
19771
20926
|
warn(`[curator] skill '${active.slug}' auto-retire skipped: retained usage window (${skillUsage.length} entries) cannot support the decision`);
|
|
19772
20927
|
} else {
|
|
19773
20928
|
const reason = `auto-retire: violation rate ${(violationRate * 100).toFixed(0)}% exceeds 30% threshold`;
|
|
19774
|
-
await
|
|
20929
|
+
await _internals26.retireSkill(directory, active.slug, reason);
|
|
19775
20930
|
observations.push(`Skill '${active.slug}' auto-retired: ${reason}`);
|
|
19776
20931
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
19777
20932
|
continue;
|
|
@@ -19780,15 +20935,15 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
19780
20935
|
let archivedSourceMatched = false;
|
|
19781
20936
|
if (allArchivedIds.size > 0) {
|
|
19782
20937
|
try {
|
|
19783
|
-
const content = await
|
|
19784
|
-
const sourceIds =
|
|
20938
|
+
const content = await _internals26.readFileAsync(active.path, "utf-8");
|
|
20939
|
+
const sourceIds = _internals26.parseDraftFrontmatter(content)?.sourceKnowledgeIds ?? [];
|
|
19785
20940
|
archivedSourceMatched = sourceIds.some((id) => allArchivedIds.has(id));
|
|
19786
20941
|
} catch {
|
|
19787
20942
|
archivedSourceMatched = false;
|
|
19788
20943
|
}
|
|
19789
20944
|
}
|
|
19790
20945
|
if (archivedSourceMatched) {
|
|
19791
|
-
const result = await
|
|
20946
|
+
const result = await _internals26.retireOrMarkStale(directory, path24.dirname(active.path), allArchivedIds);
|
|
19792
20947
|
if (result.action === "retire") {
|
|
19793
20948
|
observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`);
|
|
19794
20949
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
@@ -19798,7 +20953,7 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
19798
20953
|
}
|
|
19799
20954
|
}
|
|
19800
20955
|
}
|
|
19801
|
-
|
|
20956
|
+
_internals26.recordCuratorSkips(directory, skippedForCoverage);
|
|
19802
20957
|
} catch (autoRetireErr) {
|
|
19803
20958
|
warn(`[curator] auto-retire health check failed: ${autoRetireErr instanceof Error ? autoRetireErr.message : String(autoRetireErr)}`);
|
|
19804
20959
|
}
|
|
@@ -20062,7 +21217,7 @@ async function transactCuratorSummary(directory, mutate) {
|
|
|
20062
21217
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
20063
21218
|
let invoked = false;
|
|
20064
21219
|
let mutationResult;
|
|
20065
|
-
await
|
|
21220
|
+
await _internals26.transactFile(resolvedPath, _internals26.readCuratorSummaryState, _internals26.writeCuratorSummaryState, (state) => {
|
|
20066
21221
|
invoked = true;
|
|
20067
21222
|
const mutation = mutate(state.summary);
|
|
20068
21223
|
mutationResult = mutation.result;
|
|
@@ -20211,8 +21366,8 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
20211
21366
|
const observations = [];
|
|
20212
21367
|
const timestamp = new Date().toISOString();
|
|
20213
21368
|
for (const agent of requiredAgents) {
|
|
20214
|
-
const normalizedAgent =
|
|
20215
|
-
const isDispatched = agentsDispatched.some((a) =>
|
|
21369
|
+
const normalizedAgent = _internals26.normalizeAgentName(agent);
|
|
21370
|
+
const isDispatched = agentsDispatched.some((a) => _internals26.normalizeAgentName(a) === normalizedAgent);
|
|
20216
21371
|
if (!isDispatched) {
|
|
20217
21372
|
observations.push({
|
|
20218
21373
|
phase,
|
|
@@ -20231,7 +21386,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
20231
21386
|
if (e.type === "agent.delegation") {
|
|
20232
21387
|
const agent = e.agent;
|
|
20233
21388
|
if (agent && typeof agent === "string") {
|
|
20234
|
-
const normalized =
|
|
21389
|
+
const normalized = _internals26.normalizeAgentName(agent);
|
|
20235
21390
|
if (normalized === "coder") {
|
|
20236
21391
|
coderDelegations.push({ event: e, index: i });
|
|
20237
21392
|
} else if (normalized === "reviewer") {
|
|
@@ -20288,7 +21443,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
20288
21443
|
if (e.type === "agent.delegation" && e.agent) {
|
|
20289
21444
|
const agent = e.agent;
|
|
20290
21445
|
if (agent && typeof agent === "string") {
|
|
20291
|
-
const normalized =
|
|
21446
|
+
const normalized = _internals26.normalizeAgentName(agent);
|
|
20292
21447
|
if (normalized === "sme") {
|
|
20293
21448
|
smeDelegations.push({ event: e, index: i });
|
|
20294
21449
|
}
|
|
@@ -20312,7 +21467,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
20312
21467
|
}
|
|
20313
21468
|
async function runCuratorInit(directory, config, llmDelegate) {
|
|
20314
21469
|
try {
|
|
20315
|
-
const priorSummary = await
|
|
21470
|
+
const priorSummary = await _internals26.readCuratorSummary(directory);
|
|
20316
21471
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
20317
21472
|
const allEntries = await readKnowledge(knowledgePath);
|
|
20318
21473
|
const highConfidenceEntries = allEntries.filter((e) => typeof e.confidence === "number" && e.confidence >= config.min_knowledge_confidence);
|
|
@@ -20353,7 +21508,7 @@ async function runCuratorInit(directory, config, llmDelegate) {
|
|
|
20353
21508
|
const maxContextChars = config.max_summary_tokens * 2;
|
|
20354
21509
|
briefingParts.push(contextMd.slice(0, maxContextChars));
|
|
20355
21510
|
}
|
|
20356
|
-
const latestPostMortemDigest =
|
|
21511
|
+
const latestPostMortemDigest = _internals26.readLatestPostMortemDigest(directory);
|
|
20357
21512
|
if (latestPostMortemDigest) {
|
|
20358
21513
|
briefingParts.push(`
|
|
20359
21514
|
## Latest Post-Mortem`);
|
|
@@ -20440,7 +21595,7 @@ Could not load prior session context.`,
|
|
|
20440
21595
|
}
|
|
20441
21596
|
async function runCuratorPhase(directory, phase, agentsDispatched, config, knowledgeConfig, llmDelegate) {
|
|
20442
21597
|
try {
|
|
20443
|
-
const priorSummary = await
|
|
21598
|
+
const priorSummary = await _internals26.readCuratorSummary(directory);
|
|
20444
21599
|
if (priorSummary?.phase_digests.some((d) => d.phase === phase)) {
|
|
20445
21600
|
const existingDigest = priorSummary.phase_digests.find((d) => d.phase === phase);
|
|
20446
21601
|
return {
|
|
@@ -20453,7 +21608,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20453
21608
|
};
|
|
20454
21609
|
}
|
|
20455
21610
|
const eventsWindow = readCoreEvents(directory);
|
|
20456
|
-
const phaseEvents = eventsWindow.text.length > 0 ?
|
|
21611
|
+
const phaseEvents = eventsWindow.text.length > 0 ? _internals26.filterPhaseEvents(eventsWindow.text, phase) : [];
|
|
20457
21612
|
if (eventsWindow.coverage === "truncated") {
|
|
20458
21613
|
try {
|
|
20459
21614
|
appendCoreEventSync(directory, {
|
|
@@ -20467,7 +21622,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20467
21622
|
}
|
|
20468
21623
|
const contextMd = await readSwarmFileAsync(directory, "context.md");
|
|
20469
21624
|
const requiredAgents = ["reviewer", "test_engineer"];
|
|
20470
|
-
const complianceObservations =
|
|
21625
|
+
const complianceObservations = _internals26.checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, phase);
|
|
20471
21626
|
const plan = await loadPlanJsonOnly(directory);
|
|
20472
21627
|
const phaseData = plan?.phases.find((p) => p.id === phase);
|
|
20473
21628
|
const tasksCompleted = phaseData ? phaseData.tasks.filter((t) => t.status === "completed").length : 0;
|
|
@@ -20491,7 +21646,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20491
21646
|
timestamp: new Date().toISOString(),
|
|
20492
21647
|
summary: `Phase ${phase} completed. ${tasksCompleted}/${tasksTotal} tasks completed. ${complianceObservations.length} compliance observations.`,
|
|
20493
21648
|
agents_used: [
|
|
20494
|
-
...new Set(agentsDispatched.map((a) =>
|
|
21649
|
+
...new Set(agentsDispatched.map((a) => _internals26.normalizeAgentName(a)))
|
|
20495
21650
|
],
|
|
20496
21651
|
tasks_completed: tasksCompleted,
|
|
20497
21652
|
tasks_total: tasksTotal,
|
|
@@ -20543,7 +21698,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20543
21698
|
clearTimeout(timer);
|
|
20544
21699
|
}
|
|
20545
21700
|
if (llmOutput?.trim()) {
|
|
20546
|
-
const parsed =
|
|
21701
|
+
const parsed = _internals26.parseKnowledgeRecommendationsWithDiagnostics(llmOutput);
|
|
20547
21702
|
for (const diagnostic of parsed.diagnostics) {
|
|
20548
21703
|
warn("[curator] skipped malformed recommendation line", {
|
|
20549
21704
|
phase,
|
|
@@ -20588,7 +21743,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20588
21743
|
}
|
|
20589
21744
|
const sessionId = `session-${Date.now()}`;
|
|
20590
21745
|
const now2 = new Date().toISOString();
|
|
20591
|
-
const summaryUpdated = await
|
|
21746
|
+
const summaryUpdated = await _internals26.mergeCuratorPhaseSummary(directory, {
|
|
20592
21747
|
phase,
|
|
20593
21748
|
phaseDigest,
|
|
20594
21749
|
complianceObservations,
|
|
@@ -20621,7 +21776,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20621
21776
|
}
|
|
20622
21777
|
if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
|
|
20623
21778
|
try {
|
|
20624
|
-
const skillModule = await import("./skill-generator-
|
|
21779
|
+
const skillModule = await import("./skill-generator-kh1z90tm.js");
|
|
20625
21780
|
for (const cand of skillCandidates) {
|
|
20626
21781
|
if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
|
|
20627
21782
|
continue;
|
|
@@ -20639,8 +21794,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20639
21794
|
}
|
|
20640
21795
|
const revisedSlugs = new Set;
|
|
20641
21796
|
try {
|
|
20642
|
-
const skillListResult = await
|
|
20643
|
-
const { entries: usageEntries, coverage } =
|
|
21797
|
+
const skillListResult = await _internals26.listSkills(directory);
|
|
21798
|
+
const { entries: usageEntries, coverage } = _internals26.readSkillUsageEntriesWithCoverage(directory);
|
|
20644
21799
|
let revisionCallsThisPhase = 0;
|
|
20645
21800
|
let skippedForCoverage = 0;
|
|
20646
21801
|
for (const active of skillListResult.active) {
|
|
@@ -20665,8 +21820,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20665
21820
|
const violations = skillUsage.filter((e) => e.complianceVerdict === "violated").length;
|
|
20666
21821
|
const violationRate = violations / skillUsage.length;
|
|
20667
21822
|
if (violationRate > REVISION_VIOLATION_THRESHOLD && violationRate <= 0.3) {
|
|
20668
|
-
const content = await
|
|
20669
|
-
const fm =
|
|
21823
|
+
const content = await _internals26.readFileAsync(active.path, "utf-8");
|
|
21824
|
+
const fm = _internals26.parseDraftFrontmatter(content);
|
|
20670
21825
|
if (fm && fm.skillOrigin === "promoted_external")
|
|
20671
21826
|
continue;
|
|
20672
21827
|
if (!isUsageWindowUsable(coverage, skillUsage.length)) {
|
|
@@ -20682,7 +21837,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20682
21837
|
reviewerNotes: e.reviewerNotes,
|
|
20683
21838
|
timestamp: e.timestamp
|
|
20684
21839
|
}));
|
|
20685
|
-
const result2 = await
|
|
21840
|
+
const result2 = await _internals26.reviseSkill({
|
|
20686
21841
|
directory,
|
|
20687
21842
|
slug: active.slug,
|
|
20688
21843
|
skillPath: active.path,
|
|
@@ -20698,18 +21853,18 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20698
21853
|
revisionCallsThisPhase++;
|
|
20699
21854
|
}
|
|
20700
21855
|
}
|
|
20701
|
-
|
|
21856
|
+
_internals26.recordCuratorSkips(directory, skippedForCoverage);
|
|
20702
21857
|
} catch (revisionErr) {
|
|
20703
21858
|
warn(`[curator] skill revision check failed: ${revisionErr instanceof Error ? revisionErr.message : String(revisionErr)}`);
|
|
20704
21859
|
}
|
|
20705
21860
|
try {
|
|
20706
|
-
const peSkillList = await
|
|
20707
|
-
const { entries: peUsageEntries, coverage: peCoverage } =
|
|
21861
|
+
const peSkillList = await _internals26.listSkills(directory);
|
|
21862
|
+
const { entries: peUsageEntries, coverage: peCoverage } = _internals26.readSkillUsageEntriesWithCoverage(directory);
|
|
20708
21863
|
const peRetirementMinAgeDays = 60;
|
|
20709
21864
|
let skippedForCoverage = 0;
|
|
20710
21865
|
for (const active of peSkillList.active) {
|
|
20711
|
-
const content = await
|
|
20712
|
-
const fm =
|
|
21866
|
+
const content = await _internals26.readFileAsync(active.path, "utf-8");
|
|
21867
|
+
const fm = _internals26.parseDraftFrontmatter(content);
|
|
20713
21868
|
if (!fm || fm.skillOrigin !== "promoted_external")
|
|
20714
21869
|
continue;
|
|
20715
21870
|
const skillUsage = peUsageEntries.filter((e) => {
|
|
@@ -20762,11 +21917,11 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
20762
21917
|
phaseDigest.summary += ` [promoted-external skill '${active.slug}' source drift detected]`;
|
|
20763
21918
|
}
|
|
20764
21919
|
}
|
|
20765
|
-
|
|
21920
|
+
_internals26.recordCuratorSkips(directory, skippedForCoverage);
|
|
20766
21921
|
} catch (peErr) {
|
|
20767
21922
|
warn(`[curator] promoted-external staleness check failed: ${peErr instanceof Error ? peErr.message : String(peErr)}`);
|
|
20768
21923
|
}
|
|
20769
|
-
const autoRetireObservations = await
|
|
21924
|
+
const autoRetireObservations = await _internals26.autoRetireSkills(directory, curatorKnowledgePath, revisedSlugs);
|
|
20770
21925
|
if (autoRetireObservations.length > 0) {
|
|
20771
21926
|
const retireNote = ` [${autoRetireObservations.length} skill(s) auto-retired]`;
|
|
20772
21927
|
phaseDigest.summary += retireNote;
|
|
@@ -20903,7 +22058,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
20903
22058
|
const authorizedRevisions = new Map;
|
|
20904
22059
|
let preSnapshot = [];
|
|
20905
22060
|
if (validRecommendations.length > 0) {
|
|
20906
|
-
preSnapshot = await
|
|
22061
|
+
preSnapshot = await _internals26.readKnowledge(knowledgePath);
|
|
20907
22062
|
const authorizedRecs = [];
|
|
20908
22063
|
for (const rec of validRecommendations) {
|
|
20909
22064
|
if (rec.action !== "archive" && rec.action !== "rewrite") {
|
|
@@ -20932,7 +22087,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
20932
22087
|
}
|
|
20933
22088
|
validRecommendations = authorizedRecs;
|
|
20934
22089
|
}
|
|
20935
|
-
const dedupCheck = await
|
|
22090
|
+
const dedupCheck = await _internals26.checkRecommendations(directory, validRecommendations.map((rec) => buildCuratorRecommendationCandidate(canonicalizeRecommendationEntryId(rec, preSnapshot))));
|
|
20936
22091
|
if (!dedupCheck.degraded) {
|
|
20937
22092
|
const keptRecommendations = [];
|
|
20938
22093
|
for (const decision of dedupCheck.decisions) {
|
|
@@ -21093,7 +22248,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
21093
22248
|
} catch {}
|
|
21094
22249
|
}
|
|
21095
22250
|
if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
|
|
21096
|
-
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-
|
|
22251
|
+
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-d65mctqy.js");
|
|
21097
22252
|
for (const { id } of contradictedEntries) {
|
|
21098
22253
|
try {
|
|
21099
22254
|
await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
|
|
@@ -21206,7 +22361,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
21206
22361
|
currentLessons.push(lesson);
|
|
21207
22362
|
emittedCandidates.push(buildCuratorRecommendationCandidate(rec));
|
|
21208
22363
|
}
|
|
21209
|
-
await
|
|
22364
|
+
await _internals26.recordEmittedRecommendations(directory, emittedCandidates);
|
|
21210
22365
|
return { applied, skipped };
|
|
21211
22366
|
}
|
|
21212
22367
|
|
|
@@ -21477,18 +22632,18 @@ async function executePostMortemActions(directory, parsed, options, generation)
|
|
|
21477
22632
|
proposals_rejected: 0,
|
|
21478
22633
|
proposals_skipped: 0
|
|
21479
22634
|
};
|
|
21480
|
-
const knowledgeConfig = options.knowledgeConfig ?? await
|
|
22635
|
+
const knowledgeConfig = options.knowledgeConfig ?? await _internals27.loadDefaultKnowledgeConfig(directory);
|
|
21481
22636
|
if (parsed.recommendations.length > 0) {
|
|
21482
22637
|
try {
|
|
21483
|
-
const knowledgeResult = await
|
|
22638
|
+
const knowledgeResult = await _internals27.applyCuratorKnowledgeUpdates(directory, parsed.recommendations, knowledgeConfig, generation);
|
|
21484
22639
|
result.knowledge_applied = knowledgeResult.applied;
|
|
21485
22640
|
result.knowledge_skipped = knowledgeResult.skipped;
|
|
21486
22641
|
} catch (err) {
|
|
21487
22642
|
warnings.push(`Post-mortem knowledge actions failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
21488
22643
|
}
|
|
21489
22644
|
try {
|
|
21490
|
-
const entries = await
|
|
21491
|
-
const hiveResult = await
|
|
22645
|
+
const entries = await _internals27.readSwarmKnowledge(directory);
|
|
22646
|
+
const hiveResult = await _internals27.checkHivePromotions(entries, knowledgeConfig, directory);
|
|
21492
22647
|
result.hive_promotions = hiveResult.new_promotions;
|
|
21493
22648
|
result.hive_encounters_incremented = hiveResult.encounters_incremented;
|
|
21494
22649
|
result.hive_advancements = hiveResult.advancements;
|
|
@@ -21498,7 +22653,7 @@ async function executePostMortemActions(directory, parsed, options, generation)
|
|
|
21498
22653
|
}
|
|
21499
22654
|
if (parsed.queueTriage.length > 0) {
|
|
21500
22655
|
try {
|
|
21501
|
-
const proposalResult = await
|
|
22656
|
+
const proposalResult = await _internals27.applyProposalTriage(directory, parsed.queueTriage);
|
|
21502
22657
|
result.proposals_approved = proposalResult.approved.length;
|
|
21503
22658
|
result.proposals_rejected = proposalResult.rejected.length;
|
|
21504
22659
|
result.proposals_skipped = proposalResult.skipped.length;
|
|
@@ -21511,7 +22666,7 @@ async function executePostMortemActions(directory, parsed, options, generation)
|
|
|
21511
22666
|
async function verifyPostMortemKnowledgeActions(directory, recommendations) {
|
|
21512
22667
|
if (recommendations.length === 0)
|
|
21513
22668
|
return [];
|
|
21514
|
-
const entries = await
|
|
22669
|
+
const entries = await _internals27.readSwarmKnowledge(directory);
|
|
21515
22670
|
const activeEntries = entries.filter((entry) => isActiveStatus(entry.status));
|
|
21516
22671
|
const exactIds = new Set(activeEntries.map((entry) => entry.id));
|
|
21517
22672
|
const prefixMatches = new Map;
|
|
@@ -21612,7 +22767,7 @@ async function repairPostMortemActions(llmOutput, diagnostics, options) {
|
|
|
21612
22767
|
].join(`
|
|
21613
22768
|
`);
|
|
21614
22769
|
const repaired = await options.llmDelegate("", repairPrompt, ac.signal);
|
|
21615
|
-
const parsed =
|
|
22770
|
+
const parsed = _internals27.parsePostMortemActions(repaired);
|
|
21616
22771
|
if (parsed.diagnostics.length === 0) {
|
|
21617
22772
|
return parsed;
|
|
21618
22773
|
}
|
|
@@ -21665,7 +22820,7 @@ function collectRetrospectives(directory) {
|
|
|
21665
22820
|
}
|
|
21666
22821
|
async function collectDriftReports(directory) {
|
|
21667
22822
|
try {
|
|
21668
|
-
const reports = await
|
|
22823
|
+
const reports = await _internals27.readPriorDriftReports(directory);
|
|
21669
22824
|
return reports.slice(-MAX_DRIFT_REPORTS).map((report) => JSON.stringify(report, null, 2));
|
|
21670
22825
|
} catch {
|
|
21671
22826
|
return [];
|
|
@@ -21890,7 +23045,7 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
21890
23045
|
warnings
|
|
21891
23046
|
};
|
|
21892
23047
|
}
|
|
21893
|
-
const lock = await
|
|
23048
|
+
const lock = await _internals27.acquirePostMortemLock(directory, effectivePlanId);
|
|
21894
23049
|
if (!lock.acquired) {
|
|
21895
23050
|
return {
|
|
21896
23051
|
success: false,
|
|
@@ -21912,7 +23067,7 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
21912
23067
|
warnings.push("Failed to collect knowledge summary.");
|
|
21913
23068
|
}
|
|
21914
23069
|
try {
|
|
21915
|
-
const { getScanStatus } = await import("./scan-cursor-
|
|
23070
|
+
const { getScanStatus } = await import("./scan-cursor-q3530gc8.js");
|
|
21916
23071
|
const scanStatus = await getScanStatus(directory);
|
|
21917
23072
|
if (scanStatus.remaining_estimate > 0) {
|
|
21918
23073
|
warnings.push(`Fair scan: reviewed ${knowledgeSummary.length} entries this sweep (generation ${scanStatus.generation}); ${scanStatus.remaining_estimate} more eligible entries will be visited in future curation sweeps.`);
|
|
@@ -21971,20 +23126,20 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
21971
23126
|
} finally {
|
|
21972
23127
|
clearTimeout(timer);
|
|
21973
23128
|
}
|
|
21974
|
-
let parsedActions =
|
|
23129
|
+
let parsedActions = _internals27.parsePostMortemActions(llmOutput);
|
|
21975
23130
|
if (parsedActions.diagnostics.length > 0) {
|
|
21976
23131
|
warnings.push(`Post-mortem structured action parse diagnostics: ${parsedActions.diagnostics.join("; ")}`);
|
|
21977
|
-
const repaired = await
|
|
23132
|
+
const repaired = await _internals27.repairPostMortemActions(llmOutput, parsedActions.diagnostics, options);
|
|
21978
23133
|
if (repaired) {
|
|
21979
23134
|
parsedActions = repaired;
|
|
21980
23135
|
warnings.push("Post-mortem structured actions repaired by LLM.");
|
|
21981
23136
|
}
|
|
21982
23137
|
}
|
|
21983
23138
|
llmSummary = parsedActions.summary;
|
|
21984
|
-
const executed = await
|
|
23139
|
+
const executed = await _internals27.executePostMortemActions(directory, parsedActions, options, scanCursor.generation);
|
|
21985
23140
|
actionResult = executed.result;
|
|
21986
23141
|
warnings.push(...executed.warnings);
|
|
21987
|
-
const knowledgeVerification = await
|
|
23142
|
+
const knowledgeVerification = await _internals27.verifyPostMortemKnowledgeActions(directory, parsedActions.recommendations);
|
|
21988
23143
|
for (const item of knowledgeVerification) {
|
|
21989
23144
|
if (item.status === "not_found" || item.status === "ambiguous_prefix" || item.status === "missing_entry_id") {
|
|
21990
23145
|
warnings.push(`Post-mortem knowledge action ${item.action} for '${item.input_entry_id ?? "new"}' ${item.status}: ${item.reason}`);
|
|
@@ -22023,10 +23178,10 @@ ${actionSummary}`;
|
|
|
22023
23178
|
} catch (err) {
|
|
22024
23179
|
const msg = err instanceof Error ? err.message : String(err);
|
|
22025
23180
|
warnings.push(`LLM delegate failed, falling back to data-only report: ${msg}`);
|
|
22026
|
-
reportContent =
|
|
23181
|
+
reportContent = _internals27.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
|
|
22027
23182
|
}
|
|
22028
23183
|
} else {
|
|
22029
|
-
reportContent =
|
|
23184
|
+
reportContent = _internals27.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
|
|
22030
23185
|
}
|
|
22031
23186
|
try {
|
|
22032
23187
|
const { mkdirSync: mkdirSync8 } = await import("fs");
|
|
@@ -22067,7 +23222,7 @@ ${actionSummary}`;
|
|
|
22067
23222
|
}
|
|
22068
23223
|
}
|
|
22069
23224
|
}
|
|
22070
|
-
var
|
|
23225
|
+
var _internals27 = {
|
|
22071
23226
|
acquirePostMortemLock,
|
|
22072
23227
|
collectKnowledgeSummary,
|
|
22073
23228
|
collectRetrospectives,
|
|
@@ -22084,9 +23239,9 @@ var _internals26 = {
|
|
|
22084
23239
|
verifyPostMortemKnowledgeActions,
|
|
22085
23240
|
repairPostMortemActions,
|
|
22086
23241
|
loadDefaultKnowledgeConfig: async (directory) => {
|
|
22087
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
23242
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-5zc62306.js");
|
|
22088
23243
|
try {
|
|
22089
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
23244
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-8n602qc2.js");
|
|
22090
23245
|
const loaded = loadPluginConfigWithMeta2(directory);
|
|
22091
23246
|
return KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
|
|
22092
23247
|
} catch {
|
|
@@ -22094,11 +23249,11 @@ var _internals26 = {
|
|
|
22094
23249
|
}
|
|
22095
23250
|
},
|
|
22096
23251
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig, generation) => {
|
|
22097
|
-
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-
|
|
23252
|
+
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-pjjw3ja4.js");
|
|
22098
23253
|
return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig, generation);
|
|
22099
23254
|
},
|
|
22100
23255
|
checkHivePromotions: async (entries, knowledgeConfig, directory) => {
|
|
22101
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
23256
|
+
const { checkHivePromotions } = await import("./hive-promoter-7vxm11sm.js");
|
|
22102
23257
|
return checkHivePromotions(entries, knowledgeConfig, directory);
|
|
22103
23258
|
},
|
|
22104
23259
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -22107,7 +23262,7 @@ var _internals26 = {
|
|
|
22107
23262
|
activateProposal,
|
|
22108
23263
|
listSkills: listSkills2,
|
|
22109
23264
|
sanitizeSlug
|
|
22110
|
-
} = await import("./skill-generator-
|
|
23265
|
+
} = await import("./skill-generator-kh1z90tm.js");
|
|
22111
23266
|
const result = {
|
|
22112
23267
|
approved: [],
|
|
22113
23268
|
rejected: [],
|
|
@@ -22197,7 +23352,7 @@ function extractCurrentPhaseFromPlan(plan) {
|
|
|
22197
23352
|
|
|
22198
23353
|
// src/hooks/hive-promoter.ts
|
|
22199
23354
|
init_schema();
|
|
22200
|
-
import { createHash as
|
|
23355
|
+
import { createHash as createHash12 } from "crypto";
|
|
22201
23356
|
import path27 from "path";
|
|
22202
23357
|
|
|
22203
23358
|
// src/hooks/hive-policy.ts
|
|
@@ -22308,10 +23463,10 @@ class HiveStagedAppendError extends Error {
|
|
|
22308
23463
|
}
|
|
22309
23464
|
}
|
|
22310
23465
|
async function transactHiveStore(mutate) {
|
|
22311
|
-
const dataDir =
|
|
22312
|
-
const hivePath =
|
|
22313
|
-
const rejectedPath =
|
|
22314
|
-
const eventsPath =
|
|
23466
|
+
const dataDir = _internals28.resolveHiveDataDir();
|
|
23467
|
+
const hivePath = _internals28.resolveHiveKnowledgePath();
|
|
23468
|
+
const rejectedPath = _internals28.resolveHiveRejectedPath();
|
|
23469
|
+
const eventsPath = _internals28.resolveHiveEventsPath();
|
|
22315
23470
|
const diagnostics = [];
|
|
22316
23471
|
try {
|
|
22317
23472
|
await mkdir7(dataDir, { recursive: true });
|
|
@@ -22322,7 +23477,7 @@ async function transactHiveStore(mutate) {
|
|
|
22322
23477
|
let release = null;
|
|
22323
23478
|
try {
|
|
22324
23479
|
try {
|
|
22325
|
-
release = await
|
|
23480
|
+
release = await _internals28.lockfile.lock(dataDir, {
|
|
22326
23481
|
...HIVE_LOCK_RETRIES,
|
|
22327
23482
|
stale: HIVE_LOCK_STALE_MS
|
|
22328
23483
|
});
|
|
@@ -22330,7 +23485,7 @@ async function transactHiveStore(mutate) {
|
|
|
22330
23485
|
diagnostics.push(`hive lock acquire failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
22331
23486
|
return { committed: false, return: undefined, diagnostics };
|
|
22332
23487
|
}
|
|
22333
|
-
const entries = await
|
|
23488
|
+
const entries = await _internals28.readKnowledge(hivePath);
|
|
22334
23489
|
const outcome = await mutate({ entries });
|
|
22335
23490
|
if (outcome.kind === "noop") {
|
|
22336
23491
|
return { committed: false, return: outcome.return, diagnostics };
|
|
@@ -22351,7 +23506,7 @@ async function transactHiveStore(mutate) {
|
|
|
22351
23506
|
return { committed: false, return: undefined, diagnostics };
|
|
22352
23507
|
}
|
|
22353
23508
|
if (typeof outcome.maxEntries === "number" && committedEntries.length > outcome.maxEntries) {
|
|
22354
|
-
committedEntries =
|
|
23509
|
+
committedEntries = _internals28.selectKnowledgeCapSurvivors(committedEntries, outcome.maxEntries);
|
|
22355
23510
|
}
|
|
22356
23511
|
if (outcome.extraStagedAppends && outcome.extraStagedAppends.length > 0) {
|
|
22357
23512
|
for (const staged of outcome.extraStagedAppends) {
|
|
@@ -22362,7 +23517,7 @@ async function transactHiveStore(mutate) {
|
|
|
22362
23517
|
const content = committedEntries.map((e) => overrides?.get(e.id) ?? JSON.stringify(e)).join(`
|
|
22363
23518
|
`) + (committedEntries.length > 0 ? `
|
|
22364
23519
|
` : "");
|
|
22365
|
-
await
|
|
23520
|
+
await _internals28.atomicWriteFile(hivePath, content);
|
|
22366
23521
|
if (outcome.rejects && outcome.rejects.length > 0) {
|
|
22367
23522
|
const rejectBlock = `${outcome.rejects.map((r) => JSON.stringify(r)).join(`
|
|
22368
23523
|
`)}
|
|
@@ -22383,7 +23538,7 @@ async function transactHiveStore(mutate) {
|
|
|
22383
23538
|
if (outcome.extraStagedAppends && outcome.extraStagedAppends.length > 0) {
|
|
22384
23539
|
for (const staged of outcome.extraStagedAppends) {
|
|
22385
23540
|
try {
|
|
22386
|
-
await
|
|
23541
|
+
await _internals28.appendFile(staged.path, staged.block, "utf-8");
|
|
22387
23542
|
} catch (err) {
|
|
22388
23543
|
throw new HiveStagedAppendError(staged.path, err);
|
|
22389
23544
|
}
|
|
@@ -22447,7 +23602,7 @@ async function trimHiveEventsUnderLock(eventsPath) {
|
|
|
22447
23602
|
`)}
|
|
22448
23603
|
`);
|
|
22449
23604
|
}
|
|
22450
|
-
var
|
|
23605
|
+
var _internals28 = {
|
|
22451
23606
|
lockfile: import_proper_lockfile4.default,
|
|
22452
23607
|
readKnowledge,
|
|
22453
23608
|
atomicWriteFile,
|
|
@@ -22482,7 +23637,7 @@ function terminalHistory(membership) {
|
|
|
22482
23637
|
}
|
|
22483
23638
|
async function loadPromotionEvidenceByEntry(directory, canonicalCohortId) {
|
|
22484
23639
|
try {
|
|
22485
|
-
const history = await
|
|
23640
|
+
const history = await _internals29.queryHistoricalOutcomes(directory);
|
|
22486
23641
|
if (!history.ok)
|
|
22487
23642
|
return {};
|
|
22488
23643
|
const out = {};
|
|
@@ -22517,7 +23672,7 @@ async function loadPromotionEvidenceByEntry(directory, canonicalCohortId) {
|
|
|
22517
23672
|
return {};
|
|
22518
23673
|
}
|
|
22519
23674
|
}
|
|
22520
|
-
var
|
|
23675
|
+
var _internals29 = { queryHistoricalOutcomes };
|
|
22521
23676
|
|
|
22522
23677
|
// src/hooks/hive-promoter.ts
|
|
22523
23678
|
function carryActionableFields(source) {
|
|
@@ -22613,7 +23768,7 @@ function buildLineage(args) {
|
|
|
22613
23768
|
return lineage;
|
|
22614
23769
|
}
|
|
22615
23770
|
function lessonRevision(lesson) {
|
|
22616
|
-
return
|
|
23771
|
+
return createHash12("sha256").update(lesson).digest("hex").slice(0, 12);
|
|
22617
23772
|
}
|
|
22618
23773
|
async function checkHivePromotions(swarmEntries, config, directory) {
|
|
22619
23774
|
const empty = {
|
|
@@ -22626,8 +23781,8 @@ async function checkHivePromotions(swarmEntries, config, directory) {
|
|
|
22626
23781
|
if (config.hive_enabled === false) {
|
|
22627
23782
|
return empty;
|
|
22628
23783
|
}
|
|
22629
|
-
const sourceCohort = await
|
|
22630
|
-
const evidence2 = await
|
|
23784
|
+
const sourceCohort = await _internals30.resolveCohortId(directory);
|
|
23785
|
+
const evidence2 = await _internals30.loadPromotionEvidence(directory, sourceCohort.cohortId);
|
|
22631
23786
|
const diagnostics = [];
|
|
22632
23787
|
const activeSwarm = swarmEntries.filter((e) => isActiveStatus(e.status));
|
|
22633
23788
|
const activeSwarmBigrams = activeSwarm.map((e) => typeof e.lesson === "string" ? wordBigrams(e.lesson) : new Set);
|
|
@@ -22647,7 +23802,7 @@ async function checkHivePromotions(swarmEntries, config, directory) {
|
|
|
22647
23802
|
diagnostics.push(`skip promote '${swarmEntry.lesson.slice(0, 40)}\u2026': ${decision.reason}`);
|
|
22648
23803
|
continue;
|
|
22649
23804
|
}
|
|
22650
|
-
const validationResult =
|
|
23805
|
+
const validationResult = _internals30.validateLesson(swarmEntry.lesson, [], {
|
|
22651
23806
|
category: swarmEntry.category,
|
|
22652
23807
|
scope: swarmEntry.scope,
|
|
22653
23808
|
confidence: swarmEntry.confidence
|
|
@@ -22669,7 +23824,7 @@ async function checkHivePromotions(swarmEntries, config, directory) {
|
|
|
22669
23824
|
});
|
|
22670
23825
|
}
|
|
22671
23826
|
const hiveDir = resolveHiveDataDir();
|
|
22672
|
-
const result = await
|
|
23827
|
+
const result = await _internals30.transactHiveStore(async (ctx) => {
|
|
22673
23828
|
let newPromotions = 0;
|
|
22674
23829
|
let encounters = 0;
|
|
22675
23830
|
let advancements = 0;
|
|
@@ -22895,7 +24050,7 @@ async function authorizeAndRecordHiveMerge(args) {
|
|
|
22895
24050
|
let authorized = true;
|
|
22896
24051
|
let basis = "config-skipped-unlinked";
|
|
22897
24052
|
try {
|
|
22898
|
-
const decision = await
|
|
24053
|
+
const decision = await _internals30.authorizeCuration({
|
|
22899
24054
|
directory: hiveDir,
|
|
22900
24055
|
action: "merge",
|
|
22901
24056
|
entryId: survivingEntry.id,
|
|
@@ -22925,7 +24080,7 @@ async function authorizeAndRecordHiveMerge(args) {
|
|
|
22925
24080
|
authorizationBasis: basis
|
|
22926
24081
|
});
|
|
22927
24082
|
}
|
|
22928
|
-
var
|
|
24083
|
+
var _internals30 = {
|
|
22929
24084
|
readSwarmEntries: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory)),
|
|
22930
24085
|
checkHivePromotions,
|
|
22931
24086
|
readCuratorSummary,
|
|
@@ -22939,15 +24094,15 @@ var _internals29 = {
|
|
|
22939
24094
|
};
|
|
22940
24095
|
function createHivePromoterHook(directory, config) {
|
|
22941
24096
|
const hook = async (_input, _output) => {
|
|
22942
|
-
const swarmEntries = await
|
|
22943
|
-
const promotionSummary = await
|
|
22944
|
-
const curatorSummary = await
|
|
24097
|
+
const swarmEntries = await _internals30.readSwarmEntries(directory);
|
|
24098
|
+
const promotionSummary = await _internals30.checkHivePromotions(swarmEntries, config, directory);
|
|
24099
|
+
const curatorSummary = await _internals30.readCuratorSummary(directory);
|
|
22945
24100
|
if (!curatorSummary)
|
|
22946
24101
|
return;
|
|
22947
24102
|
const hasActivity = promotionSummary.new_promotions > 0 || promotionSummary.encounters_incremented > 0 || promotionSummary.advancements > 0;
|
|
22948
24103
|
if (!hasActivity)
|
|
22949
24104
|
return;
|
|
22950
|
-
await
|
|
24105
|
+
await _internals30.appendCuratorRecommendation(directory, {
|
|
22951
24106
|
action: "promote",
|
|
22952
24107
|
lesson: `Hive promotion: ${promotionSummary.new_promotions} new, ${promotionSummary.encounters_incremented} encounters, ${promotionSummary.advancements} advancements, ${promotionSummary.total_hive_entries} total entries`,
|
|
22953
24108
|
reason: JSON.stringify({
|
|
@@ -22985,16 +24140,16 @@ function normalizeManualActionability(fields) {
|
|
|
22985
24140
|
async function promoteToHive(directory, lesson, category, options, config, actionable) {
|
|
22986
24141
|
const trimmedLesson = lesson.trim();
|
|
22987
24142
|
const actionableFields = normalizeManualActionability(actionable);
|
|
22988
|
-
const sourceCohort = await
|
|
22989
|
-
const policyConfig = config ??
|
|
22990
|
-
const result = await
|
|
24143
|
+
const sourceCohort = await _internals30.resolveCohortId(directory);
|
|
24144
|
+
const policyConfig = config ?? _internals30.loadDefaultKnowledgeConfig();
|
|
24145
|
+
const result = await _internals30.transactHiveStore(async (ctx) => {
|
|
22991
24146
|
if (findNearDuplicate(trimmedLesson, ctx.entries, policyConfig.dedup_threshold)) {
|
|
22992
24147
|
return {
|
|
22993
24148
|
kind: "noop",
|
|
22994
24149
|
return: `Lesson already exists in hive (near-duplicate).`
|
|
22995
24150
|
};
|
|
22996
24151
|
}
|
|
22997
|
-
const validationResult =
|
|
24152
|
+
const validationResult = _internals30.validateLesson(trimmedLesson, ctx.entries.map((e) => e.lesson), {
|
|
22998
24153
|
category: category || "process",
|
|
22999
24154
|
scope: "global",
|
|
23000
24155
|
confidence: 1
|
|
@@ -23105,16 +24260,16 @@ async function promoteFromSwarm(directory, lessonId, options, config) {
|
|
|
23105
24260
|
if (!swarmEntry) {
|
|
23106
24261
|
throw new Error(`Lesson ${lessonId} not found in .swarm/knowledge.jsonl`);
|
|
23107
24262
|
}
|
|
23108
|
-
const sourceCohort = await
|
|
23109
|
-
const policyConfig = config ??
|
|
23110
|
-
const result = await
|
|
24263
|
+
const sourceCohort = await _internals30.resolveCohortId(directory);
|
|
24264
|
+
const policyConfig = config ?? _internals30.loadDefaultKnowledgeConfig();
|
|
24265
|
+
const result = await _internals30.transactHiveStore(async (ctx) => {
|
|
23111
24266
|
if (findNearDuplicate(swarmEntry.lesson, ctx.entries, policyConfig.dedup_threshold)) {
|
|
23112
24267
|
return {
|
|
23113
24268
|
kind: "noop",
|
|
23114
24269
|
return: `Lesson already exists in hive (near-duplicate).`
|
|
23115
24270
|
};
|
|
23116
24271
|
}
|
|
23117
|
-
const validationResult =
|
|
24272
|
+
const validationResult = _internals30.validateLesson(swarmEntry.lesson, ctx.entries.map((e) => e.lesson), {
|
|
23118
24273
|
category: swarmEntry.category,
|
|
23119
24274
|
scope: swarmEntry.scope,
|
|
23120
24275
|
confidence: swarmEntry.confidence
|
|
@@ -23202,7 +24357,7 @@ async function promoteFromSwarm(directory, lessonId, options, config) {
|
|
|
23202
24357
|
}
|
|
23203
24358
|
|
|
23204
24359
|
// src/hooks/knowledge-curator.ts
|
|
23205
|
-
import { createHash as
|
|
24360
|
+
import { createHash as createHash13 } from "crypto";
|
|
23206
24361
|
import { existsSync as existsSync15 } from "fs";
|
|
23207
24362
|
import { readFile as readFile9, realpath as realpath3, writeFile as writeFile6 } from "fs/promises";
|
|
23208
24363
|
import * as path29 from "path";
|
|
@@ -23434,12 +24589,12 @@ function recordSeenRetroSection(key, value, timestamp) {
|
|
|
23434
24589
|
capSeenRetroSections();
|
|
23435
24590
|
}
|
|
23436
24591
|
function hashContent(content) {
|
|
23437
|
-
return
|
|
24592
|
+
return createHash13("sha1").update(content).digest("hex");
|
|
23438
24593
|
}
|
|
23439
24594
|
async function loadConfigForPolicyCurator(directory) {
|
|
23440
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
24595
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-5zc62306.js");
|
|
23441
24596
|
try {
|
|
23442
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
24597
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-8n602qc2.js");
|
|
23443
24598
|
const { config: loadedConfig } = loadPluginConfigWithMeta2(directory);
|
|
23444
24599
|
return KnowledgeConfigSchema2.parse(loadedConfig.knowledge ?? {});
|
|
23445
24600
|
} catch {
|
|
@@ -23449,7 +24604,7 @@ async function loadConfigForPolicyCurator(directory) {
|
|
|
23449
24604
|
async function canonicalExistingPath(candidate) {
|
|
23450
24605
|
let resolved = path29.resolve(candidate);
|
|
23451
24606
|
try {
|
|
23452
|
-
resolved = await
|
|
24607
|
+
resolved = await _internals31.realpath(resolved);
|
|
23453
24608
|
} catch {}
|
|
23454
24609
|
return resolved;
|
|
23455
24610
|
}
|
|
@@ -24281,9 +25436,9 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
24281
25436
|
} catch {}
|
|
24282
25437
|
}
|
|
24283
25438
|
if (!options?.skipAutoPromotion) {
|
|
24284
|
-
await
|
|
25439
|
+
await _internals31.runAutoPromotion(directory, config);
|
|
24285
25440
|
if (phaseInfo.phase_number > 0) {
|
|
24286
|
-
await
|
|
25441
|
+
await _internals31.runAutoDemotion(directory, config, phaseInfo.phase_number);
|
|
24287
25442
|
}
|
|
24288
25443
|
}
|
|
24289
25444
|
return { stored, reinforced, skipped, rejected, quarantined };
|
|
@@ -24398,7 +25553,7 @@ function createKnowledgeCuratorHook(directory, config, options = {}) {
|
|
|
24398
25553
|
}
|
|
24399
25554
|
inFlightEvidenceEntries.add(evidenceKey);
|
|
24400
25555
|
try {
|
|
24401
|
-
await
|
|
25556
|
+
await _internals31.curateAndStoreSwarm(batch.lessons, batch.projectName, { phase_number: batch.phaseNumber }, directory, config, {
|
|
24402
25557
|
llmDelegate: options.llmDelegateFactory?.(trigger.sessionID),
|
|
24403
25558
|
enrichmentQuota: options.enrichmentQuota
|
|
24404
25559
|
});
|
|
@@ -24430,14 +25585,14 @@ function createKnowledgeCuratorHook(directory, config, options = {}) {
|
|
|
24430
25585
|
const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
|
|
24431
25586
|
const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
|
|
24432
25587
|
const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
|
|
24433
|
-
await
|
|
25588
|
+
await _internals31.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config, {
|
|
24434
25589
|
llmDelegate: options.llmDelegateFactory?.(trigger.sessionID),
|
|
24435
25590
|
enrichmentQuota: options.enrichmentQuota
|
|
24436
25591
|
});
|
|
24437
25592
|
};
|
|
24438
25593
|
return safeHook(handler);
|
|
24439
25594
|
}
|
|
24440
|
-
var
|
|
25595
|
+
var _internals31 = {
|
|
24441
25596
|
isWriteToEvidenceFile,
|
|
24442
25597
|
curateAndStoreSwarm,
|
|
24443
25598
|
runAutoPromotion,
|
|
@@ -24711,7 +25866,7 @@ function isValidTelemetryEntry(value) {
|
|
|
24711
25866
|
const nonNegFinite = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0;
|
|
24712
25867
|
return typeof obj.timestamp === "string" && typeof obj.task_id === "string" && typeof obj.agent_role === "string" && typeof obj.delegation_reason === "string" && nonNegFinite(obj.token_estimate) && nonNegFinite(obj.cache_hits) && nonNegFinite(obj.cache_misses) && nonNegFinite(obj.stale_entries) && nonNegFinite(obj.recommended_reads) && nonNegFinite(obj.skipped_reads) && typeof obj.success === "boolean";
|
|
24713
25868
|
}
|
|
24714
|
-
var
|
|
25869
|
+
var _internals32 = {
|
|
24715
25870
|
appendFileSync: fs14.appendFileSync,
|
|
24716
25871
|
readFileSync: fs14.readFileSync,
|
|
24717
25872
|
existsSync: fs14.existsSync,
|
|
@@ -24802,25 +25957,25 @@ function parseManifestLine(line) {
|
|
|
24802
25957
|
}
|
|
24803
25958
|
function readBoundedChunk(filePath, maxBytes) {
|
|
24804
25959
|
try {
|
|
24805
|
-
if (!
|
|
25960
|
+
if (!_internals32.existsSync(filePath)) {
|
|
24806
25961
|
return { text: "", truncated: false };
|
|
24807
25962
|
}
|
|
24808
|
-
const fd =
|
|
25963
|
+
const fd = _internals32.openSync(filePath, "r");
|
|
24809
25964
|
try {
|
|
24810
|
-
const size =
|
|
25965
|
+
const size = _internals32.statSync(filePath).size;
|
|
24811
25966
|
const truncated = size > maxBytes;
|
|
24812
25967
|
const len = Math.min(size, maxBytes);
|
|
24813
25968
|
const buf = Buffer.alloc(len);
|
|
24814
25969
|
let read = 0;
|
|
24815
25970
|
while (read < len) {
|
|
24816
|
-
const n =
|
|
25971
|
+
const n = _internals32.readSync(fd, buf, read, len - read, read);
|
|
24817
25972
|
if (n <= 0)
|
|
24818
25973
|
break;
|
|
24819
25974
|
read += n;
|
|
24820
25975
|
}
|
|
24821
25976
|
return { text: buf.toString("utf-8", 0, read), truncated };
|
|
24822
25977
|
} finally {
|
|
24823
|
-
|
|
25978
|
+
_internals32.closeSync(fd);
|
|
24824
25979
|
}
|
|
24825
25980
|
} catch {
|
|
24826
25981
|
warnThrottled("bounded read failed (transient I/O)");
|
|
@@ -24829,9 +25984,9 @@ function readBoundedChunk(filePath, maxBytes) {
|
|
|
24829
25984
|
}
|
|
24830
25985
|
function fileSizeOrZero(filePath) {
|
|
24831
25986
|
try {
|
|
24832
|
-
if (!
|
|
25987
|
+
if (!_internals32.existsSync(filePath))
|
|
24833
25988
|
return 0;
|
|
24834
|
-
return
|
|
25989
|
+
return _internals32.statSync(filePath).size;
|
|
24835
25990
|
} catch {
|
|
24836
25991
|
return 0;
|
|
24837
25992
|
}
|
|
@@ -24873,17 +26028,17 @@ function atomicReplace(directory, content) {
|
|
|
24873
26028
|
const finalPath = telemetryFilePath(directory);
|
|
24874
26029
|
const tmpPath = tmpFilePath(directory);
|
|
24875
26030
|
try {
|
|
24876
|
-
if (
|
|
26031
|
+
if (_internals32.existsSync(tmpPath)) {
|
|
24877
26032
|
try {
|
|
24878
|
-
|
|
26033
|
+
_internals32.unlinkSync(tmpPath);
|
|
24879
26034
|
} catch {}
|
|
24880
26035
|
}
|
|
24881
|
-
|
|
24882
|
-
|
|
26036
|
+
_internals32.writeFileSync(tmpPath, content, "utf-8");
|
|
26037
|
+
_internals32.renameSync(tmpPath, finalPath);
|
|
24883
26038
|
} catch {
|
|
24884
26039
|
try {
|
|
24885
|
-
if (
|
|
24886
|
-
|
|
26040
|
+
if (_internals32.existsSync(tmpPath)) {
|
|
26041
|
+
_internals32.unlinkSync(tmpPath);
|
|
24887
26042
|
}
|
|
24888
26043
|
} catch {}
|
|
24889
26044
|
throw new Error("context-telemetry atomic replace failed");
|
|
@@ -24893,20 +26048,20 @@ function withStoreLock(directory, fn) {
|
|
|
24893
26048
|
const lockPath = lockFilePath(directory);
|
|
24894
26049
|
let acquired = false;
|
|
24895
26050
|
try {
|
|
24896
|
-
|
|
24897
|
-
const fd =
|
|
24898
|
-
|
|
26051
|
+
_internals32.mkdirSync(path30.dirname(lockPath), { recursive: true });
|
|
26052
|
+
const fd = _internals32.openSync(lockPath, "wx");
|
|
26053
|
+
_internals32.closeSync(fd);
|
|
24899
26054
|
acquired = true;
|
|
24900
26055
|
} catch {
|
|
24901
26056
|
try {
|
|
24902
|
-
const age = Date.now() -
|
|
26057
|
+
const age = Date.now() - _internals32.statSync(lockPath).mtimeMs;
|
|
24903
26058
|
if (age > 5 * 60000) {
|
|
24904
26059
|
try {
|
|
24905
|
-
|
|
26060
|
+
_internals32.unlinkSync(lockPath);
|
|
24906
26061
|
} catch {}
|
|
24907
26062
|
try {
|
|
24908
|
-
const fd =
|
|
24909
|
-
|
|
26063
|
+
const fd = _internals32.openSync(lockPath, "wx");
|
|
26064
|
+
_internals32.closeSync(fd);
|
|
24910
26065
|
acquired = true;
|
|
24911
26066
|
} catch {
|
|
24912
26067
|
acquired = false;
|
|
@@ -24922,32 +26077,32 @@ function withStoreLock(directory, fn) {
|
|
|
24922
26077
|
return fn();
|
|
24923
26078
|
} finally {
|
|
24924
26079
|
try {
|
|
24925
|
-
|
|
26080
|
+
_internals32.unlinkSync(lockPath);
|
|
24926
26081
|
} catch {}
|
|
24927
26082
|
}
|
|
24928
26083
|
}
|
|
24929
26084
|
var _lastWarnAt = 0;
|
|
24930
26085
|
function warnThrottled(message) {
|
|
24931
26086
|
const now2 = Date.now();
|
|
24932
|
-
if (now2 - _lastWarnAt <
|
|
26087
|
+
if (now2 - _lastWarnAt < _internals32.limits.warnCooldownMs)
|
|
24933
26088
|
return;
|
|
24934
26089
|
_lastWarnAt = now2;
|
|
24935
26090
|
warn(`context-telemetry: ${message}`);
|
|
24936
26091
|
}
|
|
24937
26092
|
function readStore(directory, bounded) {
|
|
24938
26093
|
const filePath = telemetryFilePath(directory);
|
|
24939
|
-
if (!
|
|
26094
|
+
if (!_internals32.existsSync(filePath)) {
|
|
24940
26095
|
return { manifest: null, records: [], corruptLines: 0, truncated: false };
|
|
24941
26096
|
}
|
|
24942
26097
|
let text;
|
|
24943
26098
|
let truncated = false;
|
|
24944
26099
|
if (bounded) {
|
|
24945
|
-
const chunk = readBoundedChunk(filePath,
|
|
26100
|
+
const chunk = readBoundedChunk(filePath, _internals32.limits.readMaxBytes);
|
|
24946
26101
|
text = chunk.text;
|
|
24947
26102
|
truncated = chunk.truncated;
|
|
24948
26103
|
} else {
|
|
24949
26104
|
try {
|
|
24950
|
-
text =
|
|
26105
|
+
text = _internals32.readFileSync(filePath, "utf-8");
|
|
24951
26106
|
} catch {
|
|
24952
26107
|
return { manifest: null, records: [], corruptLines: 0, truncated: false };
|
|
24953
26108
|
}
|
|
@@ -25065,7 +26220,7 @@ function periodMs(oldest, newest) {
|
|
|
25065
26220
|
}
|
|
25066
26221
|
function compactStore(directory, trigger = "compaction", alreadyLocked = false) {
|
|
25067
26222
|
const filePath = telemetryFilePath(directory);
|
|
25068
|
-
if (!
|
|
26223
|
+
if (!_internals32.existsSync(filePath))
|
|
25069
26224
|
return;
|
|
25070
26225
|
const run = () => {
|
|
25071
26226
|
const view = readStore(directory, false);
|
|
@@ -25077,7 +26232,7 @@ function compactStore(directory, trigger = "compaction", alreadyLocked = false)
|
|
|
25077
26232
|
const kept = [];
|
|
25078
26233
|
for (const rec of view.records) {
|
|
25079
26234
|
const ts = Date.parse(rec.timestamp);
|
|
25080
|
-
if (!Number.isNaN(ts) && now2 - ts >
|
|
26235
|
+
if (!Number.isNaN(ts) && now2 - ts > _internals32.limits.ageMaxMs) {
|
|
25081
26236
|
agePruned.push(rec);
|
|
25082
26237
|
} else {
|
|
25083
26238
|
kept.push(rec);
|
|
@@ -25088,7 +26243,7 @@ function compactStore(directory, trigger = "compaction", alreadyLocked = false)
|
|
|
25088
26243
|
for (let i = kept.length - 1;i >= 0; i -= 1) {
|
|
25089
26244
|
const rec = kept[i];
|
|
25090
26245
|
const lineBytes = Buffer.byteLength(JSON.stringify(rec)) + 1;
|
|
25091
|
-
if (retained.length >=
|
|
26246
|
+
if (retained.length >= _internals32.limits.activeMaxEntries || bytes + lineBytes > _internals32.limits.activeMaxBytes) {
|
|
25092
26247
|
break;
|
|
25093
26248
|
}
|
|
25094
26249
|
retained.push(rec);
|
|
@@ -25131,7 +26286,7 @@ function compactStore(directory, trigger = "compaction", alreadyLocked = false)
|
|
|
25131
26286
|
oldest: folded.oldestTimestamp,
|
|
25132
26287
|
newest: folded.newestTimestamp,
|
|
25133
26288
|
bytes: fileSizeOrZero(filePath),
|
|
25134
|
-
limitBytes:
|
|
26289
|
+
limitBytes: _internals32.limits.activeMaxBytes
|
|
25135
26290
|
});
|
|
25136
26291
|
};
|
|
25137
26292
|
if (alreadyLocked) {
|
|
@@ -25142,10 +26297,10 @@ function compactStore(directory, trigger = "compaction", alreadyLocked = false)
|
|
|
25142
26297
|
}
|
|
25143
26298
|
function migrateCutover(directory, trigger = "compaction", alreadyLocked = false) {
|
|
25144
26299
|
const filePath = telemetryFilePath(directory);
|
|
25145
|
-
if (!
|
|
26300
|
+
if (!_internals32.existsSync(filePath))
|
|
25146
26301
|
return;
|
|
25147
26302
|
const run = () => {
|
|
25148
|
-
if (!
|
|
26303
|
+
if (!_internals32.existsSync(filePath))
|
|
25149
26304
|
return;
|
|
25150
26305
|
const view = readStore(directory, false);
|
|
25151
26306
|
if (view.manifest === null && view.records.length === 0)
|
|
@@ -25156,7 +26311,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
|
|
|
25156
26311
|
const kept = [];
|
|
25157
26312
|
for (const rec of view.records) {
|
|
25158
26313
|
const ts = Date.parse(rec.timestamp);
|
|
25159
|
-
if (!Number.isNaN(ts) && now2 - ts >
|
|
26314
|
+
if (!Number.isNaN(ts) && now2 - ts > _internals32.limits.ageMaxMs) {
|
|
25160
26315
|
agePruned.push(rec);
|
|
25161
26316
|
} else {
|
|
25162
26317
|
kept.push(rec);
|
|
@@ -25167,7 +26322,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
|
|
|
25167
26322
|
for (let i = kept.length - 1;i >= 0; i -= 1) {
|
|
25168
26323
|
const rec = kept[i];
|
|
25169
26324
|
const lb = Buffer.byteLength(JSON.stringify(rec)) + 1;
|
|
25170
|
-
if (retained.length >=
|
|
26325
|
+
if (retained.length >= _internals32.limits.activeMaxEntries || bytes + lb > _internals32.limits.activeMaxBytes) {
|
|
25171
26326
|
break;
|
|
25172
26327
|
}
|
|
25173
26328
|
retained.push(rec);
|
|
@@ -25186,7 +26341,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
|
|
|
25186
26341
|
let foldedBytes = 0;
|
|
25187
26342
|
for (const cand of candidates) {
|
|
25188
26343
|
const cb = Buffer.byteLength(JSON.stringify(cand)) + 1;
|
|
25189
|
-
if (foldedBytes + cb >
|
|
26344
|
+
if (foldedBytes + cb > _internals32.limits.compactMaxBytes && toFold.size > 0) {
|
|
25190
26345
|
break;
|
|
25191
26346
|
}
|
|
25192
26347
|
toFold.add(cand);
|
|
@@ -25229,7 +26384,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
|
|
|
25229
26384
|
oldest: folded.oldestTimestamp,
|
|
25230
26385
|
newest: folded.newestTimestamp,
|
|
25231
26386
|
bytes: fileSizeOrZero(filePath),
|
|
25232
|
-
limitBytes:
|
|
26387
|
+
limitBytes: _internals32.limits.activeMaxBytes
|
|
25233
26388
|
});
|
|
25234
26389
|
};
|
|
25235
26390
|
if (alreadyLocked) {
|
|
@@ -25241,7 +26396,7 @@ function migrateCutover(directory, trigger = "compaction", alreadyLocked = false
|
|
|
25241
26396
|
function finalizeContextTelemetry(directory) {
|
|
25242
26397
|
try {
|
|
25243
26398
|
const filePath = telemetryFilePath(directory);
|
|
25244
|
-
if (!
|
|
26399
|
+
if (!_internals32.existsSync(filePath))
|
|
25245
26400
|
return;
|
|
25246
26401
|
withStoreLock(directory, () => {
|
|
25247
26402
|
let prev = Number.POSITIVE_INFINITY;
|
|
@@ -25279,7 +26434,7 @@ function emitContextTelemetryHealth(_directory, payload) {
|
|
|
25279
26434
|
} catch {}
|
|
25280
26435
|
}
|
|
25281
26436
|
function emitHealth(directory, payload) {
|
|
25282
|
-
|
|
26437
|
+
_internals32.emitHealth(directory, payload);
|
|
25283
26438
|
}
|
|
25284
26439
|
|
|
25285
26440
|
// src/memory/finalize-reward-sweep.ts
|
|
@@ -25532,100 +26687,6 @@ function summarizePiiFindings(findings) {
|
|
|
25532
26687
|
}
|
|
25533
26688
|
var NER_MODEL_CACHE_DIR = path31.join(os3.homedir(), ".cache", "opencode-swarm", "models");
|
|
25534
26689
|
|
|
25535
|
-
// src/memory/redaction.ts
|
|
25536
|
-
import { createHash as createHash13 } from "crypto";
|
|
25537
|
-
var SECRET_PATTERNS = [
|
|
25538
|
-
{ type: "openai_api_key", pattern: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
|
|
25539
|
-
{
|
|
25540
|
-
type: "github_token",
|
|
25541
|
-
pattern: /\b(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}\b/g
|
|
25542
|
-
},
|
|
25543
|
-
{ type: "aws_access_key_id", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
25544
|
-
{
|
|
25545
|
-
type: "private_key_block",
|
|
25546
|
-
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g
|
|
25547
|
-
},
|
|
25548
|
-
{
|
|
25549
|
-
type: "authorization_bearer",
|
|
25550
|
-
pattern: /\bAuthorization\s*:\s*Bearer\s+[A-Za-z0-9._~+/=-]{12,}/gi
|
|
25551
|
-
},
|
|
25552
|
-
{
|
|
25553
|
-
type: "env_secret",
|
|
25554
|
-
pattern: /\b(?:[A-Z][A-Z0-9]+_)+(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi
|
|
25555
|
-
},
|
|
25556
|
-
{ type: "gitlab_token", pattern: /\bgl(?:pat|ptt)-[A-Za-z0-9_-]{15,}\b/g },
|
|
25557
|
-
{ type: "slack_token", pattern: /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g },
|
|
25558
|
-
{
|
|
25559
|
-
type: "jwt_token",
|
|
25560
|
-
pattern: /\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g
|
|
25561
|
-
},
|
|
25562
|
-
{
|
|
25563
|
-
type: "aws_secret_access_key",
|
|
25564
|
-
pattern: /\b(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY|secret_access_key|SecretAccessKey)"?\s*[=:]\s*["']?[A-Za-z0-9/+=]{40}\b/g
|
|
25565
|
-
},
|
|
25566
|
-
{
|
|
25567
|
-
type: "aws_secret_access_key_context",
|
|
25568
|
-
pattern: /\bAKIA[0-9A-Z]{16}\b[^\n]{0,200}?\b[A-Za-z0-9/+=]{40}\b/g
|
|
25569
|
-
},
|
|
25570
|
-
{
|
|
25571
|
-
type: "stripe_secret_key",
|
|
25572
|
-
pattern: /\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\b/g
|
|
25573
|
-
},
|
|
25574
|
-
{ type: "google_api_key", pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g },
|
|
25575
|
-
{
|
|
25576
|
-
type: "openssh_private_key_block",
|
|
25577
|
-
pattern: /-----BEGIN[ ]OPENSSH[ ]PRIVATE[ ]KEY-----[\s\S]*?-----END[ ]OPENSSH[ ]PRIVATE[ ]KEY-----/g
|
|
25578
|
-
}
|
|
25579
|
-
];
|
|
25580
|
-
var REDACTION_POLICY_SALT = 2;
|
|
25581
|
-
function computeRedactionPolicyVersion(policy) {
|
|
25582
|
-
return REDACTION_POLICY_SALT * 1e6 + SECRET_PATTERNS.length * 2 + (policy.rejectDurableSecrets ? 1 : 0) + (policy.detectPii ? 4 : 0) + (policy.rejectDurablePii ? 8 : 0) + (policy.piiDetector === "ner" ? 16 : 0);
|
|
25583
|
-
}
|
|
25584
|
-
var FINGERPRINT_ALGORITHM_VERSION = 2;
|
|
25585
|
-
var LEGACY_FINGERPRINT_ALGORITHM_VERSION = 1;
|
|
25586
|
-
var _internals32 = {
|
|
25587
|
-
currentAlgorithmVersion: FINGERPRINT_ALGORITHM_VERSION
|
|
25588
|
-
};
|
|
25589
|
-
function classifyStoredFingerprintAlgorithmVersion(rawStoredVersion, currentVersion = _internals32.currentAlgorithmVersion) {
|
|
25590
|
-
const storedVersion = rawStoredVersion === undefined ? LEGACY_FINGERPRINT_ALGORITHM_VERSION : rawStoredVersion;
|
|
25591
|
-
if (typeof storedVersion !== "number" || !Number.isFinite(storedVersion)) {
|
|
25592
|
-
return { status: "unknown" };
|
|
25593
|
-
}
|
|
25594
|
-
return storedVersion === currentVersion ? { status: "comparable" } : { status: "mismatch", storedVersion, currentVersion };
|
|
25595
|
-
}
|
|
25596
|
-
function computeMemoryCohortFingerprint(input) {
|
|
25597
|
-
const canonical = stableCanonicalStringify(input);
|
|
25598
|
-
return createHash13("sha256").update(canonical).digest("hex").slice(0, 12);
|
|
25599
|
-
}
|
|
25600
|
-
function buildMemoryCohortFingerprintInput(config) {
|
|
25601
|
-
return {
|
|
25602
|
-
provider: config.provider,
|
|
25603
|
-
redaction_policy_version: computeRedactionPolicyVersion({
|
|
25604
|
-
rejectDurableSecrets: config.redaction.rejectDurableSecrets,
|
|
25605
|
-
detectPii: config.redaction.detectPii,
|
|
25606
|
-
rejectDurablePii: config.redaction.rejectDurablePii,
|
|
25607
|
-
piiDetector: config.redaction.piiDetector
|
|
25608
|
-
}),
|
|
25609
|
-
embedding_model: config.embeddings.model,
|
|
25610
|
-
embedding_dimension: config.embeddings.dimension,
|
|
25611
|
-
embedding_version: config.embeddings.version ?? "default"
|
|
25612
|
-
};
|
|
25613
|
-
}
|
|
25614
|
-
function findSecrets(text) {
|
|
25615
|
-
const findings = [];
|
|
25616
|
-
for (const { type, pattern } of SECRET_PATTERNS) {
|
|
25617
|
-
pattern.lastIndex = 0;
|
|
25618
|
-
for (const match of text.matchAll(pattern)) {
|
|
25619
|
-
if (match[0])
|
|
25620
|
-
findings.push({ type, match: match[0] });
|
|
25621
|
-
}
|
|
25622
|
-
}
|
|
25623
|
-
return findings;
|
|
25624
|
-
}
|
|
25625
|
-
function containsSecret(text) {
|
|
25626
|
-
return findSecrets(text).length > 0;
|
|
25627
|
-
}
|
|
25628
|
-
|
|
25629
26690
|
// src/memory/sentinel.ts
|
|
25630
26691
|
var MEMORY_RECALL_SENTINEL = "## Retrieved Swarm Memory";
|
|
25631
26692
|
|
|
@@ -35720,7 +36781,7 @@ async function runFinalizeStage(ctx) {
|
|
|
35720
36781
|
}
|
|
35721
36782
|
}
|
|
35722
36783
|
try {
|
|
35723
|
-
const { CuratorConfigSchema: CCS } = await import("./schema-
|
|
36784
|
+
const { CuratorConfigSchema: CCS } = await import("./schema-5zc62306.js");
|
|
35724
36785
|
const { config: pmLoadedConfig } = _internals41.loadPluginConfigWithMeta(ctx.directory);
|
|
35725
36786
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
35726
36787
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
@@ -37939,9 +39000,9 @@ var _internals45 = {
|
|
|
37939
39000
|
loadPluginConfigWithMeta,
|
|
37940
39001
|
loadCuratorDeps: async () => {
|
|
37941
39002
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
37942
|
-
import("./schema-
|
|
37943
|
-
import("./curator-
|
|
37944
|
-
import("./curator-llm-factory-
|
|
39003
|
+
import("./schema-5zc62306.js"),
|
|
39004
|
+
import("./curator-pjjw3ja4.js"),
|
|
39005
|
+
import("./curator-llm-factory-7mfvey3x.js")
|
|
37945
39006
|
]);
|
|
37946
39007
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
37947
39008
|
}
|
|
@@ -38950,7 +40011,7 @@ async function computeCurationDiagnostics(directory, entries) {
|
|
|
38950
40011
|
let scanCompleted = false;
|
|
38951
40012
|
let scanRemaining = 0;
|
|
38952
40013
|
try {
|
|
38953
|
-
const { getScanStatus } = await import("./scan-cursor-
|
|
40014
|
+
const { getScanStatus } = await import("./scan-cursor-q3530gc8.js");
|
|
38954
40015
|
const status = await getScanStatus(directory);
|
|
38955
40016
|
scanGeneration = status.generation;
|
|
38956
40017
|
scanCompleted = status.completed;
|
|
@@ -38958,19 +40019,19 @@ async function computeCurationDiagnostics(directory, entries) {
|
|
|
38958
40019
|
} catch {}
|
|
38959
40020
|
let configMatch = null;
|
|
38960
40021
|
try {
|
|
38961
|
-
const { isLinked: isLinked2 } = await import("./knowledge-link-
|
|
40022
|
+
const { isLinked: isLinked2 } = await import("./knowledge-link-z9cchqdj.js");
|
|
38962
40023
|
if (isLinked2(directory)) {
|
|
38963
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
40024
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-5zc62306.js");
|
|
38964
40025
|
let config;
|
|
38965
40026
|
try {
|
|
38966
|
-
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-
|
|
40027
|
+
const { loadPluginConfigWithMeta: loadPluginConfigWithMeta2 } = await import("./index-8n602qc2.js");
|
|
38967
40028
|
const loaded = loadPluginConfigWithMeta2(directory);
|
|
38968
40029
|
config = KnowledgeConfigSchema2.parse(loaded.config.knowledge ?? {});
|
|
38969
40030
|
} catch {
|
|
38970
40031
|
config = KnowledgeConfigSchema2.parse({});
|
|
38971
40032
|
}
|
|
38972
40033
|
const { cohortConfigFingerprint: cohortConfigFingerprint2 } = await import("./config-fingerprint-v22xh5a2.js");
|
|
38973
|
-
const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-
|
|
40034
|
+
const { buildConfigFingerprintInput: buildConfigFingerprintInput2, readCohortConfigFingerprint } = await import("./curation-policy-72qx868r.js");
|
|
38974
40035
|
const currentFp = cohortConfigFingerprint2(buildConfigFingerprintInput2(config));
|
|
38975
40036
|
const cohortFp = await readCohortConfigFingerprint(directory);
|
|
38976
40037
|
configMatch = cohortFp === null ? null : currentFp === cohortFp;
|
|
@@ -40283,7 +41344,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
40283
41344
|
const result = runConfigDoctor(config, directory);
|
|
40284
41345
|
let output;
|
|
40285
41346
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
40286
|
-
const { runConfigDoctorWithFixes } = await import("./config-doctor-
|
|
41347
|
+
const { runConfigDoctorWithFixes } = await import("./config-doctor-4jxf9w9e.js");
|
|
40287
41348
|
const fixResult = await runConfigDoctorWithFixes(directory, config, true, {
|
|
40288
41349
|
applyLossy: true
|
|
40289
41350
|
});
|
|
@@ -40321,7 +41382,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
40321
41382
|
`;
|
|
40322
41383
|
}
|
|
40323
41384
|
try {
|
|
40324
|
-
const { runModelPreflight } = await import("./model-preflight-
|
|
41385
|
+
const { runModelPreflight } = await import("./model-preflight-cv9kvw8h.js");
|
|
40325
41386
|
const preflight = await runModelPreflight(config, swarmState.opencodeClient);
|
|
40326
41387
|
if (preflight.catalogAvailable) {
|
|
40327
41388
|
const unresolved = preflight.resolutions.filter((resolution) => resolution.status === "unresolved");
|
|
@@ -41223,7 +42284,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
41223
42284
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
41224
42285
|
}
|
|
41225
42286
|
async function handleEvidenceSummaryCommand(directory) {
|
|
41226
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
42287
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-5ffkbs50.js");
|
|
41227
42288
|
const artifact = await buildEvidenceSummary(directory);
|
|
41228
42289
|
if (!artifact) {
|
|
41229
42290
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -76285,7 +77346,7 @@ async function runValidationWithTransientRetry(input, candidateContent, baseline
|
|
|
76285
77346
|
if (!input.dispatcher) {
|
|
76286
77347
|
throw new Error("no evaluation dispatcher available (cannot run validation)");
|
|
76287
77348
|
}
|
|
76288
|
-
const { createModelEvaluationExecutor: createModelEvaluationExecutor2 } = await import("./runner-
|
|
77349
|
+
const { createModelEvaluationExecutor: createModelEvaluationExecutor2 } = await import("./runner-eagt6gf8.js");
|
|
76289
77350
|
const executor = createModelEvaluationExecutor2(input.dispatcher, input.sessionId);
|
|
76290
77351
|
const result = await withProtectedSetIntegrity([evalInputRoot, ...protectedRoots(input.directory)], () => _internals97.evaluateCandidateV1({
|
|
76291
77352
|
projectRoot: input.directory,
|
|
@@ -78330,7 +79391,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
78330
79391
|
async function handleHelpCommand(ctx) {
|
|
78331
79392
|
const targetCommand = ctx.args.join(" ");
|
|
78332
79393
|
if (!targetCommand) {
|
|
78333
|
-
const { buildHelpText } = await import("./index-
|
|
79394
|
+
const { buildHelpText } = await import("./index-3qpr16k2.js");
|
|
78334
79395
|
return buildHelpText();
|
|
78335
79396
|
}
|
|
78336
79397
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -78339,7 +79400,7 @@ async function handleHelpCommand(ctx) {
|
|
|
78339
79400
|
return _internals100.buildDetailedHelp(resolved.key, resolved.entry);
|
|
78340
79401
|
}
|
|
78341
79402
|
const similar = _internals100.findSimilarCommands(targetCommand);
|
|
78342
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
79403
|
+
const { buildHelpText: fullHelp } = await import("./index-3qpr16k2.js");
|
|
78343
79404
|
if (similar.length > 0) {
|
|
78344
79405
|
return `Command '/swarm ${targetCommand}' not found.
|
|
78345
79406
|
|
|
@@ -78670,7 +79731,7 @@ var COMMAND_REGISTRY = {
|
|
|
78670
79731
|
},
|
|
78671
79732
|
"guardrail explain": {
|
|
78672
79733
|
handler: async (ctx) => {
|
|
78673
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
79734
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-b9vr4ta3.js");
|
|
78674
79735
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
78675
79736
|
},
|
|
78676
79737
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -78680,7 +79741,7 @@ var COMMAND_REGISTRY = {
|
|
|
78680
79741
|
},
|
|
78681
79742
|
"guardrail reset": {
|
|
78682
79743
|
handler: async (ctx) => {
|
|
78683
|
-
const { handleGuardrailReset } = await import("./guardrail-reset-
|
|
79744
|
+
const { handleGuardrailReset } = await import("./guardrail-reset-pggm9hx4.js");
|
|
78684
79745
|
return handleGuardrailReset(ctx.args, ctx.sessionID);
|
|
78685
79746
|
},
|
|
78686
79747
|
description: "Reset one exact active invocation/action circuit after repair",
|
|
@@ -78689,7 +79750,7 @@ var COMMAND_REGISTRY = {
|
|
|
78689
79750
|
},
|
|
78690
79751
|
"guardrail-explain": {
|
|
78691
79752
|
handler: async (ctx) => {
|
|
78692
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
79753
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-b9vr4ta3.js");
|
|
78693
79754
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
78694
79755
|
},
|
|
78695
79756
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -78699,7 +79760,7 @@ var COMMAND_REGISTRY = {
|
|
|
78699
79760
|
},
|
|
78700
79761
|
"guardrail-reset": {
|
|
78701
79762
|
handler: async (ctx) => {
|
|
78702
|
-
const { handleGuardrailReset } = await import("./guardrail-reset-
|
|
79763
|
+
const { handleGuardrailReset } = await import("./guardrail-reset-pggm9hx4.js");
|
|
78703
79764
|
return handleGuardrailReset(ctx.args, ctx.sessionID);
|
|
78704
79765
|
},
|
|
78705
79766
|
description: "Reset one exact active invocation/action circuit after repair",
|
|
@@ -78709,7 +79770,7 @@ var COMMAND_REGISTRY = {
|
|
|
78709
79770
|
},
|
|
78710
79771
|
"guardrail-log": {
|
|
78711
79772
|
handler: async (ctx) => {
|
|
78712
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
79773
|
+
const { handleGuardrailLog } = await import("./guardrail-log-hrt36jz5.js");
|
|
78713
79774
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
78714
79775
|
},
|
|
78715
79776
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -79155,7 +80216,7 @@ Subcommands:
|
|
|
79155
80216
|
handler: (ctx) => handleAbortPrWorkflowCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
79156
80217
|
description: "Clear a stuck PR_REVIEW/PR_FEEDBACK mechanical gate and stop the auto-resume loop [mode] [reason]",
|
|
79157
80218
|
args: "[PR_REVIEW|PR_FEEDBACK] [reason...]",
|
|
79158
|
-
details:
|
|
80219
|
+
details: 'Human-only escape hatch for an unrecoverable PR_REVIEW or PR_FEEDBACK mechanical gate. When the architect cannot reach complete_pr_workflow \u2014 for example a compound `git fetch && git checkout` was rejected as read-only shell syntax, the PR head cannot be fetched, or the working tree is on the wrong branch \u2014 running this clears the durable gate state for the current session and stops the auto-resume loop without depending on the trapped model. The agent itself cannot run this command; it must call the abort_pr_workflow tool (or ask you to run this command). Both paths funnel into the same fail-closed abortPrWorkflow hook, which refuses while the workflow is armed for publication or while PR workflow lanes are still in flight. Issue #2108 adds the two audited exits from an armed publication window: the invalidate_pr_feedback_publication tool (change approved content \u2014 every approval of the generation is superseded and the full ladder re-runs) and the abort_pr_workflow tool kind "cancel-publication" with cancel_publication: true and a reason (terminal no-publish cancellation; never grants push authority). A plain recovery or force abort never clears an armed window. This human-only force path has exactly one exception to the lane refusal (issue #2251): when the ONLY lanes still blocking are ones past the 30-minute staleness horizon that the liveness probe reports as still running \u2014 a lane nothing will ever settle on a schedule \u2014 it clears the gate anyway, names exactly which lanes it overrode, and finalizes their delegation records so the session can start a new PR workflow. Those sessions are NOT stopped and their output is NOT collected. A lane with a fresh updatedAt still blocks even under force, and any delegation record that still keeps the session blocked is named in the warning. When checkout preparation preserved a stash, the result instructs the caller to run prepare_pr_workflow_checkout operation=restore after the clear. An audit event is appended to .swarm/events.jsonl.',
|
|
79159
80220
|
category: "utility",
|
|
79160
80221
|
toolPolicy: "restricted"
|
|
79161
80222
|
},
|
|
@@ -84696,7 +85757,7 @@ function getDisplayFinalPromptPressure() {
|
|
|
84696
85757
|
async function rehydratePrSubscriptions(sessionID, directory) {
|
|
84697
85758
|
const map = new Map;
|
|
84698
85759
|
try {
|
|
84699
|
-
const { listActive: listActive2 } = await import("./pr-subscriptions-
|
|
85760
|
+
const { listActive: listActive2 } = await import("./pr-subscriptions-76vg2xya.js");
|
|
84700
85761
|
const records = await listActive2(directory);
|
|
84701
85762
|
for (const record of records) {
|
|
84702
85763
|
if (record.sessionID !== sessionID)
|
|
@@ -85142,7 +86203,7 @@ function isLaneOwnedByCurrentSession(branchName, expectedSessionId) {
|
|
|
85142
86203
|
return extracted === expectedSessionId;
|
|
85143
86204
|
}
|
|
85144
86205
|
async function inspectStandardWorktreeCollisionOwnership(identity) {
|
|
85145
|
-
const collisionOwnership = await import("./worktree-collision-ownership-
|
|
86206
|
+
const collisionOwnership = await import("./worktree-collision-ownership-2qxjtxt6.js");
|
|
85146
86207
|
return collisionOwnership.inspectStandardWorktreeCollisionOwnership(identity);
|
|
85147
86208
|
}
|
|
85148
86209
|
async function runRecoveryGit(directory, args, timeoutMs = 15000) {
|
|
@@ -85551,7 +86612,7 @@ async function precreateStandardWorktreeSession(args) {
|
|
|
85551
86612
|
const laneProfile = computeLaneRuntimeProfile(worktreeConfig.runtime_isolation, laneIndex, handle.worktreePath);
|
|
85552
86613
|
if (laneProfile) {
|
|
85553
86614
|
try {
|
|
85554
|
-
const { writeLaneProfileToDiskReal } = await import("./core-
|
|
86615
|
+
const { writeLaneProfileToDiskReal } = await import("./core-xf2f087t.js");
|
|
85555
86616
|
await writeLaneProfileToDiskReal(handle.worktreePath, laneProfile.laneIndex, laneProfile.envOverrides);
|
|
85556
86617
|
} catch {}
|
|
85557
86618
|
}
|
|
@@ -86476,7 +87537,7 @@ async function finishStandardWorktreeDispatch(directory, dispatch, config, callI
|
|
|
86476
87537
|
}
|
|
86477
87538
|
clearWorktreeMergeStatus(statusKey);
|
|
86478
87539
|
try {
|
|
86479
|
-
const { removeLaneProfileFromDiskReal } = await import("./core-
|
|
87540
|
+
const { removeLaneProfileFromDiskReal } = await import("./core-xf2f087t.js");
|
|
86480
87541
|
await removeLaneProfileFromDiskReal(dispatch.handle.worktreePath, dispatch.laneIndex);
|
|
86481
87542
|
} catch {}
|
|
86482
87543
|
const state = serializationStateBySessionID.get(dispatch.parentSessionID);
|
|
@@ -86679,4 +87740,4 @@ var _internals102 = {
|
|
|
86679
87740
|
resolveGitExecutable
|
|
86680
87741
|
};
|
|
86681
87742
|
|
|
86682
|
-
export { resetActionCircuitExternally, getBlockingActionCircuit, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcExtractRecursiveRmTargets, dcEvaluateRecursiveDeleteTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, getSharedClassifierGuardrailBlock, classifyCommand, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, getAgentSession, parseLeanLaneIndex, computeLaneRuntimeProfile, MAX_TRACKED_STANDARD_WORKTREE_CALLS, awaitingMergeByCallID, standardWorktreeByCallID, standardWorktreeSerializationSessions, getStandardWorktreeDegradationReason, resetStandardWorktreeIsolationState, checkStandardWorktreeSerializationRelease, sanitizeWorktreeTaskId, preProvisionCollisionCheck, isLaneOwnedByCurrentSession, precreateStandardWorktreeSession, preserveBackgroundWorktreeOwnershipForCallId, preserveDirtyWorktreeForCallId, preserveDirtyWorktreeAtPath, cleanupStandardWorktreeForCallId, abortStandardWorktreeDispatch, finishStandardWorktreeDispatch, readLaneEnvFileFromDisk, _internals102 as _internals, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleApproveWriteCommand, handleArchiveCommand, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleCiSimulateCommand, handleClarifyCommand, createCuratorLLMDelegate,
|
|
87743
|
+
export { resetActionCircuitExternally, getBlockingActionCircuit, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcExtractRecursiveRmTargets, dcEvaluateRecursiveDeleteTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, getSharedClassifierGuardrailBlock, classifyCommand, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, getAgentSession, parseLeanLaneIndex, computeLaneRuntimeProfile, MAX_TRACKED_STANDARD_WORKTREE_CALLS, awaitingMergeByCallID, standardWorktreeByCallID, standardWorktreeSerializationSessions, getStandardWorktreeDegradationReason, resetStandardWorktreeIsolationState, checkStandardWorktreeSerializationRelease, sanitizeWorktreeTaskId, preProvisionCollisionCheck, isLaneOwnedByCurrentSession, precreateStandardWorktreeSession, preserveBackgroundWorktreeOwnershipForCallId, preserveDirtyWorktreeForCallId, preserveDirtyWorktreeAtPath, cleanupStandardWorktreeForCallId, abortStandardWorktreeDispatch, finishStandardWorktreeDispatch, readLaneEnvFileFromDisk, _internals102 as _internals, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleApproveWriteCommand, handleArchiveCommand, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleCiSimulateCommand, handleClarifyCommand, createCuratorLLMDelegate, _internals26 as _internals1, normalizeRecommendationEntryIdToken, parseKnowledgeRecommendations, parseKnowledgeRecommendationsWithDiagnostics, parseStructuredCuratorBlocks, readCuratorSummary, writeCuratorSummary, appendCuratorRecommendation, mergeCuratorPhaseSummary, filterPhaseEvents, checkPhaseCompliance, runCuratorInit, runCuratorPhase, applyCuratorKnowledgeUpdates, isHiveEligible, countDistinctProjects, checkHivePromotions, _internals30 as _internals2, createHivePromoterHook, promoteToHive, promoteFromSwarm, safeRealpathSync, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, VERSION_PINNED_LEAF, discoverVersionPinnedCachePaths, readCachePackageVersion, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleGateAuditCommand, handleGateStatsCommand, handleHandoffCommand, handleBlueprintValidateCommand, handleBlueprintCurrentCommand, handleBlueprintHistoryCommand, handleBlueprintDiffCommand, handleBlueprintExportCommand, handleHarnessCandidateValidateCommand, handleHarnessCandidateShowCommand, handleHarnessCandidateDiffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryValueLogCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleRecoverCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleReviewCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals100 as _internals3, resolveCommand };
|