instar 1.3.1024 → 1.3.1026
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/commands/init.js +5 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +2 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +109 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/types.d.ts +10 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/GrowthDigestPublisher.d.ts +143 -2
- package/dist/monitoring/GrowthDigestPublisher.d.ts.map +1 -1
- package/dist/monitoring/GrowthDigestPublisher.js +404 -21
- package/dist/monitoring/GrowthDigestPublisher.js.map +1 -1
- package/dist/monitoring/GrowthMilestoneAnalyst.d.ts.map +1 -1
- package/dist/monitoring/GrowthMilestoneAnalyst.js +8 -2
- package/dist/monitoring/GrowthMilestoneAnalyst.js.map +1 -1
- package/dist/monitoring/guardManifest.d.ts.map +1 -1
- package/dist/monitoring/guardManifest.js +15 -0
- package/dist/monitoring/guardManifest.js.map +1 -1
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +13 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +23 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +65 -65
- package/src/data/state-coherence-registry.json +18 -0
- package/src/templates/hooks/settings-template.json +10 -0
- package/upgrades/1.2.39.md +13 -35
- package/upgrades/1.3.1025.md +76 -0
- package/upgrades/1.3.1026.md +80 -0
- package/upgrades/analysis-paralysis-guard-esm-safe.eli16.md +21 -0
- package/upgrades/analysis-paralysis-guard-init-parity.eli16.md +16 -0
- package/upgrades/growth-digest-fallback-tags.eli16.md +27 -0
- package/upgrades/side-effects/analysis-paralysis-guard-esm-safe.md +34 -0
- package/upgrades/side-effects/analysis-paralysis-guard-init-parity.md +34 -0
- package/upgrades/side-effects/analysis-paralysis-guard.md +66 -0
- package/upgrades/side-effects/growth-digest-fallback-tags.md +46 -0
- package/upgrades/side-effects/maturation-followthrough-fix-standard-c.md +138 -0
|
@@ -4437,6 +4437,13 @@ export class PostUpdateMigrator {
|
|
|
4437
4437
|
catch (err) {
|
|
4438
4438
|
result.errors.push(`slopcheck-guard.js: ${err instanceof Error ? err.message : String(err)}`);
|
|
4439
4439
|
}
|
|
4440
|
+
try {
|
|
4441
|
+
fs.writeFileSync(path.join(instarHooksDir, 'analysis-paralysis-guard.js'), this.getAnalysisParalysisGuardHook(), { mode: 0o755 });
|
|
4442
|
+
result.upgraded.push('hooks/instar/analysis-paralysis-guard.js (act-or-report-blocked checklist)');
|
|
4443
|
+
}
|
|
4444
|
+
catch (err) {
|
|
4445
|
+
result.errors.push(`analysis-paralysis-guard.js: ${err instanceof Error ? err.message : String(err)}`);
|
|
4446
|
+
}
|
|
4440
4447
|
try {
|
|
4441
4448
|
fs.writeFileSync(path.join(instarHooksDir, 'post-action-reflection.js'), this.getPostActionReflectionHook(), { mode: 0o755 });
|
|
4442
4449
|
result.upgraded.push('hooks/instar/post-action-reflection.js (evolution awareness)');
|
|
@@ -4628,6 +4635,7 @@ export class PostUpdateMigrator {
|
|
|
4628
4635
|
'compaction-recovery.sh', 'external-operation-gate.js', 'deferral-detector.js',
|
|
4629
4636
|
'self-stop-guard.js',
|
|
4630
4637
|
'slopcheck-guard.js',
|
|
4638
|
+
'analysis-paralysis-guard.js',
|
|
4631
4639
|
'post-action-reflection.js', 'external-communication-guard.js',
|
|
4632
4640
|
'scope-coherence-collector.js', 'scope-coherence-checkpoint.js',
|
|
4633
4641
|
'instructions-loaded-tracker.js', 'subagent-start-tracker.js',
|
|
@@ -10837,6 +10845,7 @@ Two layers keep my machine-to-machine \"ropes\" (Tailscale / LAN / Cloudflare) h
|
|
|
10837
10845
|
case 'deferral-detector': return this.getDeferralDetectorHook();
|
|
10838
10846
|
case 'self-stop-guard': return this.getSelfStopGuardHook();
|
|
10839
10847
|
case 'slopcheck-guard': return this.getSlopcheckGuardHook();
|
|
10848
|
+
case 'analysis-paralysis-guard': return this.getAnalysisParalysisGuardHook();
|
|
10840
10849
|
case 'post-action-reflection': return this.getPostActionReflectionHook();
|
|
10841
10850
|
case 'external-communication-guard': return this.getExternalCommunicationGuardHook();
|
|
10842
10851
|
case 'scope-coherence-collector': return this.getScopeCoherenceCollectorHook();
|
|
@@ -13014,6 +13023,106 @@ process.stdin.on('end', () => {
|
|
|
13014
13023
|
} catch { /* never block on errors */ }
|
|
13015
13024
|
process.exit(0);
|
|
13016
13025
|
})();
|
|
13026
|
+
`;
|
|
13027
|
+
}
|
|
13028
|
+
getAnalysisParalysisGuardHook() {
|
|
13029
|
+
return `#!/usr/bin/env node
|
|
13030
|
+
// Analysis-Paralysis Guard — catches agents stuck in a read-loop without acting.
|
|
13031
|
+
// PostToolUse hook. Tracks a sliding window of recent tool calls in a small
|
|
13032
|
+
// state file. If READ_ONLY tools (Read/Grep/Glob/WebFetch) fire 5+ times
|
|
13033
|
+
// in a row without an ACTION tool (Edit/Write/Bash/NotebookEdit) in between,
|
|
13034
|
+
// injects a "act or report blocked" checklist.
|
|
13035
|
+
//
|
|
13036
|
+
// Borrowed from gsd-executor's prompt — proven to kill a known failure mode
|
|
13037
|
+
// where agents spend the whole session researching and never commit.
|
|
13038
|
+
//
|
|
13039
|
+
// Cherry-picked into Instar's hook layer 2026-05-23 from the GSD-Instar
|
|
13040
|
+
// integration spike (docs/specs/topic-intent-layer.md + the spike report).
|
|
13041
|
+
// Signal-only — never blocks. Decision: approve + additionalContext.
|
|
13042
|
+
|
|
13043
|
+
// NOTE: uses \`await import('node:fs')\` inside the handler rather than a
|
|
13044
|
+
// top-level \`require\` — a bare require crashes outright in ESM-mode agents
|
|
13045
|
+
// (the hook-event-reporter lesson: an install-if-missing CJS hook left ESM
|
|
13046
|
+
// hosts permanently broken). Dynamic import works in both module systems.
|
|
13047
|
+
|
|
13048
|
+
const READ_ONLY_TOOLS = new Set(['Read', 'Grep', 'Glob', 'WebFetch', 'WebSearch']);
|
|
13049
|
+
const ACTION_TOOLS = new Set(['Edit', 'Write', 'Bash', 'NotebookEdit']);
|
|
13050
|
+
const PARALYSIS_THRESHOLD = 5;
|
|
13051
|
+
const STATE_FILE_REL = '.instar/state/analysis-paralysis-state.json';
|
|
13052
|
+
|
|
13053
|
+
let data = '';
|
|
13054
|
+
process.stdin.on('data', chunk => data += chunk);
|
|
13055
|
+
process.stdin.on('end', async () => {
|
|
13056
|
+
try {
|
|
13057
|
+
const fs = await import('node:fs');
|
|
13058
|
+
const path = await import('node:path');
|
|
13059
|
+
const input = JSON.parse(data);
|
|
13060
|
+
const toolName = input.tool_name || '';
|
|
13061
|
+
if (!toolName) process.exit(0);
|
|
13062
|
+
|
|
13063
|
+
// Locate state file. CLAUDE_PROJECT_DIR is set by Claude Code on every hook.
|
|
13064
|
+
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
13065
|
+
const stateFile = path.join(projectDir, STATE_FILE_REL);
|
|
13066
|
+
let state = { recent: [] };
|
|
13067
|
+
try {
|
|
13068
|
+
if (fs.existsSync(stateFile)) {
|
|
13069
|
+
state = JSON.parse(fs.readFileSync(stateFile, 'utf-8'));
|
|
13070
|
+
if (!Array.isArray(state.recent)) state.recent = [];
|
|
13071
|
+
}
|
|
13072
|
+
} catch { state = { recent: [] }; }
|
|
13073
|
+
|
|
13074
|
+
const sessionId = input.session_id || 'default';
|
|
13075
|
+
const now = new Date().toISOString();
|
|
13076
|
+
|
|
13077
|
+
// Action tool → reset the per-session window
|
|
13078
|
+
if (ACTION_TOOLS.has(toolName)) {
|
|
13079
|
+
state.recent = state.recent.filter(e => e.sessionId !== sessionId);
|
|
13080
|
+
try {
|
|
13081
|
+
fs.mkdirSync(path.dirname(stateFile), { recursive: true });
|
|
13082
|
+
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
|
|
13083
|
+
} catch { /* best effort */ }
|
|
13084
|
+
process.exit(0);
|
|
13085
|
+
}
|
|
13086
|
+
|
|
13087
|
+
// Read-only tool → append to the window
|
|
13088
|
+
if (READ_ONLY_TOOLS.has(toolName)) {
|
|
13089
|
+
state.recent.push({ sessionId, tool: toolName, at: now });
|
|
13090
|
+
// Cap total entries across sessions to bound state file size
|
|
13091
|
+
if (state.recent.length > 200) state.recent = state.recent.slice(-200);
|
|
13092
|
+
try {
|
|
13093
|
+
fs.mkdirSync(path.dirname(stateFile), { recursive: true });
|
|
13094
|
+
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
|
|
13095
|
+
} catch { /* best effort */ }
|
|
13096
|
+
|
|
13097
|
+
// Count contiguous read-only entries for THIS session
|
|
13098
|
+
const sessionEntries = state.recent.filter(e => e.sessionId === sessionId);
|
|
13099
|
+
const consecutiveRO = sessionEntries.length;
|
|
13100
|
+
|
|
13101
|
+
if (consecutiveRO >= PARALYSIS_THRESHOLD) {
|
|
13102
|
+
const checklist = [
|
|
13103
|
+
'ANALYSIS-PARALYSIS DETECTED — ' + consecutiveRO + ' consecutive read-only tool calls (' +
|
|
13104
|
+
sessionEntries.slice(-5).map(e => e.tool).join(' → ') + ') without an Edit / Write / Bash.',
|
|
13105
|
+
'',
|
|
13106
|
+
'You have been researching without acting. Two paths from here:',
|
|
13107
|
+
'',
|
|
13108
|
+
'1. ACT — pick the smallest concrete action you can take with what you already know and DO it.',
|
|
13109
|
+
' The next Edit / Write / Bash resets this counter.',
|
|
13110
|
+
'',
|
|
13111
|
+
'2. REPORT BLOCKED — if you genuinely cannot proceed, state precisely what is missing:',
|
|
13112
|
+
' - a specific file or value you need access to',
|
|
13113
|
+
' - a decision only the user can make',
|
|
13114
|
+
' - an external dependency that has not been provisioned',
|
|
13115
|
+
'',
|
|
13116
|
+
'If neither path is true, you are avoiding the hard part. Pick option 1.',
|
|
13117
|
+
];
|
|
13118
|
+
process.stdout.write(JSON.stringify({ decision: 'approve', additionalContext: checklist.join('\\n') }));
|
|
13119
|
+
process.exit(0);
|
|
13120
|
+
}
|
|
13121
|
+
}
|
|
13122
|
+
// Other tools (TaskCreate, etc.) — pass through unchanged
|
|
13123
|
+
} catch { /* never block on errors */ }
|
|
13124
|
+
process.exit(0);
|
|
13125
|
+
});
|
|
13017
13126
|
`;
|
|
13018
13127
|
}
|
|
13019
13128
|
getPostActionReflectionHook() {
|