@planu/cli 5.3.5 → 5.3.7

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 (57) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/dist/config/runtime-policy.json +1 -0
  3. package/dist/engine/convention-scanner/codebase-scanner.js +1 -1
  4. package/dist/engine/hooks/handlers/on-impl-change.d.ts +17 -4
  5. package/dist/engine/hooks/handlers/on-impl-change.js +43 -44
  6. package/dist/engine/living-spec-analyzer.d.ts +5 -2
  7. package/dist/engine/living-spec-analyzer.js +5 -2
  8. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
  9. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +4 -4
  10. package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
  11. package/dist/engine/planu-core.darwin-x64.node.sbom.json +4 -4
  12. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
  13. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +4 -4
  14. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
  15. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +4 -4
  16. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
  17. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +4 -4
  18. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
  19. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +4 -4
  20. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
  21. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +4 -4
  22. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
  23. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +4 -4
  24. package/dist/engine/runtime-policy.js +7 -0
  25. package/dist/engine/scope-boundaries/contradiction-checker.js +28 -20
  26. package/dist/engine/spec-format/acceptance-criteria.js +5 -2
  27. package/dist/engine/spec-migrator/filesystem-import.js +113 -73
  28. package/dist/engine/spec-migrator/frontmatter-parser.js +15 -13
  29. package/dist/tools/auto-reconcile.js +1 -1
  30. package/dist/tools/challenge-spec/challenge-report.js +1 -1
  31. package/dist/tools/init-project/portable-index-reconciler.js +2 -1
  32. package/dist/tools/reconcile-spec.js +3 -1
  33. package/dist/tools/safe-handler.js +0 -2
  34. package/dist/tools/start-hooks/engine.d.ts +2 -3
  35. package/dist/tools/start-hooks/engine.js +50 -33
  36. package/dist/tools/start-hooks.d.ts +1 -1
  37. package/dist/tools/start-hooks.js +1 -2
  38. package/dist/tools/tool-registry/group-infra.js +36 -0
  39. package/dist/tools/update-status/transition-guard.js +17 -4
  40. package/dist/tools/validate-assurance.js +1 -1
  41. package/dist/tools/validate-lint.js +1 -1
  42. package/dist/tools/validate.d.ts +1 -0
  43. package/dist/tools/validate.js +21 -2
  44. package/dist/types/file-hooks.d.ts +4 -6
  45. package/dist/types/index.d.ts +0 -1
  46. package/dist/types/index.js +0 -1
  47. package/dist/types/mcp.d.ts +0 -19
  48. package/dist/types/runtime-policy.d.ts +1 -0
  49. package/dist/types/spec/core.d.ts +5 -0
  50. package/dist/types/spec/inputs.d.ts +16 -0
  51. package/package.json +9 -9
  52. package/planu-native.json +1 -1
  53. package/planu-plugin.json +1 -1
  54. package/dist/engine/hooks/agent-hook-migrator.d.ts +0 -9
  55. package/dist/engine/hooks/agent-hook-migrator.js +0 -140
  56. package/dist/types/hook-status-update.d.ts +0 -10
  57. package/dist/types/hook-status-update.js +0 -3
@@ -1,140 +0,0 @@
1
- // engine/hooks/agent-hook-migrator.ts — Auto-migrate deprecated Claude Code agent-type hooks.
2
- // Claude Code 2.1.113+ broke type:"agent" hooks with "Messages are required for agent hooks."
3
- // This migrator detects them in .claude/settings.json and converts to type:"command" equivalents.
4
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
5
- import { join } from 'node:path';
6
- import { homedir } from 'node:os';
7
- // ---------------------------------------------------------------------------
8
- // Constants
9
- // ---------------------------------------------------------------------------
10
- /** Projects already migrated in this session — skip re-processing. */
11
- const migratedPaths = new Set();
12
- // ---------------------------------------------------------------------------
13
- // Core migration
14
- // ---------------------------------------------------------------------------
15
- /**
16
- * Converts a single agent-type hook entry to an equivalent command-type hook.
17
- * Writes a shell script to hooksDir and returns the replacement entry.
18
- */
19
- function migrateAgentHook(hook, hooksDir, index) {
20
- const prompt = hook.prompt ?? '';
21
- const model = hook.model ?? 'claude-haiku-4-5-20251001';
22
- const scriptName = `planu-migrated-agent-hook-${index}.sh`;
23
- const scriptPath = join(hooksDir, scriptName);
24
- // Escape the prompt for heredoc embedding (backslash, backtick, dollar must be escaped)
25
- const escapedPrompt = prompt.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
26
- // Build script as array to avoid TypeScript misinterpreting bash ${...} expansions
27
- const scriptLines = [
28
- '#!/usr/bin/env bash',
29
- '# Auto-generated by Planu: migrated from deprecated Claude Code agent hook.',
30
- '# Original type: agent — converted to type: command for Claude Code 2.1.113+ compatibility.',
31
- 'set -euo pipefail',
32
- '',
33
- 'HOOK_INPUT=$(cat)',
34
- "PROMPT=$(cat <<'PLANU_HOOK_PROMPT'",
35
- escapedPrompt,
36
- 'PLANU_HOOK_PROMPT',
37
- ')',
38
- '',
39
- '# Substitute $ARGUMENTS placeholder with actual hook input',
40
- 'FULL_PROMPT="${PROMPT/\\$ARGUMENTS/$HOOK_INPUT}"',
41
- '',
42
- `claude --print --dangerously-skip-permissions --model "${model}" -p "$FULL_PROMPT" 2>/dev/null || true`,
43
- ];
44
- const script = scriptLines.join('\n') + '\n';
45
- try {
46
- mkdirSync(hooksDir, { recursive: true });
47
- writeFileSync(scriptPath, script, { mode: 0o755 });
48
- }
49
- catch {
50
- // If we can't write the script, fall back to no-op command
51
- return {
52
- type: 'command',
53
- command: 'true',
54
- statusMessage: hook.statusMessage,
55
- };
56
- }
57
- return {
58
- type: 'command',
59
- command: `bash "${scriptPath}"`,
60
- statusMessage: hook.statusMessage,
61
- ...(hook.timeout !== undefined ? { timeout: hook.timeout } : {}),
62
- };
63
- }
64
- /**
65
- * Scan a single settings file, migrate any agent-type hooks, and write back.
66
- * Returns the number of hooks migrated.
67
- */
68
- function migrateSettingsFile(settingsPath, hooksDir) {
69
- if (!existsSync(settingsPath)) {
70
- return 0;
71
- }
72
- let settings;
73
- try {
74
- settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
75
- }
76
- catch {
77
- return 0;
78
- }
79
- if (!settings.hooks || typeof settings.hooks !== 'object') {
80
- return 0;
81
- }
82
- let migratedCount = 0;
83
- let hookIndex = Date.now(); // unique index per session
84
- for (const [event, matchers] of Object.entries(settings.hooks)) {
85
- if (!Array.isArray(matchers)) {
86
- continue;
87
- }
88
- for (const matcher of matchers) {
89
- if (!Array.isArray(matcher.hooks)) {
90
- continue;
91
- }
92
- for (let i = 0; i < matcher.hooks.length; i++) {
93
- const hook = matcher.hooks[i];
94
- if (hook?.type === 'agent' && typeof hook.prompt === 'string') {
95
- matcher.hooks[i] = migrateAgentHook(hook, hooksDir, hookIndex++);
96
- migratedCount++;
97
- console.error(`[Planu] Migrated agent hook in ${settingsPath} (event: ${event}, matcher: ${matcher.matcher})`);
98
- }
99
- }
100
- }
101
- }
102
- if (migratedCount > 0) {
103
- try {
104
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
105
- }
106
- catch {
107
- // Best-effort — never throw from a migration
108
- }
109
- }
110
- return migratedCount;
111
- }
112
- // ---------------------------------------------------------------------------
113
- // Public API
114
- // ---------------------------------------------------------------------------
115
- /**
116
- * Scan .claude/settings.json (project-level) and ~/.claude/settings.json (global)
117
- * for deprecated type:"agent" hooks and migrate them to type:"command" equivalents.
118
- *
119
- * Fire-and-forget safe: never throws, logs to stderr only.
120
- * Idempotent: each projectPath is only migrated once per process lifetime.
121
- */
122
- export function migrateAgentHooksIfNeeded(projectPath) {
123
- if (migratedPaths.has(projectPath)) {
124
- return;
125
- }
126
- migratedPaths.add(projectPath);
127
- try {
128
- const projectSettingsPath = join(projectPath, '.claude', 'settings.json');
129
- const projectHooksDir = join(projectPath, '.claude', 'hooks');
130
- migrateSettingsFile(projectSettingsPath, projectHooksDir);
131
- // Also check global settings (affects all Claude Code sessions)
132
- const globalSettingsPath = join(homedir(), '.claude', 'settings.json');
133
- const globalHooksDir = join(homedir(), '.claude', 'hooks');
134
- migrateSettingsFile(globalSettingsPath, globalHooksDir);
135
- }
136
- catch {
137
- // Never block tool execution due to migration errors
138
- }
139
- }
140
- //# sourceMappingURL=agent-hook-migrator.js.map
@@ -1,10 +0,0 @@
1
- import type { ToolResult } from './common/primitives.js';
2
- import type { UpdateStatusInput } from './spec/inputs.js';
3
- export interface HookUpdateStatusInput extends UpdateStatusInput {
4
- trigger: 'fs-hook';
5
- actor: 'system';
6
- }
7
- export interface UpdateStatusModule {
8
- handleUpdateStatus: (input: HookUpdateStatusInput) => Promise<ToolResult>;
9
- }
10
- //# sourceMappingURL=hook-status-update.d.ts.map
@@ -1,3 +0,0 @@
1
- // types/hook-status-update.ts — Runtime bridge types for hook-triggered status transitions
2
- export {};
3
- //# sourceMappingURL=hook-status-update.js.map