dual-brain 0.2.18 → 0.2.19
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/bin/dual-brain.mjs +8 -5
- package/hooks/head-guard.mjs +6 -10
- package/install.mjs +2 -2
- package/package.json +1 -1
- package/src/cognitive-loop.mjs +2 -0
- package/src/session-lock.mjs +6 -0
package/bin/dual-brain.mjs
CHANGED
|
@@ -1151,7 +1151,10 @@ async function installGlobal() {
|
|
|
1151
1151
|
|
|
1152
1152
|
// Resolve absolute path to hooks directory via import.meta.url
|
|
1153
1153
|
const pkgRoot = join(__dirname, '..');
|
|
1154
|
-
|
|
1154
|
+
// Hooks live at hooks/ in the published package, .claude/hooks/ in dev
|
|
1155
|
+
const hooksDir = existsSync(join(pkgRoot, 'hooks', 'head-guard.mjs'))
|
|
1156
|
+
? join(pkgRoot, 'hooks')
|
|
1157
|
+
: join(pkgRoot, '.claude', 'hooks');
|
|
1155
1158
|
|
|
1156
1159
|
// Warn if running from npx (ephemeral path)
|
|
1157
1160
|
if (pkgRoot.includes('.npm/_npx') || pkgRoot.includes('npx-')) {
|
|
@@ -1178,9 +1181,9 @@ async function installGlobal() {
|
|
|
1178
1181
|
})();
|
|
1179
1182
|
|
|
1180
1183
|
if (hasProjectLocalHooks) {
|
|
1181
|
-
console.log(' hooks
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
+
console.log(' project-local hooks detected (will take precedence in this workspace)');
|
|
1185
|
+
}
|
|
1186
|
+
{
|
|
1184
1187
|
// Load existing settings (merge, never clobber)
|
|
1185
1188
|
let existing = {};
|
|
1186
1189
|
if (existsSync(globalSettingsPath)) {
|
|
@@ -4479,7 +4482,7 @@ async function askDefaultShell(cwd, rl, fx) {
|
|
|
4479
4482
|
` ${DIM}modifies${RST} ${YLW}.replit onBoot${RST}`,
|
|
4480
4483
|
` ${DIM}undo${RST} Settings → System → Startup`,
|
|
4481
4484
|
'',
|
|
4482
|
-
` ${CYAN}[
|
|
4485
|
+
` ${CYAN}[Enter]${RST} Start on boot ${DIM}[n] Run manually${RST}`,
|
|
4483
4486
|
];
|
|
4484
4487
|
process.stdout.write('\n' + panel('dual-brain setup', setupContent) + '\n');
|
|
4485
4488
|
|
package/hooks/head-guard.mjs
CHANGED
|
@@ -31,16 +31,12 @@ try {
|
|
|
31
31
|
const raw = readFileSync('/dev/stdin', 'utf8');
|
|
32
32
|
input = JSON.parse(raw);
|
|
33
33
|
} catch {
|
|
34
|
-
// Can't parse input — fail
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
process.stdout.write(JSON.stringify(output));
|
|
43
|
-
process.exit(2);
|
|
34
|
+
// Can't parse input — fail open. This hook's purpose is to block HEAD from
|
|
35
|
+
// implementing directly. If we can't parse stdin (e.g. subagent context where
|
|
36
|
+
// Claude Code doesn't pipe parseable JSON), blocking would incorrectly deny
|
|
37
|
+
// work agents. Allowing is safer: worst case HEAD slips through once, but
|
|
38
|
+
// work agents aren't blocked.
|
|
39
|
+
process.exit(0);
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
const toolName = input.tool_name || '';
|
package/install.mjs
CHANGED
|
@@ -913,9 +913,9 @@ function install(workspace, env, mode) {
|
|
|
913
913
|
'gpt-work-dispatcher.mjs', 'profiles.mjs',
|
|
914
914
|
'summary-checkpoint.mjs', 'decision-ledger.mjs', 'control-panel.mjs',
|
|
915
915
|
'risk-classifier.mjs', 'failure-detector.mjs',
|
|
916
|
-
'
|
|
916
|
+
'plan-generator.mjs', 'vibe-memory.mjs',
|
|
917
917
|
'wave-orchestrator.mjs',
|
|
918
|
-
'
|
|
918
|
+
'model-registry.mjs',
|
|
919
919
|
'auto-update-wrapper.mjs',
|
|
920
920
|
'head-guard.mjs',
|
|
921
921
|
];
|
package/package.json
CHANGED
package/src/cognitive-loop.mjs
CHANGED
|
@@ -197,6 +197,7 @@ export function enter(userMessage, context = {}) {
|
|
|
197
197
|
plan,
|
|
198
198
|
nextDispatch: prepared,
|
|
199
199
|
suggestion: prepared.blockers[0],
|
|
200
|
+
mode,
|
|
200
201
|
};
|
|
201
202
|
}
|
|
202
203
|
|
|
@@ -209,6 +210,7 @@ export function enter(userMessage, context = {}) {
|
|
|
209
210
|
plan,
|
|
210
211
|
nextDispatch: prepared,
|
|
211
212
|
estimatedCost: plan.estimatedCost,
|
|
213
|
+
mode,
|
|
212
214
|
};
|
|
213
215
|
}
|
|
214
216
|
|
package/src/session-lock.mjs
CHANGED
|
@@ -46,6 +46,12 @@ export function acquire({ force = false } = {}) {
|
|
|
46
46
|
return { acquired: true, sessionId: _sessionId, existingSession: null, mode: 'primary' };
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// Same process (re-entry within same session) — always grant
|
|
50
|
+
if (existing.pid === process.pid) {
|
|
51
|
+
_sessionId = existing.sessionId;
|
|
52
|
+
return { acquired: true, sessionId: _sessionId, existingSession: null, mode: 'primary' };
|
|
53
|
+
}
|
|
54
|
+
|
|
49
55
|
const age = Date.now() - existing.heartbeat;
|
|
50
56
|
|
|
51
57
|
if (age > STALE_THRESHOLD_MS || force) {
|