instar 1.3.647 → 1.3.648

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/commands/reflect.d.ts.map +1 -1
  2. package/dist/commands/reflect.js +7 -3
  3. package/dist/commands/reflect.js.map +1 -1
  4. package/dist/commands/server.d.ts.map +1 -1
  5. package/dist/commands/server.js +35 -0
  6. package/dist/commands/server.js.map +1 -1
  7. package/dist/commands/setup.d.ts.map +1 -1
  8. package/dist/commands/setup.js +17 -0
  9. package/dist/commands/setup.js.map +1 -1
  10. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  11. package/dist/config/ConfigDefaults.js +14 -0
  12. package/dist/config/ConfigDefaults.js.map +1 -1
  13. package/dist/core/CoherenceGate.d.ts.map +1 -1
  14. package/dist/core/CoherenceGate.js +24 -0
  15. package/dist/core/CoherenceGate.js.map +1 -1
  16. package/dist/core/CoherenceReviewer.d.ts +9 -0
  17. package/dist/core/CoherenceReviewer.d.ts.map +1 -1
  18. package/dist/core/CoherenceReviewer.js +18 -2
  19. package/dist/core/CoherenceReviewer.js.map +1 -1
  20. package/dist/core/InputGuard.d.ts.map +1 -1
  21. package/dist/core/InputGuard.js +17 -3
  22. package/dist/core/InputGuard.js.map +1 -1
  23. package/dist/core/MessageSentinel.d.ts.map +1 -1
  24. package/dist/core/MessageSentinel.js +19 -2
  25. package/dist/core/MessageSentinel.js.map +1 -1
  26. package/dist/core/MessagingToneGate.d.ts +8 -0
  27. package/dist/core/MessagingToneGate.d.ts.map +1 -1
  28. package/dist/core/MessagingToneGate.js +16 -1
  29. package/dist/core/MessagingToneGate.js.map +1 -1
  30. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  31. package/dist/core/PostUpdateMigrator.js +10 -0
  32. package/dist/core/PostUpdateMigrator.js.map +1 -1
  33. package/dist/core/SingleInstanceLock.d.ts +103 -0
  34. package/dist/core/SingleInstanceLock.d.ts.map +1 -0
  35. package/dist/core/SingleInstanceLock.js +300 -0
  36. package/dist/core/SingleInstanceLock.js.map +1 -0
  37. package/dist/core/SpawnCapIntelligenceProvider.d.ts +89 -0
  38. package/dist/core/SpawnCapIntelligenceProvider.d.ts.map +1 -0
  39. package/dist/core/SpawnCapIntelligenceProvider.js +164 -0
  40. package/dist/core/SpawnCapIntelligenceProvider.js.map +1 -0
  41. package/dist/core/hostSpawnSemaphore.d.ts +188 -0
  42. package/dist/core/hostSpawnSemaphore.d.ts.map +1 -0
  43. package/dist/core/hostSpawnSemaphore.js +471 -0
  44. package/dist/core/hostSpawnSemaphore.js.map +1 -0
  45. package/dist/core/intelligenceProviderFactory.d.ts +0 -12
  46. package/dist/core/intelligenceProviderFactory.d.ts.map +1 -1
  47. package/dist/core/intelligenceProviderFactory.js +27 -9
  48. package/dist/core/intelligenceProviderFactory.js.map +1 -1
  49. package/dist/core/types.d.ts +18 -0
  50. package/dist/core/types.d.ts.map +1 -1
  51. package/dist/core/types.js.map +1 -1
  52. package/dist/scaffold/templates.d.ts.map +1 -1
  53. package/dist/scaffold/templates.js +5 -0
  54. package/dist/scaffold/templates.js.map +1 -1
  55. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  56. package/dist/server/CapabilityIndex.js +9 -0
  57. package/dist/server/CapabilityIndex.js.map +1 -1
  58. package/dist/server/routes.d.ts.map +1 -1
  59. package/dist/server/routes.js +28 -0
  60. package/dist/server/routes.js.map +1 -1
  61. package/package.json +4 -2
  62. package/scripts/lint-no-direct-destructive.js +4 -0
  63. package/scripts/lint-no-unbounded-llm-spawn.js +137 -0
  64. package/src/data/builtin-manifest.json +63 -63
  65. package/src/scaffold/templates.ts +5 -0
  66. package/upgrades/1.3.648.md +99 -0
  67. package/upgrades/side-effects/forkbomb-prevention-simple.md +138 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.647",
3
+ "version": "1.3.648",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,7 +28,9 @@
28
28
  "test:contract": "node scripts/run-contract-tests.js",
29
29
  "test:contract:raw": "vitest run --config vitest.contract.config.ts",
30
30
  "test:all": "vitest run && vitest run --config vitest.integration.config.ts && vitest run --config vitest.e2e.config.ts",
31
- "lint": "tsc --noEmit && node scripts/lint-no-direct-destructive.js && node scripts/lint-no-direct-llm-http.js && node scripts/lint-no-direct-url-log.js && node scripts/lint-no-unfunneled-topic-creation.js && node scripts/lint-no-unfunneled-headless-launch.js && node scripts/lint-no-unfunneled-credential-write.js && node scripts/lint-state-registry.js && node scripts/lint-store-retention-declared.js && node scripts/lint-no-wholefile-sync-read.js && node scripts/lint-cas-emit-placement.js && node scripts/lint-journal-actuation-ban.js && node scripts/lint-no-blocking-process-scans.js && node scripts/lint-sync-subprocess-chokepoint.js && node scripts/lint-dev-agent-dark-gate.js && node scripts/lint-guard-manifest.js && node scripts/lint-llm-attribution.js && node scripts/lint-no-mainthread-cartographer-walk.js && node scripts/lint-scrape-fixture-realness.js && node scripts/check-codex-rule1-drift.js",
31
+ "lint": "tsc --noEmit && node scripts/lint-no-direct-destructive.js && node scripts/lint-no-direct-llm-http.js && node scripts/lint-no-direct-url-log.js && node scripts/lint-no-unfunneled-topic-creation.js && node scripts/lint-no-unfunneled-headless-launch.js && node scripts/lint-no-unbounded-llm-spawn.js && node scripts/lint-no-unfunneled-credential-write.js && node scripts/lint-state-registry.js && node scripts/lint-store-retention-declared.js && node scripts/lint-no-wholefile-sync-read.js && node scripts/lint-cas-emit-placement.js && node scripts/lint-journal-actuation-ban.js && node scripts/lint-no-blocking-process-scans.js && node scripts/lint-sync-subprocess-chokepoint.js && node scripts/lint-dev-agent-dark-gate.js && node scripts/lint-guard-manifest.js && node scripts/lint-llm-attribution.js && node scripts/lint-no-mainthread-cartographer-walk.js && node scripts/lint-scrape-fixture-realness.js && node scripts/check-codex-rule1-drift.js",
32
+ "lint:no-unbounded-llm-spawn": "node scripts/lint-no-unbounded-llm-spawn.js",
33
+ "lint:no-unbounded-llm-spawn:staged": "node scripts/lint-no-unbounded-llm-spawn.js --staged",
32
34
  "lint:destructive": "node scripts/lint-no-direct-destructive.js",
33
35
  "lint:dev-agent-dark-gate": "node scripts/lint-dev-agent-dark-gate.js",
34
36
  "lint:guard-manifest": "node scripts/lint-guard-manifest.js",
@@ -86,6 +86,10 @@ const ALLOWLIST = new Set([
86
86
  // Same bootstrap-escape pattern (june15-headless-spawn-reroute funnel
87
87
  // lint) — read-only `git diff --cached --name-only` only.
88
88
  'scripts/lint-no-unfunneled-headless-launch.js',
89
+ // Same bootstrap-escape pattern (fork-bomb spawn-cap funnel lint) —
90
+ // read-only `git diff --cached --name-only` for --staged. Cannot depend on
91
+ // the TS funnel because TS is not compiled when the lint runs in pre-push.
92
+ 'scripts/lint-no-unbounded-llm-spawn.js',
89
93
  // Same bootstrap-escape pattern (Step 4b credential-write funnel lint) —
90
94
  // read-only `git diff --cached --name-only` for --staged. Cannot depend on
91
95
  // the TS funnel because TS is not compiled when the lint runs in pre-push.
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * lint-no-unbounded-llm-spawn.js — refuses a raw LLM-CLI provider construction
4
+ * outside the spawn-cap funnel.
5
+ *
6
+ * Part of the SIMPLE fork-bomb prevention design
7
+ * (docs/specs/forkbomb-prevention-simple.md §P1). The host-wide concurrent-spawn
8
+ * cap is enforced by the SpawnCapIntelligenceProvider wrapper, which is installed
9
+ * at EVERY return arm of `buildIntelligenceProvider` (the factory funnel). Any
10
+ * code that constructs an LLM-CLI provider DIRECTLY —
11
+ * new ClaudeCliIntelligenceProvider(...)
12
+ * new CodexCliIntelligenceProvider(...)
13
+ * new GeminiCliIntelligenceProvider(...)
14
+ * new PiCliIntelligenceProvider(...)
15
+ * — bypasses that wrapper, re-introducing an UN-CAPPED spawn path: the exact
16
+ * 2026-06-20 fork-bomb vector (one `claude -p` per call, zero concurrency
17
+ * control). That bypass must fail CI, not be discovered on the next OOM.
18
+ *
19
+ * RULE: outside the allowlist below, no source file may construct one of those
20
+ * providers directly. Route through `buildIntelligenceProvider(...)` (the
21
+ * factory), which applies the spawn cap + circuit breaker.
22
+ *
23
+ * Exit codes: 0 — clean; 1 — at least one violation.
24
+ *
25
+ * Usage:
26
+ * node scripts/lint-no-unbounded-llm-spawn.js # full repo
27
+ * node scripts/lint-no-unbounded-llm-spawn.js --staged # staged files
28
+ */
29
+
30
+ import fs from 'node:fs';
31
+ import path from 'node:path';
32
+ import { execSync } from 'node:child_process';
33
+ import { fileURLToPath } from 'node:url';
34
+
35
+ const __filename = fileURLToPath(import.meta.url);
36
+ const ROOT = path.resolve(path.dirname(__filename), '..');
37
+
38
+ // The LLM-CLI provider classes — constructing any of them is a SPAWN-capable
39
+ // path (their evaluate() shells out to the CLI binary).
40
+ const PROVIDER_CLASSES = [
41
+ 'ClaudeCliIntelligenceProvider',
42
+ 'CodexCliIntelligenceProvider',
43
+ 'GeminiCliIntelligenceProvider',
44
+ 'PiCliIntelligenceProvider',
45
+ ];
46
+
47
+ // ── Allowlist (closed). Adding an entry requires review of WHY the callsite
48
+ // cannot route through buildIntelligenceProvider() (where the spawn-cap
49
+ // wrapper is installed), and how its spawn is otherwise bounded. ─────────
50
+ const ALLOWLIST = new Set([
51
+ // THE funnel — the spawn-cap wrapper is installed here, around every
52
+ // construction (wrapForFunnel).
53
+ 'src/core/intelligenceProviderFactory.ts',
54
+ // The provider definitions themselves (their own class bodies).
55
+ 'src/core/ClaudeCliIntelligenceProvider.ts',
56
+ 'src/core/CodexCliIntelligenceProvider.ts',
57
+ 'src/core/GeminiCliIntelligenceProvider.ts',
58
+ 'src/core/PiCliIntelligenceProvider.ts',
59
+ // This lint file mentions the symbols it greps for.
60
+ 'scripts/lint-no-unbounded-llm-spawn.js',
61
+ ]);
62
+
63
+ const SCAN_DIRS = ['src', 'scripts', 'templates'];
64
+ const EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.mjs', '.cjs']);
65
+
66
+ // `new <ProviderClass>(` — the construction. An IMPORT of the class is fine
67
+ // (the factory imports them); only a direct `new …(` outside the funnel is a
68
+ // bypass.
69
+ const PATTERNS = PROVIDER_CLASSES.map((cls) => new RegExp(`\\bnew\\s+${cls}\\s*\\(`));
70
+
71
+ function listFiles() {
72
+ const staged = process.argv.includes('--staged');
73
+ if (staged) {
74
+ const out = execSync('git diff --cached --name-only', { cwd: ROOT, encoding: 'utf-8' });
75
+ return out.split('\n').filter(Boolean);
76
+ }
77
+ const explicit = process.argv.slice(2).filter((a) => !a.startsWith('--'));
78
+ if (explicit.length) return explicit;
79
+
80
+ const files = [];
81
+ const walk = (dir) => {
82
+ let entries;
83
+ try {
84
+ entries = fs.readdirSync(dir, { withFileTypes: true });
85
+ } catch {
86
+ return;
87
+ }
88
+ for (const e of entries) {
89
+ if (e.name === 'node_modules' || e.name === '.git' || e.name === 'dist') continue;
90
+ const full = path.join(dir, e.name);
91
+ if (e.isDirectory()) walk(full);
92
+ else if (EXTENSIONS.has(path.extname(e.name))) files.push(path.relative(ROOT, full));
93
+ }
94
+ };
95
+ for (const d of SCAN_DIRS) walk(path.join(ROOT, d));
96
+ return files;
97
+ }
98
+
99
+ let violations = 0;
100
+ for (const rel of listFiles()) {
101
+ const normalized = rel.split(path.sep).join('/');
102
+ if (ALLOWLIST.has(normalized)) continue;
103
+ if (!EXTENSIONS.has(path.extname(normalized))) continue;
104
+ // Test files exercise the providers directly with stubs / real spawns under
105
+ // controlled conditions — they are not a production spawn path.
106
+ if (/(^|\/)tests\//.test(normalized) || /\.test\.[cm]?[jt]sx?$/.test(normalized)) continue;
107
+ const full = path.isAbsolute(normalized) ? normalized : path.join(ROOT, normalized);
108
+ let content;
109
+ try {
110
+ content = fs.readFileSync(full, 'utf-8');
111
+ } catch {
112
+ continue;
113
+ }
114
+ const lines = content.split('\n');
115
+ for (let i = 0; i < lines.length; i++) {
116
+ // Comment-only mentions are documentation, not a construction.
117
+ const trimmed = lines[i].trimStart();
118
+ if (/^(\/\/|\*|\/\*|#)/.test(trimmed)) continue;
119
+ for (const pattern of PATTERNS) {
120
+ if (pattern.test(lines[i])) {
121
+ console.error(
122
+ `${normalized}:${i + 1} — direct LLM-CLI provider construction outside the spawn-cap funnel. ` +
123
+ `Build it through buildIntelligenceProvider() (which installs the host-wide spawn cap + circuit breaker), ` +
124
+ `or add an allowlist entry here with a spawn-bounding justification.`,
125
+ );
126
+ violations++;
127
+ }
128
+ }
129
+ }
130
+ }
131
+
132
+ if (violations > 0) {
133
+ console.error(`\nlint-no-unbounded-llm-spawn: ${violations} violation(s). ` +
134
+ `See docs/specs/forkbomb-prevention-simple.md (§P1 — every spawn-capable provider must ride the spawn-cap funnel).`);
135
+ process.exit(1);
136
+ }
137
+ console.log('lint-no-unbounded-llm-spawn: clean');