@planu/cli 5.1.1 → 5.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/cli/commands/doctor.d.ts +22 -0
  3. package/dist/cli/commands/doctor.js +176 -2
  4. package/dist/config/environment-schema.json +161 -21
  5. package/dist/config/release-policy.json +0 -8
  6. package/dist/engine/autopilot/bootstrap.js +27 -0
  7. package/dist/engine/core-bridge.d.ts +28 -0
  8. package/dist/engine/core-bridge.js +67 -0
  9. package/dist/engine/drift-monitor.js +16 -18
  10. package/dist/engine/living-spec/hash-tracker.js +26 -28
  11. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
  12. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +4 -4
  13. package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
  14. package/dist/engine/planu-core.darwin-x64.node.sbom.json +4 -4
  15. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
  16. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +4 -4
  17. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
  18. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +4 -4
  19. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
  20. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +4 -4
  21. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
  22. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +4 -4
  23. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
  24. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +4 -4
  25. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
  26. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +4 -4
  27. package/dist/engine/spec-language/english-only.d.ts +14 -0
  28. package/dist/engine/spec-language/english-only.js +58 -0
  29. package/dist/engine/spec-migrator/criteria-scanner.js +11 -13
  30. package/dist/engine/spec-migrator/drift-detector.js +10 -12
  31. package/dist/engine/validation/validation-freshness.d.ts +20 -1
  32. package/dist/engine/validation/validation-freshness.js +181 -21
  33. package/dist/engine/validator/analyzer.d.ts +5 -2
  34. package/dist/engine/validator/analyzer.js +81 -23
  35. package/dist/engine/validator/deep-code-checker.d.ts +10 -0
  36. package/dist/engine/validator/deep-code-checker.js +33 -0
  37. package/dist/engine/validator/test-evidence-grounding.d.ts +56 -0
  38. package/dist/engine/validator/test-evidence-grounding.js +187 -0
  39. package/dist/engine/validator.js +15 -4
  40. package/dist/engine/vector-store/tfidf.d.ts +13 -9
  41. package/dist/engine/vector-store/tfidf.js +26 -0
  42. package/dist/engine/worker-config-loader.d.ts +1 -1
  43. package/dist/engine/worker-config-loader.js +1 -11
  44. package/dist/engine/workers/schema.d.ts +0 -8
  45. package/dist/engine/workers/schema.js +0 -1
  46. package/dist/i18n/index.d.ts +18 -0
  47. package/dist/i18n/index.js +40 -1
  48. package/dist/storage/global-store.d.ts +9 -0
  49. package/dist/storage/global-store.js +23 -0
  50. package/dist/storage/semantic-index-store.d.ts +23 -0
  51. package/dist/storage/semantic-index-store.js +105 -0
  52. package/dist/storage/status-store/self-healing.js +15 -17
  53. package/dist/tools/challenge-spec/scenarios-utils.js +5 -1
  54. package/dist/tools/create-spec.js +60 -15
  55. package/dist/tools/init-project/handler.js +78 -25
  56. package/dist/tools/learn.js +10 -8
  57. package/dist/tools/registry/auth.js +1 -11
  58. package/dist/tools/semantic-search-handler.js +5 -6
  59. package/dist/tools/status-handler.js +19 -6
  60. package/dist/tools/validate.js +6 -2
  61. package/dist/tools/validation-loop-handler.js +16 -15
  62. package/dist/types/analysis.d.ts +2 -0
  63. package/dist/types/spec-language-translation.d.ts +18 -0
  64. package/dist/types/spec-language-translation.js +5 -0
  65. package/dist/types/spec-registry.d.ts +0 -2
  66. package/dist/types/status.d.ts +2 -0
  67. package/dist/types/validation-receipt.d.ts +7 -0
  68. package/dist/types/vector-store.d.ts +18 -0
  69. package/dist/types/workers.d.ts +0 -3
  70. package/package.json +20 -20
  71. package/planu-native.json +8 -29
  72. package/planu-plugin.json +1 -1
  73. package/dist/engine/security/cve-refresher.d.ts +0 -12
  74. package/dist/engine/security/cve-refresher.js +0 -128
package/CHANGELOG.md CHANGED
@@ -1,3 +1,57 @@
1
+ ## [5.3.0] - 2026-08-05
2
+
3
+ ### Features
4
+ - feat(watchers): ignore non-actionable root events in validation freshness watchers (SPEC-1340)
5
+ - feat(release): harden local release pipeline — auth preflight, receipt env isolation, publish retry, visibility wait (SPEC-1369)
6
+
7
+ ### Bug Fixes
8
+ - fix(release): accept npm 12 keyed pack JSON across release gates (SPEC-1339)
9
+ - fix(validator): stop marking provably implemented test-only criteria as indeterminate (SPEC-1367)
10
+ - fix(deps): raise brace-expansion and postcss transitive floors past advisories (SPEC-1338)
11
+ - fix(readiness): fail strict readiness when canonical BDD extraction returns zero criteria (SPEC-1321)
12
+ - fix(lifecycle): route implementation review digests to done gates without entering reconciliation (SPEC-1328)
13
+ - fix(privacy): redact minimality policy locators from persisted artifacts (SPEC-1334)
14
+ - fix(create-spec): remove hardcoded test-framework commands from generated specs (SPEC-1234)
15
+ - fix(challenge): preserve title evidence in event capability detection (SPEC-1235)
16
+ - fix(release): enforce proprietary license and canonical plugin tool parity (SPEC-1236)
17
+
18
+ ### Tests
19
+ - test(release): make release preflight/receipt regressions deterministic under full-suite load (SPEC-1207)
20
+ - test(release): reconcile full test suite with local-only release policy and rollback semantics (SPEC-1373)
21
+
22
+ ### Chores
23
+ - chore(deps): update 11 patch/minor dependencies
24
+ - chore(planu): close stale lifecycle for SPEC-1010/1011 tool-reliability specs and record SPEC-1010 tech debt
25
+ - chore(planu): file SPEC-1374/1375/1376 dogfood bug specs
26
+
27
+
28
+ ## [5.2.0] - 2026-08-04
29
+
30
+ ### Features
31
+ - feat(autopilot): refresh semantic index fire-and-forget on spec:created (SPEC-1345)
32
+ - feat(i18n): auto-detect and persist user locale (SPEC-1347)
33
+ - feat(spec-language): offer translation instead of rejecting non-English specs (SPEC-1342)
34
+ - feat(semantic-search): persist index with incremental updates (SPEC-1345)
35
+
36
+ ### Bug Fixes
37
+ - fix(storage): classify non-ENOENT failures in sync global-config read
38
+ - fix(status): prefer implementing work over review work in compact status (SPEC-1228)
39
+ - fix(challenge): stop handler names activating event scenarios across clauses (SPEC-1262)
40
+
41
+ ### Performance
42
+ - perf(core-bridge): route main-thread hot paths through native dispatch (SPEC-1344)
43
+ - perf(init-project): parallelize independent pipeline stages (SPEC-1343)
44
+
45
+ ### Chores
46
+ - chore(website): regenerate deterministic product proof
47
+ - chore(planu): close lifecycle for 8 specs done + SPEC-1368 bug spec + session checkpoint
48
+ - chore(planu): file SPEC-1367 dogfood bug spec (validate false-negative on test-only criteria)
49
+ - chore(planu): file SPEC-1366 dogfood bug spec and refresh session context
50
+ - chore(doctor): remove commercial remnants and deepen diagnostics (SPEC-1346)
51
+ - chore(planu): file SPEC-1365 dogfood bug spec (teamSuggestion recommends unregistered tools)
52
+ - chore(planu): session checkpoint after v5.1.1 release
53
+
54
+
1
55
  ## [5.1.1] - 2026-08-04
2
56
 
3
57
  ### Bug Fixes
@@ -10,7 +10,29 @@ interface ToolCheck {
10
10
  paths: string[];
11
11
  format: 'standard' | 'zed';
12
12
  }
13
+ interface DeepCheckResult {
14
+ name: string;
15
+ /** 'warn' is a degraded-but-working state (e.g. TS fallback active); 'fail' blocks usage. */
16
+ status: 'ok' | 'warn' | 'fail';
17
+ detail: string;
18
+ }
13
19
  declare function checkTool(check: ToolCheck): ToolReport[];
20
+ /** Check (1): the running Node version satisfies the `engines.node` field in package.json. */
21
+ declare function checkNodeVersion(): DeepCheckResult;
22
+ /**
23
+ * Check (2): the native Rust module loads, with a remediation hint when it doesn't.
24
+ * Missing native is a supported degraded mode (TypeScript fallback stays correct), so
25
+ * this reports 'warn' rather than 'fail' — it never blocks `planu doctor`'s exit code.
26
+ */
27
+ declare function checkNativeModule(): DeepCheckResult;
28
+ /** Check (3): PLANU_HOME / the resolved data directory is writable. */
29
+ declare function checkDataDirWritable(): DeepCheckResult;
30
+ /** Check (4): the runtime SQLite database opens without corruption. */
31
+ declare function checkRuntimeDatabase(): DeepCheckResult;
32
+ /** Check (5): the active locale resolves to a real translated message. */
33
+ declare function checkLocaleResolution(): DeepCheckResult;
34
+ declare function runDeepChecks(): DeepCheckResult[];
35
+ export { checkNodeVersion, checkNativeModule, checkDataDirWritable, checkRuntimeDatabase, checkLocaleResolution, runDeepChecks, };
14
36
  export { checkTool };
15
37
  export declare const doctorCommand: CliCommand;
16
38
  //# sourceMappingURL=doctor.d.ts.map
@@ -1,9 +1,16 @@
1
1
  // cli/commands/doctor.ts — planu doctor: verify MCP installations health (SPEC-236)
2
- import { existsSync } from 'node:fs';
2
+ // Deep diagnostics (Node version, native engine, storage writability, runtime DB,
3
+ // locale resolution) added by SPEC-1346 / SPEC-1344.
4
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
3
5
  import { homedir } from 'node:os';
4
- import { join } from 'node:path';
6
+ import { dirname, join } from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
5
8
  import { bold, cyan, green, yellow, red, dim } from '../colors.js';
6
9
  import { readJsonFile, hasPlanuEntry } from './install.js';
10
+ import { resolveStorageLayout } from '../../storage/storage-layout.js';
11
+ import { RuntimeDatabase } from '../../storage/runtime-db.js';
12
+ import { probeNativeLoad } from '../../engine/core-bridge.js';
13
+ import { getLocale, t } from '../../i18n/index.js';
7
14
  // ---------------------------------------------------------------------------
8
15
  // Constants
9
16
  // ---------------------------------------------------------------------------
@@ -86,6 +93,166 @@ function checkTool(check) {
86
93
  }
87
94
  return reports;
88
95
  }
96
+ // ---------------------------------------------------------------------------
97
+ // Deep diagnostics (SPEC-1346 / SPEC-1344)
98
+ // ---------------------------------------------------------------------------
99
+ /** Root of the package, resolved relative to this module so it works from src/ and dist/. */
100
+ const PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), '../../../package.json');
101
+ function parseVersionTuple(version) {
102
+ const match = /(\d+)\.(\d+)\.(\d+)/.exec(version);
103
+ return [Number(match?.[1] ?? 0), Number(match?.[2] ?? 0), Number(match?.[3] ?? 0)];
104
+ }
105
+ function isVersionAtLeast(actual, required) {
106
+ for (let i = 0; i < 3; i++) {
107
+ const a = actual[i] ?? 0;
108
+ const r = required[i] ?? 0;
109
+ if (a !== r) {
110
+ return a > r;
111
+ }
112
+ }
113
+ return true;
114
+ }
115
+ /** Check (1): the running Node version satisfies the `engines.node` field in package.json. */
116
+ function checkNodeVersion() {
117
+ let requiredRange;
118
+ try {
119
+ const pkg = JSON.parse(readFileSync(PACKAGE_ROOT, 'utf-8'));
120
+ requiredRange = pkg.engines?.node ?? '';
121
+ }
122
+ catch {
123
+ return {
124
+ name: 'Node version',
125
+ status: 'fail',
126
+ detail: 'Could not read package.json engines field',
127
+ };
128
+ }
129
+ if (!requiredRange) {
130
+ return { name: 'Node version', status: 'ok', detail: `Running Node ${process.version}` };
131
+ }
132
+ const required = parseVersionTuple(requiredRange);
133
+ const actual = parseVersionTuple(process.version);
134
+ if (isVersionAtLeast(actual, required)) {
135
+ return {
136
+ name: 'Node version',
137
+ status: 'ok',
138
+ detail: `${process.version} satisfies ${requiredRange}`,
139
+ };
140
+ }
141
+ return {
142
+ name: 'Node version',
143
+ status: 'fail',
144
+ detail: `${process.version} does not satisfy required range ${requiredRange}. Upgrade Node to continue.`,
145
+ };
146
+ }
147
+ /**
148
+ * Check (2): the native Rust module loads, with a remediation hint when it doesn't.
149
+ * Missing native is a supported degraded mode (TypeScript fallback stays correct), so
150
+ * this reports 'warn' rather than 'fail' — it never blocks `planu doctor`'s exit code.
151
+ */
152
+ function checkNativeModule() {
153
+ if (process.env.DISABLE_NATIVE_CORE === '1') {
154
+ return {
155
+ name: 'Native engine',
156
+ status: 'ok',
157
+ detail: 'Disabled via DISABLE_NATIVE_CORE=1 (TypeScript fallback in use)',
158
+ };
159
+ }
160
+ const diagnostic = probeNativeLoad();
161
+ if (diagnostic.loaded) {
162
+ return { name: 'Native engine', status: 'ok', detail: `Loaded (${diagnostic.loaded})` };
163
+ }
164
+ const reason = diagnostic.errors[0] ?? 'unknown failure';
165
+ return {
166
+ name: 'Native engine',
167
+ status: 'warn',
168
+ detail: `Failed to load (${reason}). Running on the TypeScript fallback. Reinstall the platform package for your OS/arch to restore native acceleration.`,
169
+ };
170
+ }
171
+ /** Check (3): PLANU_HOME / the resolved data directory is writable. */
172
+ function checkDataDirWritable() {
173
+ const layout = resolveStorageLayout();
174
+ const probePath = join(layout.data, `.doctor-write-probe-${String(process.pid)}`);
175
+ try {
176
+ mkdirSync(layout.data, { recursive: true, mode: 0o700 });
177
+ writeFileSync(probePath, 'ok', { mode: 0o600 });
178
+ unlinkSync(probePath);
179
+ return { name: 'Data directory', status: 'ok', detail: `Writable: ${layout.data}` };
180
+ }
181
+ catch (error) {
182
+ const message = error instanceof Error ? error.message : String(error);
183
+ return {
184
+ name: 'Data directory',
185
+ status: 'fail',
186
+ detail: `Cannot write to ${layout.data} (${message}). Check ownership/permissions on that path or set PLANU_HOME to a writable location.`,
187
+ };
188
+ }
189
+ }
190
+ /** Check (4): the runtime SQLite database opens without corruption. */
191
+ function checkRuntimeDatabase() {
192
+ const layout = resolveStorageLayout();
193
+ try {
194
+ const db = new RuntimeDatabase({ path: layout.runtimeDatabase });
195
+ db.close();
196
+ return {
197
+ name: 'Runtime database',
198
+ status: 'ok',
199
+ detail: `Opens correctly: ${layout.runtimeDatabase}`,
200
+ };
201
+ }
202
+ catch (error) {
203
+ const message = error instanceof Error ? error.message : String(error);
204
+ return {
205
+ name: 'Runtime database',
206
+ status: 'fail',
207
+ detail: `Cannot open ${layout.runtimeDatabase} (${message}). Move or delete the corrupted file and retry — Planu recreates it on next use.`,
208
+ };
209
+ }
210
+ }
211
+ /** Check (5): the active locale resolves to a real translated message. */
212
+ function checkLocaleResolution() {
213
+ const locale = getLocale();
214
+ const sample = t('locale.changed', locale);
215
+ if (sample === 'locale.changed') {
216
+ return {
217
+ name: 'Locale resolution',
218
+ status: 'fail',
219
+ detail: `Locale "${locale}" resolved but message bundle failed to load. Reinstall Planu to restore i18n/messages/.`,
220
+ };
221
+ }
222
+ return { name: 'Locale resolution', status: 'ok', detail: `Resolved locale: ${locale}` };
223
+ }
224
+ function runDeepChecks() {
225
+ return [
226
+ checkNodeVersion(),
227
+ checkNativeModule(),
228
+ checkDataDirWritable(),
229
+ checkRuntimeDatabase(),
230
+ checkLocaleResolution(),
231
+ ];
232
+ }
233
+ function deepCheckIcon(status) {
234
+ if (status === 'ok') {
235
+ return green('+');
236
+ }
237
+ return status === 'warn' ? yellow('!') : red('x');
238
+ }
239
+ function deepCheckLabel(status) {
240
+ if (status === 'ok') {
241
+ return green('OK');
242
+ }
243
+ return status === 'warn' ? yellow('DEGRADED') : red('FAIL');
244
+ }
245
+ function printDeepChecks(results) {
246
+ process.stdout.write(`\n${bold('Deep diagnostics')}\n\n`);
247
+ for (const result of results) {
248
+ const icon = deepCheckIcon(result.status);
249
+ const label = deepCheckLabel(result.status);
250
+ process.stdout.write(` [${icon}] ${result.name.padEnd(18)} ${label}\n`);
251
+ process.stdout.write(` ${dim(result.detail)}\n`);
252
+ }
253
+ }
254
+ // Exported for tests
255
+ export { checkNodeVersion, checkNativeModule, checkDataDirWritable, checkRuntimeDatabase, checkLocaleResolution, runDeepChecks, };
89
256
  function statusIcon(status) {
90
257
  switch (status) {
91
258
  case 'ok':
@@ -143,9 +310,16 @@ export const doctorCommand = {
143
310
  }
144
311
  }
145
312
  printReports(allReports);
313
+ const deepChecks = runDeepChecks();
314
+ printDeepChecks(deepChecks);
146
315
  const installed = allReports.filter((r) => r.status === 'ok').length;
147
316
  const invalid = allReports.filter((r) => r.status === 'invalid-config').length;
317
+ const failedDeepChecks = deepChecks.filter((c) => c.status === 'fail').length;
148
318
  process.stdout.write('\n');
319
+ if (failedDeepChecks > 0) {
320
+ process.stdout.write(`${red('Warning:')} ${String(failedDeepChecks)} deep diagnostic check(s) failed. See remediation steps above.\n`);
321
+ process.exitCode = 1;
322
+ }
149
323
  if (invalid > 0) {
150
324
  process.stdout.write(`${yellow('Warning:')} ${String(invalid)} config file(s) have invalid JSON. Run ${cyan('planu install')} to fix.\n`);
151
325
  }
@@ -8,10 +8,34 @@
8
8
  "sensitivity": "secret",
9
9
  "default": null
10
10
  },
11
- { "name": "PLANU_AUTO_DRIFT", "type": "boolean", "scope": "runtime", "sensitivity": "public", "default": null },
12
- { "name": "PLANU_COMMENT", "type": "string", "scope": "runtime", "sensitivity": "public", "default": null },
13
- { "name": "PLANU_DISABLE_HOOKS", "type": "boolean", "scope": "runtime", "sensitivity": "public", "default": null },
14
- { "name": "PLANU_DRIFT_THRESHOLD", "type": "number", "scope": "runtime", "sensitivity": "public", "default": null },
11
+ {
12
+ "name": "PLANU_AUTO_DRIFT",
13
+ "type": "boolean",
14
+ "scope": "runtime",
15
+ "sensitivity": "public",
16
+ "default": null
17
+ },
18
+ {
19
+ "name": "PLANU_COMMENT",
20
+ "type": "string",
21
+ "scope": "runtime",
22
+ "sensitivity": "public",
23
+ "default": null
24
+ },
25
+ {
26
+ "name": "PLANU_DISABLE_HOOKS",
27
+ "type": "boolean",
28
+ "scope": "runtime",
29
+ "sensitivity": "public",
30
+ "default": null
31
+ },
32
+ {
33
+ "name": "PLANU_DRIFT_THRESHOLD",
34
+ "type": "number",
35
+ "scope": "runtime",
36
+ "sensitivity": "public",
37
+ "default": null
38
+ },
15
39
  {
16
40
  "name": "PLANU_ENABLE_AUTOCOMMIT",
17
41
  "type": "boolean",
@@ -26,7 +50,13 @@
26
50
  "sensitivity": "public",
27
51
  "default": null
28
52
  },
29
- { "name": "PLANU_FIGMA_CLIENT_ID", "type": "string", "scope": "runtime", "sensitivity": "public", "default": null },
53
+ {
54
+ "name": "PLANU_FIGMA_CLIENT_ID",
55
+ "type": "string",
56
+ "scope": "runtime",
57
+ "sensitivity": "public",
58
+ "default": null
59
+ },
30
60
  {
31
61
  "name": "PLANU_FIGMA_CLIENT_SECRET",
32
62
  "type": "string",
@@ -55,7 +85,13 @@
55
85
  "sensitivity": "private",
56
86
  "default": null
57
87
  },
58
- { "name": "PLANU_HOST", "type": "string", "scope": "runtime", "sensitivity": "public", "default": null },
88
+ {
89
+ "name": "PLANU_HOST",
90
+ "type": "string",
91
+ "scope": "runtime",
92
+ "sensitivity": "public",
93
+ "default": null
94
+ },
59
95
  {
60
96
  "name": "PLANU_MAX_PARALLEL_AGENTS",
61
97
  "type": "number",
@@ -63,7 +99,13 @@
63
99
  "sensitivity": "public",
64
100
  "default": null
65
101
  },
66
- { "name": "PLANU_MAX_TS_WATCHERS", "type": "number", "scope": "runtime", "sensitivity": "public", "default": null },
102
+ {
103
+ "name": "PLANU_MAX_TS_WATCHERS",
104
+ "type": "number",
105
+ "scope": "runtime",
106
+ "sensitivity": "public",
107
+ "default": null
108
+ },
67
109
  {
68
110
  "name": "PLANU_MONTHLY_BUDGET_USD",
69
111
  "type": "number",
@@ -71,7 +113,13 @@
71
113
  "sensitivity": "private",
72
114
  "default": null
73
115
  },
74
- { "name": "PLANU_NATIVE_PATH", "type": "string", "scope": "runtime", "sensitivity": "private", "default": null },
116
+ {
117
+ "name": "PLANU_NATIVE_PATH",
118
+ "type": "string",
119
+ "scope": "runtime",
120
+ "sensitivity": "private",
121
+ "default": null
122
+ },
75
123
  {
76
124
  "name": "PLANU_NETWORK_CONSENT",
77
125
  "type": "string",
@@ -79,8 +127,20 @@
79
127
  "sensitivity": "private",
80
128
  "default": null
81
129
  },
82
- { "name": "PLANU_OFFLINE", "type": "boolean", "scope": "runtime", "sensitivity": "public", "default": null },
83
- { "name": "PLANU_PLUGINS_DIR", "type": "string", "scope": "runtime", "sensitivity": "private", "default": null },
130
+ {
131
+ "name": "PLANU_OFFLINE",
132
+ "type": "boolean",
133
+ "scope": "runtime",
134
+ "sensitivity": "public",
135
+ "default": null
136
+ },
137
+ {
138
+ "name": "PLANU_PLUGINS_DIR",
139
+ "type": "string",
140
+ "scope": "runtime",
141
+ "sensitivity": "private",
142
+ "default": null
143
+ },
84
144
  {
85
145
  "name": "PLANU_PROJECT_DATA_DIR",
86
146
  "type": "string",
@@ -88,7 +148,13 @@
88
148
  "sensitivity": "private",
89
149
  "default": null
90
150
  },
91
- { "name": "PLANU_PROJECT_PATH", "type": "string", "scope": "runtime", "sensitivity": "private", "default": null },
151
+ {
152
+ "name": "PLANU_PROJECT_PATH",
153
+ "type": "string",
154
+ "scope": "runtime",
155
+ "sensitivity": "private",
156
+ "default": null
157
+ },
92
158
  {
93
159
  "name": "PLANU_QA_CHECK_TIMEOUT_MS",
94
160
  "type": "number",
@@ -96,11 +162,41 @@
96
162
  "sensitivity": "public",
97
163
  "default": null
98
164
  },
99
- { "name": "PLANU_RECORD_CASSETTES", "type": "boolean", "scope": "test", "sensitivity": "public", "default": null },
100
- { "name": "PLANU_REGISTRY_URL", "type": "string", "scope": "runtime", "sensitivity": "public", "default": null },
101
- { "name": "PLANU_SAGA_CHAOS", "type": "string", "scope": "test", "sensitivity": "public", "default": null },
102
- { "name": "PLANU_SESSION_BUDGET", "type": "number", "scope": "runtime", "sensitivity": "private", "default": null },
103
- { "name": "PLANU_SESSION_ID", "type": "string", "scope": "runtime", "sensitivity": "private", "default": null },
165
+ {
166
+ "name": "PLANU_RECORD_CASSETTES",
167
+ "type": "boolean",
168
+ "scope": "test",
169
+ "sensitivity": "public",
170
+ "default": null
171
+ },
172
+ {
173
+ "name": "PLANU_REGISTRY_URL",
174
+ "type": "string",
175
+ "scope": "runtime",
176
+ "sensitivity": "public",
177
+ "default": null
178
+ },
179
+ {
180
+ "name": "PLANU_SAGA_CHAOS",
181
+ "type": "string",
182
+ "scope": "test",
183
+ "sensitivity": "public",
184
+ "default": null
185
+ },
186
+ {
187
+ "name": "PLANU_SESSION_BUDGET",
188
+ "type": "number",
189
+ "scope": "runtime",
190
+ "sensitivity": "private",
191
+ "default": null
192
+ },
193
+ {
194
+ "name": "PLANU_SESSION_ID",
195
+ "type": "string",
196
+ "scope": "runtime",
197
+ "sensitivity": "private",
198
+ "default": null
199
+ },
104
200
  {
105
201
  "name": "PLANU_SUPPRESS_AUTOCOMMIT",
106
202
  "type": "boolean",
@@ -108,7 +204,13 @@
108
204
  "sensitivity": "public",
109
205
  "default": null
110
206
  },
111
- { "name": "PLANU_TELEMETRY", "type": "string", "scope": "runtime", "sensitivity": "public", "default": null },
207
+ {
208
+ "name": "PLANU_TELEMETRY",
209
+ "type": "string",
210
+ "scope": "runtime",
211
+ "sensitivity": "public",
212
+ "default": null
213
+ },
112
214
  {
113
215
  "name": "PLANU_TELEMETRY_CONSENT_VERSION",
114
216
  "type": "string",
@@ -123,9 +225,27 @@
123
225
  "sensitivity": "public",
124
226
  "default": null
125
227
  },
126
- { "name": "PLANU_TELEMETRY_TOKEN", "type": "string", "scope": "runtime", "sensitivity": "secret", "default": null },
127
- { "name": "PLANU_TIMING", "type": "boolean", "scope": "runtime", "sensitivity": "public", "default": null },
128
- { "name": "PLANU_TOOL_TIMEOUT_MS", "type": "number", "scope": "runtime", "sensitivity": "public", "default": null },
228
+ {
229
+ "name": "PLANU_TELEMETRY_TOKEN",
230
+ "type": "string",
231
+ "scope": "runtime",
232
+ "sensitivity": "secret",
233
+ "default": null
234
+ },
235
+ {
236
+ "name": "PLANU_TIMING",
237
+ "type": "boolean",
238
+ "scope": "runtime",
239
+ "sensitivity": "public",
240
+ "default": null
241
+ },
242
+ {
243
+ "name": "PLANU_TOOL_TIMEOUT_MS",
244
+ "type": "number",
245
+ "scope": "runtime",
246
+ "sensitivity": "public",
247
+ "default": null
248
+ },
129
249
  {
130
250
  "name": "PLANU_VALIDATE_LINT_TIMEOUT_MS",
131
251
  "type": "number",
@@ -133,7 +253,27 @@
133
253
  "sensitivity": "public",
134
254
  "default": null
135
255
  },
136
- { "name": "PLANU_VERBOSE_OUTPUT", "type": "boolean", "scope": "runtime", "sensitivity": "public", "default": null }
256
+ {
257
+ "name": "PLANU_VALIDATE_PROBE",
258
+ "type": "string",
259
+ "scope": "runtime",
260
+ "sensitivity": "public",
261
+ "default": null
262
+ },
263
+ {
264
+ "name": "PLANU_VALIDATE_PROBE_TIMEOUT_MS",
265
+ "type": "number",
266
+ "scope": "runtime",
267
+ "sensitivity": "public",
268
+ "default": null
269
+ },
270
+ {
271
+ "name": "PLANU_VERBOSE_OUTPUT",
272
+ "type": "boolean",
273
+ "scope": "runtime",
274
+ "sensitivity": "public",
275
+ "default": null
276
+ }
137
277
  ],
138
278
  "dynamicPatterns": [
139
279
  {
@@ -96,13 +96,5 @@
96
96
  { "id": "CC", "command": "clang" },
97
97
  { "id": "CXX", "command": "clang++" }
98
98
  ]
99
- },
100
- "workflowActions": {
101
- "actions/checkout": "d23441a48e516b6c34aea4fa41551a30e30af803",
102
- "actions/setup-node": "249970729cb0ef3589644e2896645e5dc5ba9c38",
103
- "actions/upload-artifact": "b7c566a772e6b6bfb58ed0dc250532a479d7789f",
104
- "pnpm/action-setup": "fc06bc1257f339d1d5d8b3a19a8cae5388b55320",
105
- "dtolnay/rust-toolchain": "2c7215f132e9ebf062739d9130488b56d53c060c",
106
- "Swatinem/rust-cache": "e18b497796c12c097a38f9edb9d0641fb99eee32"
107
99
  }
108
100
  }
@@ -99,6 +99,31 @@ function registerPluginInstalledListener() {
99
99
  })();
100
100
  });
101
101
  }
102
+ /**
103
+ * SPEC-1345 AC4: Fire-and-forget semantic index refresh on spec:created.
104
+ * Reconciles the persisted TF-IDF index against the current corpus so the next
105
+ * semantic_search call hits a warm, up-to-date index.
106
+ */
107
+ function registerSemanticIndexRefreshListener() {
108
+ onAutopilotEvent('spec:created', (event) => {
109
+ void (async () => {
110
+ try {
111
+ const { getOrCreateBackend } = await import('../../storage/vector-store/backend-factory.js');
112
+ const { SemanticIndexStore } = await import('../../storage/semantic-index-store.js');
113
+ const backend = await getOrCreateBackend(event.projectId);
114
+ const allDocs = await backend.getAll();
115
+ if (allDocs.length === 0) {
116
+ return;
117
+ }
118
+ const indexStore = new SemanticIndexStore(event.projectId, 'all');
119
+ await indexStore.loadOrBuild(allDocs.map((doc) => ({ id: doc.id, content: doc.content })));
120
+ }
121
+ catch {
122
+ /* best-effort — never surface to user */
123
+ }
124
+ })();
125
+ });
126
+ }
102
127
  const AUTOPILOT_EVENTS = [
103
128
  'spec:created',
104
129
  'spec:status:approved',
@@ -133,5 +158,7 @@ export function bootstrapAutopilotHandlers() {
133
158
  registerPluginInstalledListener();
134
159
  // SPEC-628: Register daily cron for auto_fix_health (moved from update_status cascade)
135
160
  registerDailyCronListener();
161
+ // SPEC-1345 AC4: Register semantic index refresh on spec:created
162
+ registerSemanticIndexRefreshListener();
136
163
  }
137
164
  //# sourceMappingURL=bootstrap.js.map
@@ -31,6 +31,34 @@ export declare function fastExtractTsRelations(rootPath: string, paths: string[]
31
31
  export declare function fastQueryAffectedNodes(seed: string, edges: GraphEdgeInputRs[], relationFilter: string[], policy: ProjectGraphLimitsPolicyRs, overrides?: Partial<ResolvedProjectGraphLimitsRs>): AffectedNodeRs[];
32
32
  export declare function fastQueryShortestPath(from: string, to: string, edges: GraphEdgeInputRs[], relationFilter: string[], policy: ProjectGraphLimitsPolicyRs, overrides?: Partial<ResolvedProjectGraphLimitsRs>): ShortestPathResultRs;
33
33
  export declare function fastSelectCompactGraphSlice(seeds: string[], nodes: GraphNodeInputRs[], edges: GraphEdgeInputRs[], policy: ProjectGraphLimitsPolicyRs, overrides?: Partial<ResolvedProjectGraphLimitsRs>): CompactGraphSliceRs;
34
+ /** Worker-dispatched variant of {@link fastDetectDriftParallel} for main-thread callers. */
35
+ export declare function fastDetectDriftParallelAsync(rootPath: string, keywords: string[]): Promise<{
36
+ value: DriftResult;
37
+ degradationNotice?: string;
38
+ }>;
39
+ /** Worker-dispatched variant of {@link fastScanAndHashFiles} for main-thread callers. */
40
+ export declare function fastScanAndHashFilesAsync(rootPath: string): Promise<{
41
+ value: FileHash[];
42
+ degradationNotice?: string;
43
+ }>;
44
+ /** Worker-dispatched variant of {@link fastScanProjectMetadata} for main-thread callers. */
45
+ export declare function fastScanProjectMetadataAsync(rootPath: string): Promise<{
46
+ value: FileMetadata[];
47
+ degradationNotice?: string;
48
+ }>;
49
+ /** Worker-dispatched variant of {@link fastScanSpecs} for main-thread callers. */
50
+ export declare function fastScanSpecsAsync(rootPath: string): Promise<{
51
+ value: SpecBriefRs[] | null;
52
+ degradationNotice?: string;
53
+ }>;
34
54
  export declare const isNativeActive: () => boolean;
35
55
  export declare const nativeLoadDiagnostic: () => NativeLoadDiagnostic;
56
+ /**
57
+ * Force a native load attempt regardless of the calling thread and return the
58
+ * resulting diagnostic. `nativeLoadDiagnostic()` alone only reports load state
59
+ * that some other main-thread-bypassing caller already triggered (e.g. the
60
+ * macOS Keychain port); this is the main-thread-safe way to actually probe
61
+ * native availability, used by `planu doctor`.
62
+ */
63
+ export declare const probeNativeLoad: () => NativeLoadDiagnostic;
36
64
  //# sourceMappingURL=core-bridge.d.ts.map