@planu/cli 5.3.27 → 5.3.29

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 +12 -0
  2. package/dist/cli/commands/doctor.d.ts +4 -10
  3. package/dist/cli/commands/doctor.js +5 -31
  4. package/dist/cli/commands/inspect.js +2 -14
  5. package/dist/cli/commands/offline.d.ts +1 -2
  6. package/dist/cli/commands/offline.js +24 -41
  7. package/dist/config/release-policy.json +1 -79
  8. package/dist/engine/auto-updater/release-verifier.js +17 -35
  9. package/dist/engine/core-bridge.d.ts +6 -23
  10. package/dist/engine/core-bridge.js +35 -376
  11. package/dist/engine/execution/job-runtime.d.ts +0 -11
  12. package/dist/engine/execution/job-runtime.js +0 -23
  13. package/dist/engine/living-spec/annotation-parser.js +0 -14
  14. package/dist/engine/project-graph/native.js +2 -2
  15. package/dist/engine/sandbox/profiles/macos.sb +33 -0
  16. package/dist/engine/scan-project/module-discoverer.js +10 -53
  17. package/dist/engine/validation/validation-receipt.d.ts +5 -0
  18. package/dist/engine/validation/validation-receipt.js +9 -1
  19. package/dist/engine/validator/deep-code-checker.js +19 -26
  20. package/dist/security/adapters/macos-keychain.d.ts +5 -3
  21. package/dist/security/adapters/macos-keychain.js +79 -18
  22. package/dist/tools/create-spec/autopilot-analyzer.d.ts +1 -1
  23. package/dist/tools/create-spec/autopilot-analyzer.js +2 -2
  24. package/dist/tools/create-spec/relevance-scorer.d.ts +1 -1
  25. package/dist/tools/create-spec/relevance-scorer.js +1 -17
  26. package/dist/tools/create-spec.js +1 -1
  27. package/dist/types/atomic-upgrade.d.ts +0 -2
  28. package/dist/types/core-bridge.d.ts +0 -108
  29. package/dist/types/core-bridge.js +1 -1
  30. package/dist/types/durable-job.d.ts +0 -40
  31. package/dist/types/security.d.ts +0 -5
  32. package/package.json +7 -43
  33. package/planu-plugin.json +1 -1
  34. package/dist/config/native-release-public-key.pem +0 -3
  35. package/dist/config/native-targets.json +0 -87
  36. package/dist/engine/execution/job-executor.d.ts +0 -16
  37. package/dist/engine/execution/job-executor.js +0 -140
  38. package/dist/engine/execution/native-relevance-scorer.d.ts +0 -6
  39. package/dist/engine/execution/native-relevance-scorer.js +0 -64
  40. package/dist/engine/execution/native-worker-dispatch.d.ts +0 -3
  41. package/dist/engine/execution/native-worker-dispatch.js +0 -46
  42. package/dist/engine/execution/native-worker-protocol.d.ts +0 -6
  43. package/dist/engine/execution/native-worker-protocol.js +0 -33
  44. package/dist/engine/execution/native-worker-runtime.d.ts +0 -4
  45. package/dist/engine/execution/native-worker-runtime.js +0 -177
  46. package/dist/engine/execution/native-worker-thread.d.ts +0 -2
  47. package/dist/engine/execution/native-worker-thread.js +0 -66
  48. package/dist/engine/macos-keychain-native-port.d.ts +0 -10
  49. package/dist/engine/macos-keychain-native-port.js +0 -64
  50. package/dist/engine/native-capability-policy.d.ts +0 -4
  51. package/dist/engine/native-capability-policy.js +0 -24
  52. package/dist/engine/native-platform.d.ts +0 -3
  53. package/dist/engine/native-platform.js +0 -44
  54. package/dist/engine/native-runtime-handshake.d.ts +0 -20
  55. package/dist/engine/native-runtime-handshake.js +0 -230
  56. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +0 -39
  57. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +0 -1310
  58. package/dist/engine/planu-core.darwin-x64.node.manifest.json +0 -39
  59. package/dist/engine/planu-core.darwin-x64.node.sbom.json +0 -1310
  60. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +0 -38
  61. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +0 -1310
  62. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +0 -38
  63. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +0 -1310
  64. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +0 -38
  65. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +0 -1310
  66. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +0 -38
  67. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +0 -1310
  68. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +0 -38
  69. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +0 -1310
  70. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +0 -38
  71. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +0 -1310
  72. package/dist/types/native-worker.d.ts +0 -48
  73. package/dist/types/native-worker.js +0 -2
  74. package/planu-native.json +0 -82
@@ -2,9 +2,8 @@ import { technologyValue } from '../technology-registry.js';
2
2
  // engine/scan-project/module-discoverer.ts — Detects module boundaries in a project (SPEC-134)
3
3
  // Language-agnostic: supports monorepo, package-based, framework-based, and directory-based detection.
4
4
  import { readFile, readdir, stat } from 'node:fs/promises';
5
- import { join, relative, basename, dirname } from 'node:path';
5
+ import { join, relative, basename } from 'node:path';
6
6
  import { glob } from 'glob';
7
- import { isNativeActive, fastFindFilesByName } from '../core-bridge.js';
8
7
  // === Constants ===
9
8
  const IGNORE_PATTERNS = [
10
9
  'node_modules',
@@ -210,29 +209,15 @@ async function detectMonorepo(projectPath) {
210
209
  return null;
211
210
  }
212
211
  const resolved = [];
213
- if (isNativeActive()) {
214
- // Rust: optimized directory resolution for monorepo patterns
215
- const pkgJsonPaths = fastFindFilesByName(projectPath, ['package.json']);
216
- // Filter directories that match the workspace globs (simplified heuristic).
217
- const dirs = pkgJsonPaths
218
- .map((p) => dirname(p))
219
- .map((p) => relative(projectPath, p))
220
- .filter((rel) => rel !== '' && !isIgnored(rel.split('/')[0] ?? ''));
221
- // In a real implementation we would match against workspaceGlobs exactly,
222
- // but for speed we take all dirs with package.json that aren't ignored.
223
- resolved.push(...dirs);
224
- }
225
- if (resolved.length === 0) {
226
- for (const pattern of workspaceGlobs) {
227
- // Append '/' to match only directories (glob treats trailing slash as dir-only)
228
- const dirPattern = pattern.endsWith('/') ? pattern : `${pattern}/`;
229
- const matches = await glob(dirPattern, {
230
- cwd: projectPath,
231
- ignore: IGNORE_PATTERNS.map((p) => `**/${p}/**`),
232
- });
233
- // Strip trailing slash glob may add
234
- resolved.push(...matches.map((m) => m.replace(/\/$/, '')));
235
- }
212
+ for (const pattern of workspaceGlobs) {
213
+ // Append '/' to match only directories (glob treats trailing slash as dir-only)
214
+ const dirPattern = pattern.endsWith('/') ? pattern : `${pattern}/`;
215
+ const matches = await glob(dirPattern, {
216
+ cwd: projectPath,
217
+ ignore: IGNORE_PATTERNS.map((p) => `**/${p}/**`),
218
+ });
219
+ // Strip trailing slash glob may add
220
+ resolved.push(...matches.map((m) => m.replace(/\/$/, '')));
236
221
  }
237
222
  if (resolved.length === 0) {
238
223
  return null;
@@ -255,34 +240,6 @@ async function detectMonorepo(projectPath) {
255
240
  }
256
241
  // === Package-based detection ===
257
242
  async function detectPackageBased(projectPath) {
258
- if (isNativeActive()) {
259
- const manifests = fastFindFilesByName(projectPath, PACKAGE_MANIFESTS);
260
- if (manifests.length > 0) {
261
- const modules = [];
262
- const seen = new Set();
263
- for (const m of manifests) {
264
- const rel = relative(projectPath, dirname(m));
265
- if (rel === '' || rel.includes('/') || isIgnored(rel) || seen.has(rel)) {
266
- continue;
267
- }
268
- seen.add(rel);
269
- const [estimatedFiles, language] = await Promise.all([
270
- countSourceFiles(join(projectPath, rel)),
271
- detectLanguage(join(projectPath, rel)),
272
- ]);
273
- modules.push({
274
- name: rel,
275
- path: rel,
276
- estimatedFiles,
277
- language,
278
- detectionMethod: 'package',
279
- });
280
- }
281
- if (modules.length > 0) {
282
- return modules;
283
- }
284
- }
285
- }
286
243
  const subdirs = await getSubdirs(projectPath);
287
244
  const modules = [];
288
245
  for (const subdir of subdirs) {
@@ -3,6 +3,11 @@ import type { RuntimeDatabase } from '../../storage/runtime-db.js';
3
3
  import { type StorageCatalogContext } from '../../storage/storage-catalog.js';
4
4
  export { normalizeValidationCommand } from './validation-receipt-codec.js';
5
5
  export declare const LOCAL_VALIDATION_RECEIPT_ISSUER = "planu-local-validator";
6
+ export declare class ValidationReceiptSignerUnavailableError extends Error {
7
+ readonly reason: 'PLATFORM_UNSUPPORTED' | 'PROVIDER_NONCANONICAL' | 'PROVIDER_UNAVAILABLE';
8
+ readonly code: 'VALIDATION_RECEIPT_SIGNER_UNAVAILABLE';
9
+ constructor(reason: 'PLATFORM_UNSUPPORTED' | 'PROVIDER_NONCANONICAL' | 'PROVIDER_UNAVAILABLE', remediation?: string);
10
+ }
6
11
  export declare class ValidationReceiptStore implements ValidationReceiptPersistence {
7
12
  private readonly options;
8
13
  private readonly logDirectory;
@@ -6,11 +6,19 @@ import { reportClassifiedDegradation } from '../../errors/classified-degradation
6
6
  import { resolvedStorageArtifactPath, } from '../../storage/storage-catalog.js';
7
7
  import { formatSecretReference, getSecretProvider, parseSecretReference, SecretProviderError, } from '../../security/secret-provider.js';
8
8
  import { redactText } from '../../security/redactor.js';
9
- import { ValidationReceiptSignerUnavailableError } from '../macos-keychain-native-port.js';
10
9
  import { acquireLock, releaseLock } from '../safety/file-mutex.js';
11
10
  import { canonicalize, DIGEST, ISSUER_ID, PROJECT_ID, receiptCore, safeProof, sha256, SPEC_ID, validBindings, validReceiptShape, } from './validation-receipt-codec.js';
12
11
  export { normalizeValidationCommand } from './validation-receipt-codec.js';
13
12
  export const LOCAL_VALIDATION_RECEIPT_ISSUER = 'planu-local-validator';
13
+ export class ValidationReceiptSignerUnavailableError extends Error {
14
+ reason;
15
+ code = 'VALIDATION_RECEIPT_SIGNER_UNAVAILABLE';
16
+ constructor(reason, remediation = 'Restart the MCP host and retry.') {
17
+ super(`[Planu] VALIDATION_RECEIPT_SIGNER_UNAVAILABLE:${reason} ${remediation}`);
18
+ this.reason = reason;
19
+ this.name = 'ValidationReceiptSignerUnavailableError';
20
+ }
21
+ }
14
22
  export class ValidationReceiptStore {
15
23
  options;
16
24
  logDirectory;
@@ -1,7 +1,7 @@
1
1
  // Planu — Validator: deep code checker
2
2
  // Performs real filesystem/grep analysis for spec criteria that go beyond file-name matching.
3
3
  import { readFile, stat } from 'node:fs/promises';
4
- import { join, relative } from 'node:path';
4
+ import { join } from 'node:path';
5
5
  import { glob } from 'glob';
6
6
  const DEFAULT_IGNORE = ['node_modules/**', 'dist/**', 'build/**', '.git/**', 'coverage/**'];
7
7
  function escapeRegex(input) {
@@ -152,7 +152,6 @@ async function resolveFiles(scopeGlob, projectPath, exclude) {
152
152
  }
153
153
  }
154
154
  // ─── Checkers ─────────────────────────────────────────────────────────────────
155
- import { isNativeActive, fastFindPatterns } from '../core-bridge.js';
156
155
  function buildRegex(pattern) {
157
156
  try {
158
157
  return new RegExp(pattern, 'g');
@@ -174,32 +173,26 @@ function buildRegex(pattern) {
174
173
  */
175
174
  export async function grepCheck(config, projectPath, checkType) {
176
175
  const evidence = [];
177
- if (isNativeActive()) {
178
- const results = fastFindPatterns(projectPath, [config.pattern], [], config.exclude ? [config.exclude] : []);
179
- evidence.push(...results.map((r) => `${relative(projectPath, r.path)}:${r.line}`));
180
- }
181
- else {
182
- const files = await resolveFiles(config.scope, projectPath, config.exclude);
183
- const regex = buildRegex(config.pattern);
184
- if (regex) {
185
- await Promise.all(files.map(async (file) => {
186
- const fullPath = join(projectPath, file);
187
- try {
188
- const content = await readFile(fullPath, 'utf-8');
189
- const lines = content.split('\n');
190
- for (let i = 0; i < lines.length; i++) {
191
- const line = lines[i];
192
- if (line !== undefined && regex.test(line)) {
193
- evidence.push(`${file}:${i + 1}`);
194
- regex.lastIndex = 0;
195
- }
176
+ const files = await resolveFiles(config.scope, projectPath, config.exclude);
177
+ const regex = buildRegex(config.pattern);
178
+ if (regex) {
179
+ await Promise.all(files.map(async (file) => {
180
+ const fullPath = join(projectPath, file);
181
+ try {
182
+ const content = await readFile(fullPath, 'utf-8');
183
+ const lines = content.split('\n');
184
+ for (let i = 0; i < lines.length; i++) {
185
+ const line = lines[i];
186
+ if (line !== undefined && regex.test(line)) {
187
+ evidence.push(`${file}:${i + 1}`);
188
+ regex.lastIndex = 0;
196
189
  }
197
190
  }
198
- catch {
199
- // Skip unreadable files
200
- }
201
- }));
202
- }
191
+ }
192
+ catch {
193
+ // Skip unreadable files
194
+ }
195
+ }));
203
196
  }
204
197
  const matchCount = evidence.length;
205
198
  const passed = checkType === 'grep_absent' ? matchCount === 0 : matchCount >= config.expected;
@@ -1,15 +1,17 @@
1
- import type { MacOSKeychainNativePort, MacOSKeychainOperation, SecretStoreAdapter } from '../../types/security.js';
1
+ import type { MacOSKeychainOperation, SecretStoreAdapter } from '../../types/security.js';
2
2
  export declare class MacOSKeychainOperationError extends Error {
3
3
  readonly code: 'KEYCHAIN_TIMEOUT' | 'KEYCHAIN_OUTCOME_UNKNOWN';
4
4
  constructor(code: 'KEYCHAIN_TIMEOUT' | 'KEYCHAIN_OUTCOME_UNKNOWN', operation: MacOSKeychainOperation);
5
5
  }
6
6
  export declare class MacOSKeychainAdapter implements SecretStoreAdapter {
7
- private readonly nativePort;
7
+ private readonly run;
8
8
  private readonly timeoutMs;
9
9
  readonly kind: 'macos-keychain';
10
10
  private readonly pending;
11
11
  private nextFence;
12
- constructor(nativePort?: () => MacOSKeychainNativePort, timeoutMs?: number);
12
+ constructor(run?: (args: string[]) => Promise<{
13
+ stdout: string;
14
+ }>, timeoutMs?: number);
13
15
  get(id: string): Promise<string | null>;
14
16
  set(id: string, value: string): Promise<void>;
15
17
  delete(id: string): Promise<void>;
@@ -1,6 +1,20 @@
1
- import { requireMacOSKeychainNativePort } from '../../engine/core-bridge.js';
1
+ import { execFile as execFileCallback } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import { reportClassifiedDegradation } from '../../errors/classified-degradation.js';
4
+ const execFile = promisify(execFileCallback);
2
5
  const TIMEOUT_MS = 10_000;
3
- const decoder = new TextDecoder('utf-8', { fatal: true });
6
+ const SERVICE_LABEL = 'Planu';
7
+ const MISSING_ITEM_EXIT_CODE = 44;
8
+ async function defaultSecurityRun(args) {
9
+ return execFile('/usr/bin/security', args, { timeout: TIMEOUT_MS });
10
+ }
11
+ function isMissingCredentialExit(error) {
12
+ const failure = error;
13
+ return failure.code === MISSING_ITEM_EXIT_CODE || failure.code === String(MISSING_ITEM_EXIT_CODE);
14
+ }
15
+ function stripTrailingNewline(value) {
16
+ return value.endsWith('\n') ? value.slice(0, -1) : value;
17
+ }
4
18
  export class MacOSKeychainOperationError extends Error {
5
19
  code;
6
20
  constructor(code, operation) {
@@ -12,13 +26,13 @@ export class MacOSKeychainOperationError extends Error {
12
26
  }
13
27
  }
14
28
  export class MacOSKeychainAdapter {
15
- nativePort;
29
+ run;
16
30
  timeoutMs;
17
31
  kind = 'macos-keychain';
18
32
  pending = new Map();
19
33
  nextFence = 0;
20
- constructor(nativePort = requireMacOSKeychainNativePort, timeoutMs = TIMEOUT_MS) {
21
- this.nativePort = nativePort;
34
+ constructor(run = defaultSecurityRun, timeoutMs = TIMEOUT_MS) {
35
+ this.run = run;
22
36
  this.timeoutMs = timeoutMs;
23
37
  if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1) {
24
38
  throw new Error('[Planu] macOS Keychain timeout must be a positive integer');
@@ -26,31 +40,78 @@ export class MacOSKeychainAdapter {
26
40
  }
27
41
  get(id) {
28
42
  return this.enqueue(id, 'get', false, async () => {
29
- const secret = await this.nativePort().get(id);
30
- if (secret === null) {
31
- return null;
32
- }
33
43
  try {
34
- return decoder.decode(secret);
44
+ const result = await this.run([
45
+ 'find-generic-password',
46
+ '-a',
47
+ id,
48
+ '-s',
49
+ SERVICE_LABEL,
50
+ '-w',
51
+ ]);
52
+ return Buffer.from(stripTrailingNewline(result.stdout), 'base64').toString('utf8');
35
53
  }
36
- finally {
37
- secret.fill(0);
54
+ catch (error) {
55
+ if (isMissingCredentialExit(error)) {
56
+ return null;
57
+ }
58
+ throw error;
38
59
  }
39
60
  });
40
61
  }
41
62
  set(id, value) {
42
- return this.enqueue(id, 'set', true, () => {
43
- const secret = Buffer.from(value, 'utf8');
63
+ return this.enqueue(id, 'set', true, async () => {
44
64
  try {
45
- return this.nativePort().set(id, secret);
65
+ await this.run(['delete-generic-password', '-a', id, '-s', SERVICE_LABEL]);
66
+ }
67
+ catch (error) {
68
+ if (!isMissingCredentialExit(error)) {
69
+ throw error;
70
+ }
71
+ reportClassifiedDegradation('MACOS_SECRET_DELETE', error);
46
72
  }
47
- finally {
48
- secret.fill(0);
73
+ const encoded = Buffer.from(value, 'utf8').toString('base64');
74
+ await this.run([
75
+ 'add-generic-password',
76
+ '-T',
77
+ '/usr/bin/security',
78
+ '-a',
79
+ id,
80
+ '-s',
81
+ SERVICE_LABEL,
82
+ '-w',
83
+ encoded,
84
+ ]);
85
+ try {
86
+ await this.run([
87
+ 'set-generic-password-partition-list',
88
+ '-S',
89
+ 'apple:,apple-tool:',
90
+ '-s',
91
+ SERVICE_LABEL,
92
+ '-a',
93
+ id,
94
+ '-k',
95
+ '',
96
+ ]);
97
+ }
98
+ catch (error) {
99
+ reportClassifiedDegradation('MACOS_SECRET_PARTITION', error);
49
100
  }
50
101
  });
51
102
  }
52
103
  delete(id) {
53
- return this.enqueue(id, 'delete', true, () => this.nativePort().delete(id));
104
+ return this.enqueue(id, 'delete', true, async () => {
105
+ try {
106
+ await this.run(['delete-generic-password', '-a', id, '-s', SERVICE_LABEL]);
107
+ }
108
+ catch (error) {
109
+ if (!isMissingCredentialExit(error)) {
110
+ throw error;
111
+ }
112
+ reportClassifiedDegradation('MACOS_SECRET_DELETE', error);
113
+ }
114
+ });
54
115
  }
55
116
  enqueue(id, operation, mutates, execute) {
56
117
  const predecessor = this.pending.get(id)?.settled ?? Promise.resolve();
@@ -20,7 +20,7 @@ export declare function getEmptyAutopilotResult(): AutopilotAnalysis;
20
20
  * Analyze the project to enrich a spec with real file paths and patterns.
21
21
  * Runs automatically during create_spec — no user interaction needed.
22
22
  */
23
- export declare function analyzeProjectForSpec(projectPath: string, description: string, title: string, _knowledge: ProjectKnowledge | null, signal?: AbortSignal): Promise<AutopilotAnalysis>;
23
+ export declare function analyzeProjectForSpec(projectPath: string, description: string, title: string, _knowledge: ProjectKnowledge | null): Promise<AutopilotAnalysis>;
24
24
  /**
25
25
  * SPEC-619 AC1: Detect broad-scope descriptions that mention 2+ major subsystems.
26
26
  * When true, create_spec should ask clarifying questions before proceeding.
@@ -17,7 +17,7 @@ export function getEmptyAutopilotResult() {
17
17
  * Analyze the project to enrich a spec with real file paths and patterns.
18
18
  * Runs automatically during create_spec — no user interaction needed.
19
19
  */
20
- export async function analyzeProjectForSpec(projectPath, description, title, _knowledge, signal) {
20
+ export async function analyzeProjectForSpec(projectPath, description, title, _knowledge) {
21
21
  const result = {
22
22
  suggestedFiles: { create: [], modify: [], test: [] },
23
23
  detectedPatterns: [],
@@ -44,7 +44,7 @@ export async function analyzeProjectForSpec(projectPath, description, title, _kn
44
44
  const keywords = extractKeywordsScorer(`${title} ${description}`);
45
45
  // Scan project files to find semantically related ones
46
46
  try {
47
- const relatedFiles = await findRelevantFiles(projectPath, keywords, 10, signal);
47
+ const relatedFiles = await findRelevantFiles(projectPath, keywords, 10);
48
48
  if (relatedFiles.length === 0) {
49
49
  result.noRelatedFilesMessage =
50
50
  'No related files detected — please populate ## Technical manually';
@@ -14,5 +14,5 @@ export declare function scoreFile(filePath: string, keywords: Set<string>): Prom
14
14
  * Scans `src/**\/\*.ts` and `tests/**\/\*.ts` under projectPath,
15
15
  * scores each, drops score=0 entries, returns top-`limit` by descending score.
16
16
  */
17
- export declare function findRelevantFiles(projectPath: string, keywords: Set<string>, limit?: number, signal?: AbortSignal): Promise<string[]>;
17
+ export declare function findRelevantFiles(projectPath: string, keywords: Set<string>, limit?: number): Promise<string[]>;
18
18
  //# sourceMappingURL=relevance-scorer.d.ts.map
@@ -4,9 +4,6 @@
4
4
  import { readFile } from 'node:fs/promises';
5
5
  import { glob } from 'glob';
6
6
  import { join } from 'node:path';
7
- import { isNativeActive } from '../../engine/core-bridge.js';
8
- import { runNativeWorkerOperation } from '../../engine/execution/native-worker-runtime.js';
9
- import { hashProjectPath } from '../../storage/base-store.js';
10
7
  /** Stop words to exclude from keyword extraction. */
11
8
  const STOP_WORDS = new Set([
12
9
  // English stop words
@@ -136,23 +133,10 @@ export async function scoreFile(filePath, keywords) {
136
133
  * Scans `src/**\/\*.ts` and `tests/**\/\*.ts` under projectPath,
137
134
  * scores each, drops score=0 entries, returns top-`limit` by descending score.
138
135
  */
139
- export async function findRelevantFiles(projectPath, keywords, limit = 10, signal) {
136
+ export async function findRelevantFiles(projectPath, keywords, limit = 10) {
140
137
  if (keywords.size === 0) {
141
138
  return [];
142
139
  }
143
- if (isNativeActive()) {
144
- const result = await runNativeWorkerOperation({
145
- projectId: hashProjectPath(projectPath),
146
- operation: 'find-relevant-files',
147
- payload: { rootPath: projectPath, keywords: [...keywords], limit },
148
- deadlineAt: Date.now() + 5_000,
149
- signal,
150
- });
151
- if (!Array.isArray(result) || !result.every((filePath) => typeof filePath === 'string')) {
152
- throw new Error('[Planu] Native relevance worker returned an invalid payload');
153
- }
154
- return result;
155
- }
156
140
  const patterns = [join(projectPath, 'src/**/*.ts'), join(projectPath, 'tests/**/*.ts')];
157
141
  const candidates = [];
158
142
  for (const pattern of patterns) {
@@ -1099,7 +1099,7 @@ async function prepareCreateSpecCandidate(initialParams, server) {
1099
1099
  if (constitutionCheck.blocked && constitutionCheck.errorResult) {
1100
1100
  return earlyPreparation(constitutionCheck.errorResult);
1101
1101
  }
1102
- const inlineAnalysis = await withBudget('create-spec-inline-analysis', getRuntimePolicy().createSpec.inlineAnalysisBudgetMs, (signal) => analyzeProjectForSpec(params.projectPath ?? '', params.description, spec.title, knowledge, signal));
1102
+ const inlineAnalysis = await withBudget('create-spec-inline-analysis', getRuntimePolicy().createSpec.inlineAnalysisBudgetMs, () => analyzeProjectForSpec(params.projectPath ?? '', params.description, spec.title, knowledge));
1103
1103
  const autopilot = unwrapBudget(inlineAnalysis, getEmptyAutopilotResult());
1104
1104
  if (autopilot.isIdea) {
1105
1105
  return earlyPreparation({
@@ -21,9 +21,7 @@ export interface UpgradeJournal {
21
21
  export interface ReleaseVerificationReport {
22
22
  version: string;
23
23
  cliPackage: string;
24
- nativePackage: string;
25
24
  cliVerified: true;
26
- nativeVerified: true;
27
25
  mcpSmokeVerified: true;
28
26
  canaryVerified: true;
29
27
  verifiedAt: string;
@@ -1,4 +1,3 @@
1
- import type { SpecAnnotation } from './living-spec/annotations.js';
2
1
  export type { SpecAnnotation } from './living-spec/annotations.js';
3
2
  export interface FileHash {
4
3
  path: string;
@@ -9,79 +8,6 @@ export interface FileMetadata {
9
8
  mtime: number;
10
9
  size: number;
11
10
  }
12
- /** Versioned contract returned by a native runtime before it may execute work. */
13
- export interface NativeRuntimeHandshake {
14
- engineVersion: string;
15
- buildId: string;
16
- protocolAbi: number;
17
- capabilityAbi: number;
18
- nodeApiAbi: number;
19
- capabilities: string[];
20
- storageSchemaMin: number;
21
- storageSchemaMax: number;
22
- target: string;
23
- }
24
- /** Externally generated release metadata stored next to the native artifact. */
25
- export interface NativeArtifactManifest extends NativeRuntimeHandshake {
26
- schemaVersion: 2;
27
- cliVersion: string;
28
- artifactSha256: string;
29
- platform: NodeJS.Platform;
30
- arch: string;
31
- libc: 'glibc' | 'musl' | null;
32
- sbom: {
33
- format: 'CycloneDX-1.5';
34
- path: string;
35
- sha256: string;
36
- };
37
- provenance: {
38
- builder: string;
39
- sourceCommit: string;
40
- sourceTreeDirty: boolean;
41
- sourceDateEpoch: number;
42
- rustToolchain: string;
43
- zigVersion: string | null;
44
- };
45
- signature: {
46
- algorithm: 'Ed25519';
47
- keyId: string;
48
- value: string;
49
- };
50
- }
51
- export interface NativeRuntimeCompatibility {
52
- compatible: boolean;
53
- reasons: string[];
54
- handshake: NativeRuntimeHandshake | null;
55
- }
56
- export type NativeFallbackClass = 'optimization' | 'correctness-critical';
57
- export type NativeFallbackMode = 'typescript-visible-degradation' | 'fail-closed';
58
- export interface NativeCapabilityPolicy {
59
- readonly capability: string;
60
- readonly classification: NativeFallbackClass;
61
- readonly fallback: NativeFallbackMode;
62
- readonly parityContract: string;
63
- }
64
- export interface NativeCapabilityDiagnostic {
65
- capability: string;
66
- state: 'available' | 'degraded' | 'unavailable';
67
- fallback: NativeFallbackMode;
68
- }
69
- export interface NativeLoadDiagnostic {
70
- attempted: string[];
71
- errors: string[];
72
- loaded?: string;
73
- artifactSha256?: string;
74
- origin?: 'local' | 'package';
75
- compatibility?: NativeRuntimeCompatibility;
76
- rejectedOverrides?: string[];
77
- capabilities?: NativeCapabilityDiagnostic[];
78
- executionScope?: 'isolated-worker-and-keychain-port';
79
- }
80
- export interface NativePlatformInfo {
81
- platform: NodeJS.Platform;
82
- arch: string;
83
- libc: 'glibc' | 'musl' | null;
84
- }
85
11
  export interface DriftResult {
86
12
  foundKeywords: string[];
87
13
  fileCount: number;
@@ -207,38 +133,4 @@ export interface ProjectGraphNeighborRs {
207
133
  edgeId: string;
208
134
  relation: string;
209
135
  }
210
- export interface PlanuCore {
211
- /** Mandatory for runtimes loaded by the versioned bridge. */
212
- planuRuntimeHandshake?(): NativeRuntimeHandshake;
213
- hashProjectPath(projectPath: string): string;
214
- isSafeProjectId(projectId: string): boolean;
215
- getProjectDataPath(baseDir: string, project_id: string): string | null;
216
- scanAndHashFiles(rootPath: string): FileHash[];
217
- scanProjectMetadata(rootPath: string): FileMetadata[];
218
- scanSpecAnnotations(rootPath: string): SpecAnnotation[];
219
- checkAcCoverage(filePaths: string[], keywords: string[]): string[];
220
- fastDetectDriftParallel(rootPath: string, keywords: string[]): DriftResult;
221
- fastFindDuplicateBlocks(paths: string[], minLines: number): DuplicateRawBlockRs[];
222
- fastFindPatterns(rootPath: string, patterns: string[], extensions: string[], exclude: string[]): FastGrepMatch[];
223
- fastFindFilesByName(rootPath: string, names: string[]): string[];
224
- fastFindFilesByExt(rootPath: string, extensions: string[]): string[];
225
- fastReadFiles(paths: string[]): FileContent[];
226
- fastScanSpecs(rootPath: string): SpecBriefRs[];
227
- fastVerifyGapsChain(filePath: string): GapsLogChainResultRs;
228
- fastAppendGapEntry(filePath: string, id: string, timestamp: string, specId: string, description: string, severity: string, affectedSpecs: string[]): string;
229
- fastCosineSimilarity(v1: number[], v2: number[]): number;
230
- fastHnswSearchFlat(query: number[], nodes: VectorNode[], topK: number): NativeVectorSearchResult[];
231
- fastHmacSign(secret: string, data: string): string;
232
- fastHmacVerify(secret: string, data: string, signature: string): boolean;
233
- macosKeychainSet?(account: string, secret: Buffer): Promise<void>;
234
- macosKeychainGet?(account: string): Promise<Buffer | null>;
235
- macosKeychainDelete?(account: string): Promise<void>;
236
- scanProjectGraphSources?(rootPath: string, limits: ResolvedProjectGraphLimitsRs): ProjectGraphSourceFileRs[];
237
- extractTsRelations?(rootPath: string, paths: string[], limits: ResolvedProjectGraphLimitsRs): TsRelationRs[];
238
- queryAffectedNodes?(seed: string, edges: GraphEdgeInputRs[], relationFilter: string[], limits: ResolvedProjectGraphLimitsRs): AffectedNodeRs[];
239
- queryAffectedNodesCompact?(seed: string, edges: CompactGraphEdgesRs, relationFilter: string[], limits: ResolvedProjectGraphLimitsRs): AffectedNodeRs[];
240
- queryShortestPath?(from: string, to: string, edges: GraphEdgeInputRs[], relationFilter: string[], limits: ResolvedProjectGraphLimitsRs): ShortestPathResultRs;
241
- selectCompactGraphSlice?(seeds: string[], nodes: GraphNodeInputRs[], edges: GraphEdgeInputRs[], limits: ResolvedProjectGraphLimitsRs): CompactGraphSliceRs;
242
- selectCompactGraphSliceCompact?(seeds: string[], nodeIds: string[], edges: CompactGraphEdgesRs, limits: ResolvedProjectGraphLimitsRs): CompactGraphSliceRs;
243
- }
244
136
  //# sourceMappingURL=core-bridge.d.ts.map
@@ -1,3 +1,3 @@
1
- // src/types/core-bridge.ts — Types for the native Rust engine
1
+ // src/types/core-bridge.ts — Types for the TypeScript fallback engine
2
2
  export {};
3
3
  //# sourceMappingURL=core-bridge.js.map
@@ -1,5 +1,3 @@
1
- import type { DurableJobRecord } from '../storage/runtime-db.js';
2
- import type { NativeWorkerCall, NativeWorkerOperation } from './native-worker.js';
3
1
  import type { ValidationArtifactDigests, ValidationFreshnessLease } from './validation-receipt.js';
4
2
  export interface DurableJobIdentity {
5
3
  readonly operationId: string;
@@ -15,13 +13,6 @@ export interface WatchJobInput extends DurableJobIdentity {
15
13
  export interface DurableJobRuntimeOptions {
16
14
  readonly databasePath?: string;
17
15
  }
18
- export interface NativeDurableJobPayload {
19
- readonly kind: 'native-worker';
20
- readonly operation: NativeWorkerOperation;
21
- readonly payload: Readonly<Record<string, unknown>>;
22
- readonly deadlineAt: number;
23
- readonly cancellationId?: string;
24
- }
25
16
  export interface ValidateDurableJobPayload {
26
17
  readonly kind: 'validate';
27
18
  readonly schemaVersion: 2;
@@ -44,35 +35,4 @@ export interface ValidateDurableJobPayload {
44
35
  readonly freshnessLease?: ValidationFreshnessLease;
45
36
  readonly specPath: string;
46
37
  }
47
- export type NativeWorkerRunner = (call: NativeWorkerCall) => Promise<unknown>;
48
- export interface DurableJobExecutorOptions {
49
- readonly runtime: {
50
- list(projectId: string, workspaceId?: string): readonly DurableJobRecord[];
51
- claim(input: DurableJobIdentity & {
52
- readonly workerId: string;
53
- readonly leaseMs: number;
54
- }): DurableJobRecord | undefined;
55
- renew(input: DurableJobIdentity & {
56
- readonly workerId: string;
57
- readonly leaseMs: number;
58
- readonly fencingToken: number;
59
- }): boolean;
60
- get(input: DurableJobIdentity): DurableJobRecord;
61
- complete(input: DurableJobIdentity & {
62
- readonly workerId: string;
63
- readonly fencingToken: number;
64
- readonly result: unknown;
65
- }): DurableJobRecord;
66
- fail(input: DurableJobIdentity & {
67
- readonly workerId: string;
68
- readonly fencingToken: number;
69
- readonly error: string;
70
- }): DurableJobRecord;
71
- };
72
- readonly workerId: string;
73
- readonly leaseMs?: number;
74
- readonly heartbeatMs?: number;
75
- readonly maxConcurrency?: number;
76
- readonly runNative?: NativeWorkerRunner;
77
- }
78
38
  //# sourceMappingURL=durable-job.d.ts.map
@@ -97,11 +97,6 @@ export interface SecurityPatternsConfig {
97
97
  complianceCriteria: Record<string, string[]>;
98
98
  }
99
99
  export type SecretStoreKind = 'macos-keychain' | 'linux-secret-service' | 'windows-credential-manager' | 'environment';
100
- export interface MacOSKeychainNativePort {
101
- set(account: string, secret: Buffer): Promise<void>;
102
- get(account: string): Promise<Buffer | null>;
103
- delete(account: string): Promise<void>;
104
- }
105
100
  export type MacOSKeychainOperation = 'get' | 'set' | 'delete';
106
101
  export interface MacOSKeychainPendingOperation {
107
102
  readonly fence: number;