@planu/cli 3.9.14 → 4.1.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.
- package/CHANGELOG.md +17 -1
- package/dist/cli/commands/spec.js +20 -1
- package/dist/cli/commands/status.js +18 -1
- package/dist/config/license-plans.json +1 -0
- package/dist/engine/ai-integration/agents-md/generator.js +4 -1
- package/dist/engine/ai-integration/cline/clinerules-generator.js +7 -2
- package/dist/engine/ai-integration/codex/agents-md-generator.js +2 -0
- package/dist/engine/ai-integration/codex/hooks-generator.js +1 -0
- package/dist/engine/ai-integration/cursor/cursorrules-generator.js +7 -2
- package/dist/engine/ai-integration/gemini/settings-generator.js +4 -1
- package/dist/engine/ai-integration/kiro/hooks-generator.js +2 -1
- package/dist/engine/ai-integration/windsurf/windsurfrules-generator.js +7 -2
- package/dist/engine/autopilot/action-registry.js +5 -14
- package/dist/engine/autopilot/state-updater.js +13 -10
- package/dist/engine/cascade-hooks/hooks/git-auto-stage.hook.js +3 -0
- package/dist/engine/cascade-hooks/hooks/html-regen.hook.js +1 -1
- package/dist/engine/cascade-hooks/hooks/status-json.hook.js +1 -1
- package/dist/engine/cascade-hooks/state-drift-detector.d.ts +1 -1
- package/dist/engine/cascade-hooks/state-drift-detector.js +15 -12
- package/dist/engine/git/planu-autocommit.d.ts +1 -0
- package/dist/engine/git/planu-autocommit.js +6 -0
- package/dist/engine/git-hook-injector.js +3 -3
- package/dist/engine/handoff-artifacts/io.js +3 -2
- package/dist/engine/handoff-packager.js +2 -1
- package/dist/engine/hooks/full-spectrum-generator.d.ts +2 -1
- package/dist/engine/hooks/full-spectrum-generator.js +5 -3
- package/dist/engine/marketplace-fetcher/anthropic-source.js +2 -0
- package/dist/engine/opencode/config-scaffold.js +4 -0
- package/dist/engine/release/postmortem-generator.d.ts +1 -1
- package/dist/engine/release/postmortem-generator.js +3 -2
- package/dist/engine/rules-generator/index.js +2 -0
- package/dist/engine/rules-reconciler.js +2 -0
- package/dist/engine/safety/cross-process-lock.js +2 -2
- package/dist/engine/session/checkpoint-writer.js +0 -1
- package/dist/engine/session-context-generator.js +4 -1
- package/dist/engine/skill-bootstrap/skill-writer.js +2 -0
- package/dist/engine/skill-generation/multi-agent-writer.js +2 -0
- package/dist/engine/spec-audit/index.js +2 -2
- package/dist/engine/spec-audit/report-writer.d.ts +1 -1
- package/dist/engine/spec-audit/report-writer.js +5 -4
- package/dist/engine/spec-language/english-only.d.ts +8 -7
- package/dist/engine/spec-language/english-only.js +27 -3
- package/dist/engine/spec-migrator/index.d.ts +1 -0
- package/dist/engine/spec-migrator/index.js +1 -0
- package/dist/engine/spec-migrator/planu-canonical-policy.d.ts +9 -0
- package/dist/engine/spec-migrator/planu-canonical-policy.js +62 -0
- package/dist/engine/spec-migrator/planu-root-cleaner.js +18 -94
- package/dist/engine/spec-migrator/strict-planu-cleanup.d.ts +6 -0
- package/dist/engine/spec-migrator/strict-planu-cleanup.js +199 -0
- package/dist/engine/spec-summary-html.d.ts +5 -5
- package/dist/engine/spec-summary-html.js +7 -32
- package/dist/engine/universal-rules/host-writer.js +8 -2
- package/dist/engine/universal-rules/rules/planu-english-specs.js +9 -5
- package/dist/hosts/claude-code/ux/skills-writer.js +2 -0
- package/dist/hosts/codex/config-scaffold.js +5 -0
- package/dist/hosts/gemini/config-scaffold.js +4 -0
- package/dist/storage/gaps-log.js +4 -4
- package/dist/storage/transition-log.js +3 -2
- package/dist/tools/audit-specs-drift.js +3 -3
- package/dist/tools/create-skill.js +21 -0
- package/dist/tools/create-spec/post-creation.d.ts +2 -1
- package/dist/tools/create-spec/post-creation.js +9 -11
- package/dist/tools/create-spec/spec-builder.js +1 -1
- package/dist/tools/create-spec.js +42 -18
- package/dist/tools/flag-spec-gap.d.ts +1 -1
- package/dist/tools/flag-spec-gap.js +1 -1
- package/dist/tools/generate-dashboard.js +3 -3
- package/dist/tools/housekeeping-sweep.js +16 -0
- package/dist/tools/init-project/agents-md-writer.js +2 -0
- package/dist/tools/init-project/conventions-writer.js +2 -0
- package/dist/tools/init-project/find-skills-writer.js +2 -0
- package/dist/tools/init-project/git-setup.js +11 -2
- package/dist/tools/init-project/handler.js +1 -27
- package/dist/tools/init-project/helpers.js +5 -0
- package/dist/tools/init-project/migration-runner.js +8 -0
- package/dist/tools/init-project/per-client-files-writer.js +2 -0
- package/dist/tools/init-project/planu-workflow-generator.js +2 -0
- package/dist/tools/init-project/rules-generator.js +7 -1
- package/dist/tools/init-project/rules-writer.js +3 -0
- package/dist/tools/init-project/skills-multi-teammate-review-writer.js +2 -0
- package/dist/tools/init-project/skills-writer.js +2 -0
- package/dist/tools/license-gate.d.ts +1 -0
- package/dist/tools/license-gate.js +5 -1
- package/dist/tools/list-specs.js +13 -0
- package/dist/tools/register-sdd-tools.d.ts +1 -1
- package/dist/tools/register-sdd-tools.js +1 -0
- package/dist/tools/register-spec-tools/core-spec-tools.js +16 -0
- package/dist/tools/spec-lock-handler.js +1 -1
- package/dist/tools/tool-registry/group-misc.js +4 -4
- package/dist/tools/update-status/batch.d.ts +3 -0
- package/dist/tools/update-status/batch.js +96 -0
- package/dist/tools/update-status/dod-gates.js +1 -1
- package/dist/tools/update-status/file-sync.js +3 -1
- package/dist/tools/update-status/index.js +15 -2
- package/dist/tools/update-status-actions.js +2 -6
- package/dist/tools/validate.js +27 -0
- package/dist/tools/workspace-dashboard-handler.js +6 -9
- package/dist/types/git.d.ts +1 -1
- package/dist/types/spec-format.d.ts +26 -0
- package/dist/types/spec-language.d.ts +8 -0
- package/dist/types/spec-language.js +2 -0
- package/package.json +20 -20
|
@@ -1182,11 +1182,11 @@ export function registerMiscGroupTools(s) {
|
|
|
1182
1182
|
registerRepairFrontmatterDriftTool(s);
|
|
1183
1183
|
// ── Generate dashboard ─────────────────────────────────────────────────────
|
|
1184
1184
|
s.registerTool('generate_spec_dashboard', {
|
|
1185
|
-
description: '
|
|
1185
|
+
description: 'Deprecated compatibility tool. Planu no longer writes generated dashboard HTML into planu/.',
|
|
1186
1186
|
inputSchema: {
|
|
1187
1187
|
projectPath: z.string().describe('Absolute path to the project root directory'),
|
|
1188
1188
|
},
|
|
1189
|
-
annotations: { readOnlyHint:
|
|
1189
|
+
annotations: { readOnlyHint: true },
|
|
1190
1190
|
}, async (args) => {
|
|
1191
1191
|
const projectId = hashProjectPath(args.projectPath);
|
|
1192
1192
|
const specs = await specStore.listSpecs(projectId);
|
|
@@ -1196,7 +1196,7 @@ export function registerMiscGroupTools(s) {
|
|
|
1196
1196
|
content: [
|
|
1197
1197
|
{
|
|
1198
1198
|
type: 'text',
|
|
1199
|
-
text: `Dashboard
|
|
1199
|
+
text: `Dashboard generation is deprecated; no project files were written. Current specs: ${String(specs.length)} (${String(doneCount)} done).`,
|
|
1200
1200
|
},
|
|
1201
1201
|
],
|
|
1202
1202
|
};
|
|
@@ -1331,7 +1331,7 @@ export function registerMiscGroupTools(s) {
|
|
|
1331
1331
|
// ── SPEC-739: flag_spec_gap ─────────────────────────────────────────────────
|
|
1332
1332
|
s.registerTool('flag_spec_gap', {
|
|
1333
1333
|
description: 'Record a spec implementation gap discovered mid-implementation. ' +
|
|
1334
|
-
'Persists a hash-chained entry to
|
|
1334
|
+
'Persists a hash-chained entry to external Planu project data with severity ' +
|
|
1335
1335
|
"classification ('low' | 'medium' | 'high') and affected spec links. " +
|
|
1336
1336
|
'Existing callers without severity or affectedSpecs continue to work (defaults applied).',
|
|
1337
1337
|
inputSchema: {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// tools/update-status/batch.ts — SPEC-1017 batch status transitions
|
|
2
|
+
import { handleUpdateStatus } from './index.js';
|
|
3
|
+
import { resolveProjectIdOrAutoDetect } from '../resolve-project-id.js';
|
|
4
|
+
function firstText(result) {
|
|
5
|
+
const first = result.content[0];
|
|
6
|
+
return first?.type === 'text' ? first.text : JSON.stringify(result.structuredContent ?? {});
|
|
7
|
+
}
|
|
8
|
+
export async function handleUpdateStatusBatch(input) {
|
|
9
|
+
const uniqueSpecIds = [...new Set(input.specIds)].sort();
|
|
10
|
+
if (uniqueSpecIds.length === 0) {
|
|
11
|
+
return { content: [{ type: 'text', text: 'update_status_batch requires at least one specId.' }], isError: true };
|
|
12
|
+
}
|
|
13
|
+
const resolved = await resolveProjectIdOrAutoDetect({
|
|
14
|
+
projectId: input.projectId,
|
|
15
|
+
projectPath: input.projectPath,
|
|
16
|
+
});
|
|
17
|
+
if (!resolved.ok) {
|
|
18
|
+
return resolved.errorResult;
|
|
19
|
+
}
|
|
20
|
+
if (input.dryRun) {
|
|
21
|
+
return {
|
|
22
|
+
content: [
|
|
23
|
+
{
|
|
24
|
+
type: 'text',
|
|
25
|
+
text: `Batch status dry run: ${uniqueSpecIds.length} spec(s) would transition to ${input.status}.\n` +
|
|
26
|
+
uniqueSpecIds.map((id) => `- ${id}`).join('\n'),
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
structuredContent: {
|
|
30
|
+
dryRun: true,
|
|
31
|
+
status: input.status,
|
|
32
|
+
specIds: uniqueSpecIds,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const updated = [];
|
|
37
|
+
const skipped = [];
|
|
38
|
+
const failed = [];
|
|
39
|
+
const previousSuppress = process.env.PLANU_SUPPRESS_AUTOCOMMIT;
|
|
40
|
+
process.env.PLANU_SUPPRESS_AUTOCOMMIT = 'true';
|
|
41
|
+
try {
|
|
42
|
+
for (const specId of uniqueSpecIds) {
|
|
43
|
+
const result = await handleUpdateStatus({
|
|
44
|
+
specId,
|
|
45
|
+
status: input.status,
|
|
46
|
+
projectId: resolved.projectId,
|
|
47
|
+
projectPath: resolved.projectPath,
|
|
48
|
+
reviewNotes: input.reviewNotes,
|
|
49
|
+
});
|
|
50
|
+
const message = firstText(result);
|
|
51
|
+
if (result.isError === true) {
|
|
52
|
+
if (/already|idempotent|same status/i.test(message)) {
|
|
53
|
+
skipped.push({ specId, message });
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
failed.push({ specId, message });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
updated.push({ specId, message });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
if (previousSuppress === undefined) {
|
|
66
|
+
delete process.env.PLANU_SUPPRESS_AUTOCOMMIT;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
process.env.PLANU_SUPPRESS_AUTOCOMMIT = previousSuppress;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const { runStrictPlanuCleanup } = await import('../../engine/spec-migrator/index.js');
|
|
74
|
+
await runStrictPlanuCleanup(resolved.projectPath);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
/* best-effort final pass */
|
|
78
|
+
}
|
|
79
|
+
const text = [
|
|
80
|
+
`Batch status transition complete: ${input.status}`,
|
|
81
|
+
`Updated: ${updated.length}`,
|
|
82
|
+
`Skipped: ${skipped.length}`,
|
|
83
|
+
`Failed: ${failed.length}`,
|
|
84
|
+
].join('\n');
|
|
85
|
+
return {
|
|
86
|
+
content: [{ type: 'text', text }],
|
|
87
|
+
isError: failed.length > 0,
|
|
88
|
+
structuredContent: {
|
|
89
|
+
updated,
|
|
90
|
+
skipped,
|
|
91
|
+
failed,
|
|
92
|
+
sideEffectsFlushed: ['strict-planu-cleanup'],
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -264,7 +264,7 @@ export async function checkValidationReportGate(specId, projectId, force) {
|
|
|
264
264
|
return null;
|
|
265
265
|
}
|
|
266
266
|
if (!result.payload.passed) {
|
|
267
|
-
const artifactPath = `
|
|
267
|
+
const artifactPath = `external Planu project data: handoffs/${specId}/validation-report.json`;
|
|
268
268
|
return {
|
|
269
269
|
content: [
|
|
270
270
|
{
|
|
@@ -86,7 +86,9 @@ export async function syncSpecFiles(updatedSpec, currentStatus, newStatus, proje
|
|
|
86
86
|
// Commit message must reflect the actual transition — 'mark-done' is only
|
|
87
87
|
// correct when newStatus === 'done'; any other transition uses 'status-update'
|
|
88
88
|
// to avoid misleading "mark as done" messages on approved/implementing/etc.
|
|
89
|
-
if (projectPath
|
|
89
|
+
if (projectPath &&
|
|
90
|
+
process.env.PLANU_ENABLE_AUTOCOMMIT === 'true' &&
|
|
91
|
+
process.env.PLANU_SUPPRESS_AUTOCOMMIT !== 'true') {
|
|
90
92
|
try {
|
|
91
93
|
const { git: gitCmd } = await import('../git/git-helpers.js');
|
|
92
94
|
await gitCmd(projectPath, ['add', '--', updatedSpec.specPath]);
|
|
@@ -240,6 +240,16 @@ export async function handleUpdateStatus(params, server) {
|
|
|
240
240
|
return resolved.errorResult;
|
|
241
241
|
}
|
|
242
242
|
const projectId = resolved.projectId;
|
|
243
|
+
const effectiveProjectPath = resolved.projectPath;
|
|
244
|
+
if (effectiveProjectPath) {
|
|
245
|
+
try {
|
|
246
|
+
const { runStrictPlanuCleanup } = await import('../../engine/spec-migrator/index.js');
|
|
247
|
+
await runStrictPlanuCleanup(effectiveProjectPath);
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
/* strict cleanup is best-effort here; validate fails closed if artifacts remain */
|
|
251
|
+
}
|
|
252
|
+
}
|
|
243
253
|
try {
|
|
244
254
|
// Get the current spec
|
|
245
255
|
const spec = await specStore.getSpec(projectId, specId);
|
|
@@ -271,7 +281,7 @@ export async function handleUpdateStatus(params, server) {
|
|
|
271
281
|
content: [
|
|
272
282
|
{
|
|
273
283
|
type: 'text',
|
|
274
|
-
text: `Spec ${specId} is locked by another process (cross-process lock). Retry later or inspect
|
|
284
|
+
text: `Spec ${specId} is locked by another process (cross-process lock). Retry later or inspect data/.locks/planu/${specId}.lock`,
|
|
275
285
|
},
|
|
276
286
|
],
|
|
277
287
|
isError: true,
|
|
@@ -864,7 +874,10 @@ export async function handleUpdateStatus(params, server) {
|
|
|
864
874
|
}
|
|
865
875
|
// SPEC-544: Final git add after all writes complete (covers auto-advance multi-step transitions)
|
|
866
876
|
// SPEC-575: Auto-commit staged planu/ docs (idempotent, safe-fail)
|
|
867
|
-
if (effectiveGatePath &&
|
|
877
|
+
if (effectiveGatePath &&
|
|
878
|
+
updatedSpec.specPath &&
|
|
879
|
+
process.env.PLANU_ENABLE_AUTOCOMMIT === 'true' &&
|
|
880
|
+
process.env.PLANU_SUPPRESS_AUTOCOMMIT !== 'true') {
|
|
868
881
|
try {
|
|
869
882
|
const { git: gitCmd } = await import('../git/git-helpers.js');
|
|
870
883
|
await gitCmd(effectiveGatePath, ['add', 'planu/']);
|
|
@@ -162,22 +162,18 @@ export async function runDoneActions(projectId, specId, gitBranch) {
|
|
|
162
162
|
}
|
|
163
163
|
return null;
|
|
164
164
|
})(),
|
|
165
|
-
//
|
|
166
|
-
// SPEC-575: Auto-commit staged planu/ docs (idempotent, safe-fail)
|
|
165
|
+
// Warn if non-planu changes remain. Planu autocommit/staging is opt-in only.
|
|
167
166
|
(async () => {
|
|
168
167
|
try {
|
|
169
168
|
const { resolveProjectPath, git: gitCmd } = await import('./git/git-helpers.js');
|
|
170
169
|
const projectPath = await resolveProjectPath(projectId);
|
|
171
|
-
|
|
170
|
+
if (process.env.PLANU_ENABLE_AUTOCOMMIT === 'true') {
|
|
172
171
|
await gitCmd(projectPath, ['add', 'planu/']);
|
|
173
172
|
const { planuAutoCommit } = await import('../engine/git/planu-autocommit.js');
|
|
174
173
|
void planuAutoCommit({ projectPath, specId, reason: 'mark-done' }).catch((err) => {
|
|
175
174
|
console.error('[update-status] planuAutoCommit failed:', err instanceof Error ? err.message : String(err));
|
|
176
175
|
});
|
|
177
176
|
}
|
|
178
|
-
catch {
|
|
179
|
-
// git add failed (nothing to stage, or not a git repo) — continue to status check
|
|
180
|
-
}
|
|
181
177
|
const { stdout } = await gitCmd(projectPath, ['status', '--porcelain']);
|
|
182
178
|
const nonPlanuLines = stdout
|
|
183
179
|
.trim()
|
package/dist/tools/validate.js
CHANGED
|
@@ -68,6 +68,33 @@ export async function handleValidate(args, server) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
const projectPath = knowledge.projectPath;
|
|
71
|
+
// SPEC-1017: fail closed when planu/ contains non-canonical artifacts.
|
|
72
|
+
try {
|
|
73
|
+
const { runStrictPlanuCleanup, validateStrictPlanuLayout } = await import('../engine/spec-migrator/index.js');
|
|
74
|
+
await runStrictPlanuCleanup(projectPath);
|
|
75
|
+
const layout = await validateStrictPlanuLayout(projectPath);
|
|
76
|
+
if (!layout.ok) {
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: 'text',
|
|
81
|
+
text: `Strict Planu layout validation failed for ${specId}.\n\n` +
|
|
82
|
+
`Non-canonical paths:\n${layout.offenders.map((p) => `- ${p}`).join('\n')}\n\n` +
|
|
83
|
+
`Canonical contract:\n${layout.contract}`,
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
isError: true,
|
|
87
|
+
structuredContent: {
|
|
88
|
+
error: 'strict_planu_layout_violation',
|
|
89
|
+
offenders: layout.offenders,
|
|
90
|
+
contract: layout.contract,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* best-effort — implementation validation still runs if layout check is unavailable */
|
|
97
|
+
}
|
|
71
98
|
// 3. Run validation engine
|
|
72
99
|
const result = await validateSpec(spec, projectPath);
|
|
73
100
|
// 4. Generate DoR and DoD checklists
|
|
@@ -10,6 +10,7 @@ import { readRecentAutopilotAlerts } from '../storage/autopilot-log-store.js';
|
|
|
10
10
|
import { verifyStateFiles } from '../engine/cascade-hooks/state-drift-detector.js';
|
|
11
11
|
import { readFile } from 'node:fs/promises';
|
|
12
12
|
import { join } from 'node:path';
|
|
13
|
+
import { getAsyncAnalysisPath } from './create-spec/post-creation.js';
|
|
13
14
|
export async function handleWorkspaceOverview(args) {
|
|
14
15
|
const result = await buildWorkspaceOverview(args.healthThreshold);
|
|
15
16
|
if (result.projectCount === 0) {
|
|
@@ -126,10 +127,10 @@ export async function handleWorkspaceSearch(args) {
|
|
|
126
127
|
}
|
|
127
128
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
128
129
|
}
|
|
129
|
-
/** SPEC-781: Check if a spec has
|
|
130
|
-
async function hasPendingAnalysis(projectPath,
|
|
130
|
+
/** SPEC-781: Check if a spec has pending async analysis in external project data. */
|
|
131
|
+
async function hasPendingAnalysis(projectPath, specId) {
|
|
131
132
|
try {
|
|
132
|
-
await readFile(
|
|
133
|
+
await readFile(getAsyncAnalysisPath(projectPath, specId), 'utf-8');
|
|
133
134
|
return false;
|
|
134
135
|
}
|
|
135
136
|
catch {
|
|
@@ -144,7 +145,6 @@ async function collectPendingAnalysisAlerts(projectPath) {
|
|
|
144
145
|
const results = [];
|
|
145
146
|
const PENDING_RE = /^pendingAnalysis:\s*true/m;
|
|
146
147
|
const ID_RE = /^id:\s*(SPEC-\d+)/m;
|
|
147
|
-
const SPEC_DIR_RE = /planu\/specs\/([^/]+)\/spec\.md$/;
|
|
148
148
|
for (const specFile of specFiles) {
|
|
149
149
|
const content = await readFile(specFile, 'utf-8').catch(() => '');
|
|
150
150
|
if (!PENDING_RE.test(content)) {
|
|
@@ -155,11 +155,8 @@ async function collectPendingAnalysisAlerts(projectPath) {
|
|
|
155
155
|
if (specId === undefined) {
|
|
156
156
|
continue;
|
|
157
157
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const specDir = dirName !== undefined ? join('planu/specs', dirName) : null;
|
|
161
|
-
if (specDir !== null && !(await hasPendingAnalysis(projectPath, specDir))) {
|
|
162
|
-
continue; // .analysis.json exists — analysis done
|
|
158
|
+
if (!(await hasPendingAnalysis(projectPath, specId))) {
|
|
159
|
+
continue;
|
|
163
160
|
}
|
|
164
161
|
results.push({ specId, message: `Spec ${specId} analysis still running` });
|
|
165
162
|
}
|
package/dist/types/git.d.ts
CHANGED
|
@@ -310,7 +310,7 @@ export interface ListSpecPrsInput {
|
|
|
310
310
|
projectPath: string;
|
|
311
311
|
specId?: string;
|
|
312
312
|
}
|
|
313
|
-
export type PlanuAutocommitSkipReason = 'no-staged-changes' | 'mid-merge' | 'detached-head';
|
|
313
|
+
export type PlanuAutocommitSkipReason = 'disabled' | 'no-staged-changes' | 'mid-merge' | 'detached-head';
|
|
314
314
|
export type PlanuAutocommitReason = 'mark-done' | 'sync-release' | 'status-update' | 'session-checkpoint';
|
|
315
315
|
export interface PlanuAutocommitResult {
|
|
316
316
|
committed: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Spec } from './spec/core.js';
|
|
2
2
|
import type { Estimation } from './estimation.js';
|
|
3
|
+
import type { SpecStatus } from './common/index.js';
|
|
3
4
|
/** A criterion in the lean spec frontmatter. */
|
|
4
5
|
export interface LeanCriterion {
|
|
5
6
|
text: string;
|
|
@@ -42,6 +43,31 @@ export interface CleanupResult {
|
|
|
42
43
|
deletedSpecFiles: string[];
|
|
43
44
|
totalDeleted: number;
|
|
44
45
|
}
|
|
46
|
+
export interface PlanuCanonicalPathPolicy {
|
|
47
|
+
readonly canonicalRootFiles: readonly string[];
|
|
48
|
+
readonly canonicalRootDirs: readonly string[];
|
|
49
|
+
readonly canonicalSpecFiles: readonly string[];
|
|
50
|
+
readonly generatedRuntimePatterns: readonly string[];
|
|
51
|
+
readonly legacyMergeBeforeDeleteFiles: readonly string[];
|
|
52
|
+
}
|
|
53
|
+
export interface StrictPlanuCleanupResult {
|
|
54
|
+
deleted: string[];
|
|
55
|
+
merged: string[];
|
|
56
|
+
gitignoreUpdated: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface StrictPlanuValidationResult {
|
|
59
|
+
ok: boolean;
|
|
60
|
+
offenders: string[];
|
|
61
|
+
contract: string;
|
|
62
|
+
}
|
|
63
|
+
export interface UpdateStatusBatchInput {
|
|
64
|
+
specIds: string[];
|
|
65
|
+
status: SpecStatus;
|
|
66
|
+
projectId?: string;
|
|
67
|
+
projectPath?: string;
|
|
68
|
+
dryRun?: boolean;
|
|
69
|
+
reviewNotes?: string;
|
|
70
|
+
}
|
|
45
71
|
/** Report of detected migration drift (SPEC-715). Read-only — no FS mutations. */
|
|
46
72
|
export interface MigrationDriftReport {
|
|
47
73
|
/** Count of specs that still have a stray technical.md (need unified migration). */
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type EnglishOnlyArtifactKind = 'spec' | 'skill' | 'agent' | 'rule';
|
|
2
|
+
export interface EnglishOnlyValidationResult {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
detectedLanguage: 'en' | 'es' | 'pt' | 'unknown';
|
|
5
|
+
reason?: string;
|
|
6
|
+
signals: string[];
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=spec-language.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planu/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Planu — MCP Server for Spec Driven Development with native Rust acceleration for hot paths. Cross-platform (Linux/macOS/Windows, x64/arm64, glibc/musl).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"packageName": "@planu/core"
|
|
33
33
|
},
|
|
34
34
|
"optionalDependencies": {
|
|
35
|
-
"@planu/core-darwin-arm64": "
|
|
36
|
-
"@planu/core-darwin-x64": "
|
|
37
|
-
"@planu/core-linux-arm64-gnu": "
|
|
38
|
-
"@planu/core-linux-arm64-musl": "
|
|
39
|
-
"@planu/core-linux-x64-gnu": "
|
|
40
|
-
"@planu/core-linux-x64-musl": "
|
|
35
|
+
"@planu/core-darwin-arm64": "4.1.0",
|
|
36
|
+
"@planu/core-darwin-x64": "4.1.0",
|
|
37
|
+
"@planu/core-linux-arm64-gnu": "4.1.0",
|
|
38
|
+
"@planu/core-linux-arm64-musl": "4.1.0",
|
|
39
|
+
"@planu/core-linux-x64-gnu": "4.1.0",
|
|
40
|
+
"@planu/core-linux-x64-musl": "4.1.0"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=24.0.0"
|
|
@@ -149,8 +149,8 @@
|
|
|
149
149
|
"@commitlint/config-conventional": "^21.0.1",
|
|
150
150
|
"@eslint/js": "^10.0.1",
|
|
151
151
|
"@napi-rs/cli": "^3.6.2",
|
|
152
|
-
"@secretlint/secretlint-rule-no-homedir": "^13.0.
|
|
153
|
-
"@secretlint/secretlint-rule-preset-recommend": "^13.0.
|
|
152
|
+
"@secretlint/secretlint-rule-no-homedir": "^13.0.2",
|
|
153
|
+
"@secretlint/secretlint-rule-preset-recommend": "^13.0.2",
|
|
154
154
|
"@semantic-release/changelog": "^6.0.3",
|
|
155
155
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
156
156
|
"@semantic-release/git": "^10.0.1",
|
|
@@ -159,30 +159,30 @@
|
|
|
159
159
|
"@semantic-release/release-notes-generator": "^14.1.1",
|
|
160
160
|
"@stryker-mutator/core": "^9.6.1",
|
|
161
161
|
"@stryker-mutator/vitest-runner": "^9.6.1",
|
|
162
|
-
"@supabase/supabase-js": "^2.
|
|
163
|
-
"@types/node": "^25.
|
|
164
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
165
|
-
"@vitest/coverage-v8": "^4.1.
|
|
162
|
+
"@supabase/supabase-js": "^2.106.1",
|
|
163
|
+
"@types/node": "^25.9.1",
|
|
164
|
+
"@vitejs/plugin-vue": "^6.0.7",
|
|
165
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
166
166
|
"@vue/test-utils": "^2.4.10",
|
|
167
|
-
"eslint": "^10.
|
|
167
|
+
"eslint": "^10.4.0",
|
|
168
168
|
"eslint-config-prettier": "^10.1.8",
|
|
169
169
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
170
170
|
"eslint-plugin-import": "^2.32.0",
|
|
171
171
|
"happy-dom": "^20.9.0",
|
|
172
172
|
"husky": "^9.1.7",
|
|
173
173
|
"javascript-obfuscator": "^5.4.2",
|
|
174
|
-
"knip": "^6.
|
|
175
|
-
"lint-staged": "^17.0.
|
|
174
|
+
"knip": "^6.14.1",
|
|
175
|
+
"lint-staged": "^17.0.5",
|
|
176
176
|
"madge": "^8.0.0",
|
|
177
177
|
"prettier": "^3.8.3",
|
|
178
|
-
"secretlint": "^13.0.
|
|
178
|
+
"secretlint": "^13.0.2",
|
|
179
179
|
"semantic-release": "^25.0.3",
|
|
180
180
|
"tsc-alias": "^1.8.17",
|
|
181
181
|
"type-coverage": "^2.29.7",
|
|
182
182
|
"typescript": "^6.0.3",
|
|
183
|
-
"typescript-eslint": "^8.59.
|
|
184
|
-
"vite": "^8.0.
|
|
185
|
-
"vitest": "^4.1.
|
|
183
|
+
"typescript-eslint": "^8.59.4",
|
|
184
|
+
"vite": "^8.0.14",
|
|
185
|
+
"vitest": "^4.1.7",
|
|
186
186
|
"vue": "^3.5.34"
|
|
187
187
|
}
|
|
188
188
|
}
|