dual-brain 0.2.30 → 0.3.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/.dual-brain/docs/claude-code-extension-points.md +32 -0
- package/.dual-brain/docs/data-tools-capabilities.md +181 -0
- package/.dual-brain/docs/ecosystem-tools.md +91 -0
- package/.dual-brain/docs/panel-handoff.md +124 -0
- package/.dual-brain/docs/ruflo-analysis.md +48 -0
- package/bin/dual-brain.mjs +56 -56
- package/dist/mcp-server/index.d.ts +27 -0
- package/dist/mcp-server/index.js +359 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/src/agent-protocol.d.ts +163 -0
- package/dist/src/agent-protocol.js +368 -0
- package/dist/src/agent-protocol.js.map +1 -0
- package/dist/src/agents/registry.d.ts +52 -0
- package/dist/src/agents/registry.js +393 -0
- package/dist/src/agents/registry.js.map +1 -0
- package/dist/src/awareness.d.ts +93 -0
- package/dist/src/awareness.js +406 -0
- package/dist/src/awareness.js.map +1 -0
- package/dist/src/brief.d.ts +48 -0
- package/dist/src/brief.js +179 -0
- package/dist/src/brief.js.map +1 -0
- package/dist/src/calibration.d.ts +32 -0
- package/dist/src/calibration.js +133 -0
- package/dist/src/calibration.js.map +1 -0
- package/dist/src/checkpoint.d.ts +33 -0
- package/dist/src/checkpoint.js +99 -0
- package/dist/src/checkpoint.js.map +1 -0
- package/dist/src/ci-triage.d.ts +33 -0
- package/dist/src/ci-triage.js +193 -0
- package/dist/src/ci-triage.js.map +1 -0
- package/dist/src/cognitive-loop.d.ts +56 -0
- package/dist/src/cognitive-loop.js +495 -0
- package/dist/src/cognitive-loop.js.map +1 -0
- package/dist/src/collaboration.d.ts +147 -0
- package/dist/src/collaboration.js +438 -0
- package/dist/src/collaboration.js.map +1 -0
- package/dist/src/context-intel.d.ts +47 -0
- package/dist/src/context-intel.js +156 -0
- package/dist/src/context-intel.js.map +1 -0
- package/dist/src/context.d.ts +53 -0
- package/dist/src/context.js +332 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/continuity.d.ts +89 -0
- package/dist/src/continuity.js +230 -0
- package/dist/src/continuity.js.map +1 -0
- package/dist/src/cost-tracker.d.ts +47 -0
- package/dist/src/cost-tracker.js +170 -0
- package/dist/src/cost-tracker.js.map +1 -0
- package/dist/src/debrief.d.ts +53 -0
- package/dist/src/debrief.js +222 -0
- package/dist/src/debrief.js.map +1 -0
- package/dist/src/decide.d.ts +96 -0
- package/dist/src/decide.js +744 -0
- package/dist/src/decide.js.map +1 -0
- package/dist/src/decompose.d.ts +39 -0
- package/dist/src/decompose.js +218 -0
- package/dist/src/decompose.js.map +1 -0
- package/dist/src/detect.d.ts +91 -0
- package/dist/src/detect.js +544 -0
- package/dist/src/detect.js.map +1 -0
- package/dist/src/dispatch.d.ts +154 -0
- package/dist/src/dispatch.js +1306 -0
- package/dist/src/dispatch.js.map +1 -0
- package/dist/src/doctor.d.ts +421 -0
- package/dist/src/doctor.js +1689 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/engine.d.ts +70 -0
- package/dist/src/engine.js +155 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/envelope.d.ts +36 -0
- package/dist/src/envelope.js +80 -0
- package/dist/src/envelope.js.map +1 -0
- package/dist/src/failure-memory.d.ts +55 -0
- package/dist/src/failure-memory.js +175 -0
- package/dist/src/failure-memory.js.map +1 -0
- package/dist/src/fx.d.ts +87 -0
- package/dist/src/fx.js +272 -0
- package/dist/src/fx.js.map +1 -0
- package/dist/src/governance.d.ts +93 -0
- package/dist/src/governance.js +261 -0
- package/dist/src/governance.js.map +1 -0
- package/dist/src/handoff.d.ts +11 -0
- package/dist/src/handoff.js +90 -0
- package/dist/src/handoff.js.map +1 -0
- package/dist/src/head-protocol.d.ts +76 -0
- package/dist/src/head-protocol.js +109 -0
- package/dist/src/head-protocol.js.map +1 -0
- package/dist/src/head.d.ts +222 -0
- package/dist/src/head.js +765 -0
- package/dist/src/head.js.map +1 -0
- package/dist/src/health.d.ts +132 -0
- package/dist/src/health.js +435 -0
- package/dist/src/health.js.map +1 -0
- package/dist/src/inbox.d.ts +70 -0
- package/dist/src/inbox.js +218 -0
- package/dist/src/inbox.js.map +1 -0
- package/dist/src/index.d.ts +33 -0
- package/dist/src/index.js +38 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/install-hooks.d.ts +13 -0
- package/dist/src/install-hooks.js +88 -0
- package/dist/src/install-hooks.js.map +1 -0
- package/dist/src/integrity.d.ts +59 -0
- package/dist/src/integrity.js +206 -0
- package/dist/src/integrity.js.map +1 -0
- package/dist/src/intelligence.d.ts +104 -0
- package/dist/src/intelligence.js +391 -0
- package/dist/src/intelligence.js.map +1 -0
- package/dist/src/ledger.d.ts +54 -0
- package/dist/src/ledger.js +179 -0
- package/dist/src/ledger.js.map +1 -0
- package/dist/src/living-docs.d.ts +14 -0
- package/dist/src/living-docs.js +197 -0
- package/dist/src/living-docs.js.map +1 -0
- package/dist/src/memory-tiers.d.ts +37 -0
- package/dist/src/memory-tiers.js +160 -0
- package/dist/src/memory-tiers.js.map +1 -0
- package/dist/src/model-profiles.d.ts +65 -0
- package/dist/src/model-profiles.js +568 -0
- package/dist/src/model-profiles.js.map +1 -0
- package/dist/src/models.d.ts +58 -0
- package/dist/src/models.js +327 -0
- package/dist/src/models.js.map +1 -0
- package/dist/src/narrative.d.ts +54 -0
- package/dist/src/narrative.js +163 -0
- package/dist/src/narrative.js.map +1 -0
- package/dist/src/nextstep.d.ts +16 -0
- package/dist/src/nextstep.js +103 -0
- package/dist/src/nextstep.js.map +1 -0
- package/dist/src/observer.d.ts +18 -0
- package/dist/src/observer.js +251 -0
- package/dist/src/observer.js.map +1 -0
- package/dist/src/outcome.d.ts +110 -0
- package/dist/src/outcome.js +377 -0
- package/dist/src/outcome.js.map +1 -0
- package/dist/src/pipeline.d.ts +167 -0
- package/dist/src/pipeline.js +1503 -0
- package/dist/src/pipeline.js.map +1 -0
- package/dist/src/playbook.d.ts +59 -0
- package/dist/src/playbook.js +238 -0
- package/dist/src/playbook.js.map +1 -0
- package/dist/src/pr-agent.d.ts +97 -0
- package/dist/src/pr-agent.js +195 -0
- package/dist/src/pr-agent.js.map +1 -0
- package/dist/src/predictive.d.ts +57 -0
- package/dist/src/predictive.js +230 -0
- package/dist/src/predictive.js.map +1 -0
- package/dist/src/profile.d.ts +294 -0
- package/dist/src/profile.js +1347 -0
- package/dist/src/profile.js.map +1 -0
- package/dist/src/prompt-audit.d.ts +22 -0
- package/dist/src/prompt-audit.js +194 -0
- package/dist/src/prompt-audit.js.map +1 -0
- package/dist/src/prompt-intel.d.ts +12 -0
- package/dist/src/prompt-intel.js +321 -0
- package/dist/src/prompt-intel.js.map +1 -0
- package/dist/src/provider-context.d.ts +121 -0
- package/dist/src/provider-context.js +222 -0
- package/dist/src/provider-context.js.map +1 -0
- package/dist/src/provider-manager.d.ts +92 -0
- package/dist/src/provider-manager.js +428 -0
- package/dist/src/provider-manager.js.map +1 -0
- package/dist/src/receipt.d.ts +87 -0
- package/dist/src/receipt.js +326 -0
- package/dist/src/receipt.js.map +1 -0
- package/dist/src/recommendations.d.ts +13 -0
- package/dist/src/recommendations.js +291 -0
- package/dist/src/recommendations.js.map +1 -0
- package/dist/src/redact.d.ts +15 -0
- package/dist/src/redact.js +129 -0
- package/dist/src/redact.js.map +1 -0
- package/dist/src/replit.d.ts +397 -0
- package/dist/src/replit.js +1160 -0
- package/dist/src/replit.js.map +1 -0
- package/dist/src/repo.d.ts +149 -0
- package/dist/src/repo.js +416 -0
- package/dist/src/repo.js.map +1 -0
- package/dist/src/revert.d.ts +30 -0
- package/dist/src/revert.js +166 -0
- package/dist/src/revert.js.map +1 -0
- package/dist/src/room.d.ts +102 -0
- package/dist/src/room.js +212 -0
- package/dist/src/room.js.map +1 -0
- package/dist/src/routing-advisor.d.ts +57 -0
- package/dist/src/routing-advisor.js +221 -0
- package/dist/src/routing-advisor.js.map +1 -0
- package/dist/src/self-correct.d.ts +40 -0
- package/dist/src/self-correct.js +137 -0
- package/dist/src/self-correct.js.map +1 -0
- package/dist/src/session-lock.d.ts +35 -0
- package/dist/src/session-lock.js +134 -0
- package/dist/src/session-lock.js.map +1 -0
- package/dist/src/session.d.ts +267 -0
- package/dist/src/session.js +1660 -0
- package/dist/src/session.js.map +1 -0
- package/dist/src/settings-tui.d.ts +5 -0
- package/dist/src/settings-tui.js +422 -0
- package/dist/src/settings-tui.js.map +1 -0
- package/dist/src/setup-flow.d.ts +63 -0
- package/dist/src/setup-flow.js +233 -0
- package/dist/src/setup-flow.js.map +1 -0
- package/dist/src/signal.d.ts +19 -0
- package/dist/src/signal.js +122 -0
- package/dist/src/signal.js.map +1 -0
- package/dist/src/simmer.d.ts +85 -0
- package/dist/src/simmer.js +224 -0
- package/dist/src/simmer.js.map +1 -0
- package/dist/src/state-export.d.ts +129 -0
- package/dist/src/state-export.js +233 -0
- package/dist/src/state-export.js.map +1 -0
- package/dist/src/strategy.d.ts +54 -0
- package/dist/src/strategy.js +95 -0
- package/dist/src/strategy.js.map +1 -0
- package/dist/src/subscription.d.ts +40 -0
- package/dist/src/subscription.js +189 -0
- package/dist/src/subscription.js.map +1 -0
- package/dist/src/templates.d.ts +208 -0
- package/dist/src/templates.js +238 -0
- package/dist/src/templates.js.map +1 -0
- package/dist/src/test.d.ts +9 -0
- package/dist/src/test.js +1173 -0
- package/dist/src/test.js.map +1 -0
- package/dist/src/think-engine.d.ts +67 -0
- package/dist/src/think-engine.js +412 -0
- package/dist/src/think-engine.js.map +1 -0
- package/dist/src/tui.d.ts +71 -0
- package/dist/src/tui.js +242 -0
- package/dist/src/tui.js.map +1 -0
- package/dist/src/types.d.ts +177 -0
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/update-check.d.ts +7 -0
- package/dist/src/update-check.js +36 -0
- package/dist/src/update-check.js.map +1 -0
- package/dist/src/wave-planner.d.ts +30 -0
- package/dist/src/wave-planner.js +281 -0
- package/dist/src/wave-planner.js.map +1 -0
- package/hooks/head-guard.sh +41 -0
- package/hooks/task-classifier.mjs +328 -0
- package/hooks/vibe-router.mjs +387 -0
- package/package.json +29 -153
- package/src/agents/registry.mjs +0 -405
- package/src/awareness.mjs +0 -425
- package/src/brief.mjs +0 -266
- package/src/calibration.mjs +0 -148
- package/src/checkpoint.mjs +0 -109
- package/src/ci-triage.mjs +0 -191
- package/src/cognitive-loop.mjs +0 -562
- package/src/collaboration.mjs +0 -545
- package/src/context-intel.mjs +0 -158
- package/src/context.mjs +0 -389
- package/src/continuity.mjs +0 -298
- package/src/cost-tracker.mjs +0 -184
- package/src/debrief.mjs +0 -228
- package/src/decide.mjs +0 -1099
- package/src/decompose.mjs +0 -331
- package/src/detect.mjs +0 -702
- package/src/dispatch.mjs +0 -1447
- package/src/doctor.mjs +0 -1607
- package/src/envelope.mjs +0 -139
- package/src/failure-memory.mjs +0 -178
- package/src/fx.mjs +0 -276
- package/src/governance.mjs +0 -279
- package/src/handoff.mjs +0 -87
- package/src/head-protocol.mjs +0 -128
- package/src/head.mjs +0 -952
- package/src/health.mjs +0 -528
- package/src/inbox.mjs +0 -195
- package/src/index.mjs +0 -44
- package/src/install-hooks.mjs +0 -100
- package/src/integrity.mjs +0 -245
- package/src/intelligence.mjs +0 -447
- package/src/ledger.mjs +0 -196
- package/src/living-docs.mjs +0 -210
- package/src/memory-tiers.mjs +0 -193
- package/src/models.mjs +0 -363
- package/src/narrative.mjs +0 -169
- package/src/nextstep.mjs +0 -100
- package/src/observer.mjs +0 -241
- package/src/outcome.mjs +0 -400
- package/src/pipeline.mjs +0 -1711
- package/src/playbook.mjs +0 -257
- package/src/pr-agent.mjs +0 -214
- package/src/predictive.mjs +0 -250
- package/src/profile.mjs +0 -1411
- package/src/prompt-audit.mjs +0 -231
- package/src/prompt-intel.mjs +0 -325
- package/src/provider-context.mjs +0 -257
- package/src/receipt.mjs +0 -344
- package/src/recommendations.mjs +0 -296
- package/src/redact.mjs +0 -192
- package/src/replit.mjs +0 -1210
- package/src/repo.mjs +0 -445
- package/src/revert.mjs +0 -149
- package/src/routing-advisor.mjs +0 -204
- package/src/self-correct.mjs +0 -147
- package/src/session-lock.mjs +0 -160
- package/src/session.mjs +0 -1655
- package/src/settings-tui.mjs +0 -373
- package/src/setup-flow.mjs +0 -223
- package/src/signal.mjs +0 -115
- package/src/simmer.mjs +0 -241
- package/src/strategy.mjs +0 -235
- package/src/subscription.mjs +0 -212
- package/src/templates.mjs +0 -260
- package/src/think-engine.mjs +0 -428
- package/src/tui.mjs +0 -276
- package/src/update-check.mjs +0 -35
- package/src/wave-planner.mjs +0 -294
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* integrity.ts — State integrity primitives for dual-brain
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - atomicWriteJson / readJsonSafe — safe JSON file I/O with schema versioning
|
|
6
|
+
* - acquireLock / releaseLock / withLock — advisory file locks
|
|
7
|
+
* - lockedUpdate — locked atomic read-modify-write
|
|
8
|
+
* - atomicAppend — append-only ledger with lock
|
|
9
|
+
*/
|
|
10
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { dirname } from 'node:path';
|
|
12
|
+
/**
|
|
13
|
+
* Write JSON to filePath atomically via a temp file + rename.
|
|
14
|
+
* Adds _schemaVersion and _writtenAt to plain objects.
|
|
15
|
+
*/
|
|
16
|
+
export function atomicWriteJson(filePath, data, opts = {}) {
|
|
17
|
+
const { schemaVersion = 1, backup = false } = opts;
|
|
18
|
+
// Stamp schema version onto plain objects
|
|
19
|
+
if (data && typeof data === 'object' && !Array.isArray(data)) {
|
|
20
|
+
data._schemaVersion = schemaVersion;
|
|
21
|
+
data._writtenAt = new Date().toISOString();
|
|
22
|
+
}
|
|
23
|
+
const dir = dirname(filePath);
|
|
24
|
+
mkdirSync(dir, { recursive: true });
|
|
25
|
+
const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
26
|
+
const json = JSON.stringify(data, null, 2) + '\n';
|
|
27
|
+
// Write to temp file
|
|
28
|
+
writeFileSync(tmpPath, json);
|
|
29
|
+
// Validate the temp file is parseable before committing
|
|
30
|
+
try {
|
|
31
|
+
JSON.parse(readFileSync(tmpPath, 'utf8'));
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
unlinkSync(tmpPath);
|
|
35
|
+
throw new Error(`atomicWrite: validation failed for ${filePath}: ${err.message}`);
|
|
36
|
+
}
|
|
37
|
+
// Optionally back up the existing file
|
|
38
|
+
if (backup && existsSync(filePath)) {
|
|
39
|
+
const backupPath = filePath + '.bak';
|
|
40
|
+
try {
|
|
41
|
+
renameSync(filePath, backupPath);
|
|
42
|
+
}
|
|
43
|
+
catch { }
|
|
44
|
+
}
|
|
45
|
+
// Atomic rename — either fully succeeds or the original is untouched
|
|
46
|
+
renameSync(tmpPath, filePath);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Read and parse a JSON file safely, with optional schema migration.
|
|
50
|
+
* Falls back to a .bak copy on parse failure.
|
|
51
|
+
* Returns null when the file is absent or unrecoverable.
|
|
52
|
+
*/
|
|
53
|
+
export function readJsonSafe(filePath, opts = {}) {
|
|
54
|
+
const { expectedVersion, migrate } = opts;
|
|
55
|
+
if (!existsSync(filePath))
|
|
56
|
+
return null;
|
|
57
|
+
let data;
|
|
58
|
+
try {
|
|
59
|
+
data = JSON.parse(readFileSync(filePath, 'utf8'));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Primary file corrupt — try backup
|
|
63
|
+
const bakPath = filePath + '.bak';
|
|
64
|
+
if (existsSync(bakPath)) {
|
|
65
|
+
try {
|
|
66
|
+
data = JSON.parse(readFileSync(bakPath, 'utf8'));
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Schema version check with optional migration
|
|
77
|
+
if (expectedVersion !== undefined && data?._schemaVersion !== expectedVersion) {
|
|
78
|
+
if (migrate && typeof migrate === 'function') {
|
|
79
|
+
data = migrate(data, data?._schemaVersion, expectedVersion);
|
|
80
|
+
}
|
|
81
|
+
// Tolerant read: return data even without a migrator
|
|
82
|
+
}
|
|
83
|
+
return data;
|
|
84
|
+
}
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// 2. Advisory file locks
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
const LOCK_TIMEOUT_MS = 10_000; // stale lock threshold
|
|
89
|
+
const LOCK_RETRY_MS = 50; // busy-wait interval
|
|
90
|
+
const LOCK_MAX_RETRIES = 100; // max retries (~5 s)
|
|
91
|
+
/**
|
|
92
|
+
* Acquire an advisory lock for filePath by creating filePath.lock.
|
|
93
|
+
* Stale locks (> LOCK_TIMEOUT_MS old) are cleared automatically.
|
|
94
|
+
*/
|
|
95
|
+
export function acquireLock(filePath) {
|
|
96
|
+
const lockPath = filePath + '.lock';
|
|
97
|
+
// Clear stale or corrupt lock
|
|
98
|
+
if (existsSync(lockPath)) {
|
|
99
|
+
try {
|
|
100
|
+
const lockData = JSON.parse(readFileSync(lockPath, 'utf8'));
|
|
101
|
+
const age = Date.now() - (lockData.createdAt || 0);
|
|
102
|
+
if (age > LOCK_TIMEOUT_MS) {
|
|
103
|
+
unlinkSync(lockPath);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
try {
|
|
108
|
+
unlinkSync(lockPath);
|
|
109
|
+
}
|
|
110
|
+
catch { }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Spin-try to create the lock exclusively
|
|
114
|
+
let retries = 0;
|
|
115
|
+
while (retries < LOCK_MAX_RETRIES) {
|
|
116
|
+
try {
|
|
117
|
+
writeFileSync(lockPath, JSON.stringify({
|
|
118
|
+
pid: process.pid,
|
|
119
|
+
createdAt: Date.now(),
|
|
120
|
+
holder: process.argv[1] || 'unknown',
|
|
121
|
+
}), { flag: 'wx' }); // 'wx' = exclusive create, EEXIST if present
|
|
122
|
+
return { acquired: true, lockPath };
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
if (err.code === 'EEXIST') {
|
|
126
|
+
retries++;
|
|
127
|
+
// Synchronous busy-wait — intentional; only triggered under contention
|
|
128
|
+
const start = Date.now();
|
|
129
|
+
while (Date.now() - start < LOCK_RETRY_MS) { }
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
throw err; // Unexpected error — propagate
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return { acquired: false, lockPath, reason: 'timeout' };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Release a previously acquired lock.
|
|
139
|
+
*/
|
|
140
|
+
export function releaseLock(lockResult) {
|
|
141
|
+
if (lockResult?.lockPath) {
|
|
142
|
+
try {
|
|
143
|
+
unlinkSync(lockResult.lockPath);
|
|
144
|
+
}
|
|
145
|
+
catch { }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Run fn while holding an advisory lock on filePath.
|
|
150
|
+
* Throws if the lock cannot be acquired within the retry window.
|
|
151
|
+
*/
|
|
152
|
+
export function withLock(filePath, fn) {
|
|
153
|
+
const lock = acquireLock(filePath);
|
|
154
|
+
if (!lock.acquired) {
|
|
155
|
+
throw new Error(`Could not acquire lock for ${filePath}: ${lock.reason}`);
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
return fn();
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
releaseLock(lock);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Locked atomic read-modify-write.
|
|
166
|
+
* Reads the current JSON, passes it to updateFn, then writes the result.
|
|
167
|
+
* If updateFn returns undefined the file is left unchanged.
|
|
168
|
+
*/
|
|
169
|
+
export function lockedUpdate(filePath, updateFn, opts = {}) {
|
|
170
|
+
return withLock(filePath, () => {
|
|
171
|
+
const current = readJsonSafe(filePath, opts);
|
|
172
|
+
const updated = updateFn(current);
|
|
173
|
+
if (updated !== undefined) {
|
|
174
|
+
atomicWriteJson(filePath, updated, opts);
|
|
175
|
+
}
|
|
176
|
+
return updated;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// 3. Append-only ledger with lock
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
/**
|
|
183
|
+
* Append a NDJSON record to filePath under an advisory lock.
|
|
184
|
+
* On lock failure the write is attempted without a lock (best-effort).
|
|
185
|
+
*/
|
|
186
|
+
export async function atomicAppend(filePath, record) {
|
|
187
|
+
const line = JSON.stringify(record) + '\n';
|
|
188
|
+
const lock = acquireLock(filePath);
|
|
189
|
+
if (!lock.acquired) {
|
|
190
|
+
// Non-fatal: best-effort append without lock
|
|
191
|
+
try {
|
|
192
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
193
|
+
appendFileSync(filePath, line);
|
|
194
|
+
}
|
|
195
|
+
catch { }
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
200
|
+
appendFileSync(filePath, line);
|
|
201
|
+
}
|
|
202
|
+
finally {
|
|
203
|
+
releaseLock(lock);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=integrity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrity.js","sourceRoot":"","sources":["../../src/integrity.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAa,EAAE,OAAwB,EAAE;IACzF,MAAM,EAAE,aAAa,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IAEnD,0CAA0C;IAC1C,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5D,IAAgC,CAAC,cAAc,GAAG,aAAa,CAAC;QAChE,IAAgC,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1E,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpC,MAAM,OAAO,GAAG,GAAG,QAAQ,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IAElD,qBAAqB;IACrB,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAE7B,wDAAwD;IACxD,IAAI,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,UAAU,CAAC,OAAO,CAAC,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,sCAAsC,QAAQ,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,uCAAuC;IACvC,IAAI,MAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;QACrC,IAAI,CAAC;YAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACpD,CAAC;IAED,qEAAqE;IACrE,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,OAAqB,EAAE;IACpE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAE1C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;QACpC,MAAM,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;QAClC,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YACnD,CAAC;YAAC,MAAM,CAAC;gBAAC,OAAO,IAAI,CAAC;YAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,IAAI,eAAe,KAAK,SAAS,IAAK,IAAgC,EAAE,cAAc,KAAK,eAAe,EAAE,CAAC;QAC3G,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAC7C,IAAI,GAAG,OAAO,CAAC,IAAI,EAAG,IAAgC,EAAE,cAAoC,EAAE,eAAe,CAAC,CAAC;QACjH,CAAC;QACD,qDAAqD;IACvD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,uBAAuB;AACvD,MAAM,aAAa,GAAK,EAAE,CAAC,CAAK,qBAAqB;AACrD,MAAM,gBAAgB,GAAG,GAAG,CAAC,CAAG,qBAAqB;AAErD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IAEpC,8BAA8B;IAC9B,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;YAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;YACnD,IAAI,GAAG,GAAG,eAAe,EAAE,CAAC;gBAC1B,UAAU,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACxC,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,OAAO,GAAG,gBAAgB,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC;gBACrC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,SAAS;aACrC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,6CAA6C;YAClE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACtC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,OAAO,EAAE,CAAC;gBACV,uEAAuE;gBACvE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,aAAa,EAAE,CAAC,CAAA,CAAC;gBAC7C,SAAS;YACX,CAAC;YACD,MAAM,GAAG,CAAC,CAAC,+BAA+B;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,UAAkC;IAC5D,IAAI,UAAU,EAAE,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC;YAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACnD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAI,QAAgB,EAAE,EAAW;IACvD,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,WAAW,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,QAA0D,EAAE,OAAuC,EAAE;IAClJ,OAAO,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,kCAAkC;AAClC,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB,EAAE,MAAe;IAClE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAE3C,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnB,6CAA6C;QAC7C,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;YAAS,CAAC;QACT,WAAW,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* intelligence.ts — Situational awareness for every pipeline run.
|
|
3
|
+
* Reads project reality fresh, derives task context, and detects contradictions
|
|
4
|
+
* between what an agent plans to do and what is actually true.
|
|
5
|
+
*/
|
|
6
|
+
interface ParsedFailure {
|
|
7
|
+
prompt: string;
|
|
8
|
+
error: string;
|
|
9
|
+
approach: string;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
}
|
|
12
|
+
interface ParsedOutcome {
|
|
13
|
+
task: string;
|
|
14
|
+
success: boolean;
|
|
15
|
+
timestamp: number;
|
|
16
|
+
}
|
|
17
|
+
export interface ProjectBrief {
|
|
18
|
+
packageName: string;
|
|
19
|
+
version: string;
|
|
20
|
+
versionMajor: number;
|
|
21
|
+
description: string;
|
|
22
|
+
branch: string;
|
|
23
|
+
dirty: boolean;
|
|
24
|
+
dirtyFiles: string[];
|
|
25
|
+
recentCommits: string[];
|
|
26
|
+
aheadOfRemote: number;
|
|
27
|
+
brandName: string;
|
|
28
|
+
cliCommand: string;
|
|
29
|
+
moduleType: string;
|
|
30
|
+
entryPoint: string;
|
|
31
|
+
testCommand: string | null;
|
|
32
|
+
protectedPaths: string[];
|
|
33
|
+
recentFailures: ParsedFailure[];
|
|
34
|
+
recentOutcomes: ParsedOutcome[];
|
|
35
|
+
derivedAt: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Read project reality fresh. No cache. Returns a ProjectBrief.
|
|
39
|
+
*/
|
|
40
|
+
export declare function deriveProjectState(cwd?: string): ProjectBrief;
|
|
41
|
+
interface PriorAttempt {
|
|
42
|
+
approach?: string;
|
|
43
|
+
tier?: string;
|
|
44
|
+
failed: boolean;
|
|
45
|
+
reason?: string;
|
|
46
|
+
files?: string[];
|
|
47
|
+
filesChanged?: string[];
|
|
48
|
+
status?: string;
|
|
49
|
+
error?: string;
|
|
50
|
+
type?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface TaskBrief {
|
|
53
|
+
task: string;
|
|
54
|
+
priorAttempts: Array<{
|
|
55
|
+
approach: string;
|
|
56
|
+
failed: boolean;
|
|
57
|
+
reason: string;
|
|
58
|
+
}>;
|
|
59
|
+
activeConstraints: string[];
|
|
60
|
+
filesInScope: string[];
|
|
61
|
+
filesOutOfScope: string[];
|
|
62
|
+
escalationLevel: 'normal' | 'elevated' | 'critical';
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Derive task-scoped context from the current prompt and optional session events.
|
|
66
|
+
*/
|
|
67
|
+
export declare function deriveTaskContext(task?: string, recentEvents?: Array<PriorAttempt | null>): TaskBrief;
|
|
68
|
+
interface Plan {
|
|
69
|
+
description?: string;
|
|
70
|
+
assumptions?: Record<string, string> | string;
|
|
71
|
+
targetFiles?: string[];
|
|
72
|
+
}
|
|
73
|
+
interface Contradiction {
|
|
74
|
+
type: string;
|
|
75
|
+
severity: 'block' | 'warn';
|
|
76
|
+
message: string;
|
|
77
|
+
evidence: {
|
|
78
|
+
expected: string;
|
|
79
|
+
actual: string;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Detect contradictions between project reality, task context, and a proposed plan.
|
|
84
|
+
* Returns an array of contradiction objects.
|
|
85
|
+
*/
|
|
86
|
+
export declare function detectContradictions(projectBrief: ProjectBrief, taskBrief: TaskBrief | null, plan?: Plan): Contradiction[];
|
|
87
|
+
interface SessionContext {
|
|
88
|
+
relatedSessions?: unknown[];
|
|
89
|
+
riskSignals?: unknown;
|
|
90
|
+
priorAttempts?: Array<{
|
|
91
|
+
failed?: boolean;
|
|
92
|
+
status?: string;
|
|
93
|
+
daysAgo?: number;
|
|
94
|
+
when?: string;
|
|
95
|
+
error?: string;
|
|
96
|
+
reason?: string;
|
|
97
|
+
}>;
|
|
98
|
+
relevantFiles?: string[];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Format a compact situational awareness summary (max 15 lines) for agent prompts.
|
|
102
|
+
*/
|
|
103
|
+
export declare function formatBrief(projectBrief: ProjectBrief, taskBrief: TaskBrief | null, sessionContext?: SessionContext | null): string;
|
|
104
|
+
export {};
|