@planu/cli 5.7.4 → 5.7.6
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 +85 -0
- package/README.md +3 -3
- package/dist/.planu-build.json +1 -1
- package/dist/cli/commands/package-handoff.js +30 -5
- package/dist/config/compliance-profiles.json +36 -3
- package/dist/config/environment-schema.json +21 -0
- package/dist/config/hook-templates/planu-session-safeguard.sh +22 -15
- package/dist/config/official-sdd-tools.d.ts +1 -1
- package/dist/config/official-sdd-tools.js +11 -24
- package/dist/config/registries/hosts/codex.json +14 -30
- package/dist/config/registries/hosts/opencode.json +1 -6
- package/dist/config/registries/legacy-guidance.json +26 -0
- package/dist/config/server-instructions.js +0 -21
- package/dist/config/skill-templates/planu-context-assets.md +3 -6
- package/dist/config/skill-templates/planu-implement.md +2 -2
- package/dist/config/skill-templates/planu-multi-teammate-review.md +1 -1
- package/dist/config/skill-templates/planu-release.md +2 -7
- package/dist/config/skill-templates/planu-validate.md +3 -3
- package/dist/config/spec-templates/crud-rest-api/template.json +5 -1
- package/dist/config/spec-templates/file-upload-s3/template.json +5 -1
- package/dist/config/spec-templates/stripe-payments/template.json +5 -1
- package/dist/config/spec-templates/webhook-system/template.json +5 -1
- package/dist/config/subagent-templates/planu-challenger.md +4 -9
- package/dist/config/subagent-templates/planu-spec-implementer.md +2 -4
- package/dist/config/subagent-templates/planu-validator.md +5 -8
- package/dist/config/tool-groups.json +6 -144
- package/dist/engine/ambiguity-scorer.js +40 -1
- package/dist/engine/autopilot/bootstrap.js +1 -1
- package/dist/engine/code-impact-analyzer.js +2 -6
- package/dist/engine/context-orchestrator/index.js +2 -2
- package/dist/engine/convention-scanner/codebase-scanner.js +2 -2
- package/dist/engine/dogfooding/runtime-gap-detector.js +2 -2
- package/dist/engine/evidence-gates/artifact-reader.d.ts +1 -0
- package/dist/engine/evidence-gates/artifact-reader.js +1 -1
- package/dist/engine/evidence-gates/evidence-autofill.d.ts +13 -5
- package/dist/engine/evidence-gates/evidence-autofill.js +106 -43
- package/dist/engine/evidence-gates/lifecycle-gate.js +7 -4
- package/dist/engine/evidence-index/index-builder.js +21 -4
- package/dist/engine/execution/job-runtime.js +1 -1
- package/dist/engine/execution/package-handoff-job-executor.d.ts +22 -0
- package/dist/engine/execution/package-handoff-job-executor.js +490 -0
- package/dist/engine/execution/validate-job-executor.js +20 -8
- package/dist/engine/git/exec-git.d.ts +4 -0
- package/dist/engine/git/exec-git.js +14 -0
- package/dist/engine/handoff-artifacts/implementation-review-reader.js +15 -2
- package/dist/engine/handoff-artifacts/schemas.d.ts +2 -0
- package/dist/engine/handoff-artifacts/schemas.js +1 -0
- package/dist/engine/handoff-format.d.ts +36 -0
- package/dist/engine/handoff-format.js +314 -0
- package/dist/engine/handoff-packager.d.ts +5 -3
- package/dist/engine/handoff-packager.js +89 -32
- package/dist/engine/host-tool-filter.js +20 -49
- package/dist/engine/human-summary.js +14 -3
- package/dist/engine/implementation-contract/common.d.ts +8 -3
- package/dist/engine/implementation-contract/common.js +9 -6
- package/dist/engine/implementation-contract/evaluator.js +4 -6
- package/dist/engine/implementation-contract/renderer.js +18 -23
- package/dist/engine/project-health-checker.js +2 -2
- package/dist/engine/readiness-checker.js +27 -0
- package/dist/engine/reconcile/apply-changes.js +4 -0
- package/dist/engine/reconcile/propagate-mirrors.d.ts +3 -0
- package/dist/engine/reconcile/propagate-mirrors.js +311 -0
- package/dist/engine/self-healing/healer.js +12 -5
- package/dist/engine/self-healing/strategies/lint-fix.d.ts +1 -1
- package/dist/engine/self-healing/strategies/lint-fix.js +4 -1
- package/dist/engine/self-healing/strategies/test-fix.d.ts +4 -3
- package/dist/engine/self-healing/strategies/test-fix.js +32 -14
- package/dist/engine/self-healing/strategies/typescript-fix.d.ts +1 -1
- package/dist/engine/self-healing/strategies/typescript-fix.js +28 -10
- package/dist/engine/session/checkpoint-writer.js +8 -4
- package/dist/engine/session/session-tracker.d.ts +5 -16
- package/dist/engine/session/session-tracker.js +29 -26
- package/dist/engine/session-state/writer.js +3 -11
- package/dist/engine/skill-generator/workflow-skill-generator.d.ts +4 -2
- package/dist/engine/skill-generator/workflow-skill-generator.js +113 -38
- package/dist/engine/spec-format/bdd-parser.d.ts +1 -11
- package/dist/engine/spec-format/bdd-parser.js +40 -11
- package/dist/engine/spec-format/lean-spec-generator.js +30 -10
- package/dist/engine/spec-format/retired-scaffold.d.ts +3 -0
- package/dist/engine/spec-format/retired-scaffold.js +5 -0
- package/dist/engine/spec-format/technical-md-populator.d.ts +1 -0
- package/dist/engine/spec-format/technical-md-populator.js +27 -0
- package/dist/engine/spec-format/unified-spec-builder.d.ts +1 -0
- package/dist/engine/spec-format/unified-spec-builder.js +30 -20
- package/dist/engine/spec-grounding/contract.js +115 -1
- package/dist/engine/spec-migrator/fold-technical.js +60 -19
- package/dist/engine/spec-migrator/placeholder-technical.d.ts +2 -0
- package/dist/engine/spec-migrator/placeholder-technical.js +18 -0
- package/dist/engine/spec-quality/generic-output-gate.js +37 -3
- package/dist/engine/technical-enricher/index.js +4 -1
- package/dist/engine/type-safety-gate.js +3 -11
- package/dist/engine/universal-rules/catalog.js +0 -2
- package/dist/engine/universal-rules/rules/planu-workflow.js +1 -1
- package/dist/engine/validation/durable-validation.d.ts +3 -2
- package/dist/engine/validation/durable-validation.js +106 -40
- package/dist/engine/validation/validation-freshness.d.ts +3 -2
- package/dist/engine/validation/validation-freshness.js +22 -16
- package/dist/engine/validation/validation-worktree.js +34 -0
- package/dist/hosts/claude-code/ux/mcp-prompts.js +8 -8
- package/dist/index.js +3 -17
- package/dist/resources/process.js +38 -65
- package/dist/storage/session-state-store.js +2 -0
- package/dist/tools/challenge-spec/scenarios-utils.js +2 -2
- package/dist/tools/configure-checkpoint-policy.js +3 -3
- package/dist/tools/create-spec-helpers.js +2 -5
- package/dist/tools/create-spec.js +21 -4
- package/dist/tools/facilitate.js +3 -6
- package/dist/tools/git/branch-ops.js +16 -4
- package/dist/tools/github-release-handler.js +1 -20
- package/dist/tools/heal-spec-docs.js +1 -13
- package/dist/tools/init-project/agents-md-writer.js +6 -6
- package/dist/tools/init-project/claude-md-generator.d.ts +0 -1
- package/dist/tools/init-project/claude-md-generator.js +0 -35
- package/dist/tools/init-project/handler.js +24 -49
- package/dist/tools/init-project/legacy-guidance-scanner.d.ts +12 -0
- package/dist/tools/init-project/legacy-guidance-scanner.js +176 -0
- package/dist/tools/init-project/per-client-files-writer.js +5 -5
- package/dist/tools/init-project/planu-workflow-generator.js +2 -13
- package/dist/tools/init-project/portable-index-reconciler.d.ts +21 -1
- package/dist/tools/init-project/portable-index-reconciler.js +66 -0
- package/dist/tools/init-project/rules-generator.d.ts +0 -11
- package/dist/tools/init-project/rules-generator.js +4 -85
- package/dist/tools/init-project/scaffold-writer.d.ts +0 -1
- package/dist/tools/init-project/scaffold-writer.js +1 -12
- package/dist/tools/jobs/handlers.d.ts +0 -6
- package/dist/tools/jobs/handlers.js +13 -40
- package/dist/tools/list-specs.js +6 -21
- package/dist/tools/package-handoff.d.ts +3 -2
- package/dist/tools/package-handoff.js +153 -427
- package/dist/tools/reconcile-session-safeguard-hook.js +22 -15
- package/dist/tools/register-sdd-tools.js +0 -23
- package/dist/tools/register-spec-tools/core-spec-tools.js +18 -27
- package/dist/tools/schemas/index.d.ts +1 -1
- package/dist/tools/schemas/index.js +1 -1
- package/dist/tools/schemas/output-schemas.d.ts +1 -18
- package/dist/tools/schemas/output-schemas.js +1 -11
- package/dist/tools/schemas/package-handoff-output-schema.d.ts +40 -0
- package/dist/tools/schemas/package-handoff-output-schema.js +68 -0
- package/dist/tools/schemas/validate-output-schema.d.ts +1 -2
- package/dist/tools/schemas/validate-output-schema.js +3 -2
- package/dist/tools/session-checkpoint.js +2 -2
- package/dist/tools/skill-registry/index.d.ts +0 -1
- package/dist/tools/skill-registry/index.js +0 -1
- package/dist/tools/sync-spec-state-handler.d.ts +2 -2
- package/dist/tools/sync-spec-state-handler.js +23 -3
- package/dist/tools/tool-registry/core-tools.js +1 -140
- package/dist/tools/tool-registry/group-infra.js +2 -39
- package/dist/tools/tool-registry/group-quality-compliance.js +9 -1
- package/dist/tools/update-status/batch.js +17 -0
- package/dist/tools/update-status/dod-gates.js +14 -1
- package/dist/tools/update-status/done-receipt-verifier.d.ts +22 -0
- package/dist/tools/update-status/done-receipt-verifier.js +56 -26
- package/dist/tools/update-status/evidence-gate.js +10 -21
- package/dist/tools/update-status/file-sync.d.ts +1 -0
- package/dist/tools/update-status/file-sync.js +6 -0
- package/dist/tools/update-status/index.d.ts +6 -0
- package/dist/tools/update-status/index.js +39 -44
- package/dist/tools/update-status-actions.js +2 -7
- package/dist/tools/validate.js +34 -28
- package/dist/transports/oauth-validator.js +12 -1
- package/dist/transports/transport-factory.d.ts +2 -1
- package/dist/transports/transport-factory.js +19 -0
- package/dist/types/common/primitives.d.ts +2 -0
- package/dist/types/durable-job.d.ts +45 -0
- package/dist/types/durable-validation.d.ts +1 -1
- package/dist/types/evidence-autofill.d.ts +13 -1
- package/dist/types/handoff-artifacts.d.ts +2 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/legacy-guidance.d.ts +20 -0
- package/dist/types/legacy-guidance.js +3 -0
- package/dist/types/readiness.d.ts +8 -1
- package/dist/types/reconcile.d.ts +6 -0
- package/dist/types/skill-registry.d.ts +26 -1
- package/dist/types/spec/core.d.ts +5 -0
- package/dist/types/spec/inputs.d.ts +2 -2
- package/dist/types/spec-format.d.ts +11 -1
- package/dist/types/spec-grounding.d.ts +12 -0
- package/dist/types/ssr-migration.d.ts +1 -1
- package/dist/types/transport.d.ts +1 -0
- package/dist/types/validation-receipt.d.ts +27 -0
- package/package.json +3 -2
- package/planu-plugin.json +13 -26
- package/src/i18n/messages/en.json +1 -1
- package/src/i18n/messages/es.json +1 -1
- package/src/i18n/messages/pt.json +1 -1
- package/dist/engine/skill-generator/conventions-hasher.d.ts +0 -7
- package/dist/engine/skill-generator/conventions-hasher.js +0 -24
- package/dist/engine/universal-rules/rules/agent-teams.d.ts +0 -3
- package/dist/engine/universal-rules/rules/agent-teams.js +0 -63
- package/dist/tools/clarify-requirements/multiple-choice.d.ts +0 -30
- package/dist/tools/clarify-requirements/multiple-choice.js +0 -306
- package/dist/tools/clarify-requirements/questions-context.d.ts +0 -9
- package/dist/tools/clarify-requirements/questions-context.js +0 -74
- package/dist/tools/clarify-requirements/questions.d.ts +0 -16
- package/dist/tools/clarify-requirements/questions.js +0 -96
- package/dist/tools/clarify-requirements.d.ts +0 -4
- package/dist/tools/clarify-requirements.js +0 -314
- package/dist/tools/code-graph-handler.d.ts +0 -6
- package/dist/tools/code-graph-handler.js +0 -72
- package/dist/tools/create-rule.d.ts +0 -4
- package/dist/tools/create-rule.js +0 -107
- package/dist/tools/feedback-handler.d.ts +0 -7
- package/dist/tools/feedback-handler.js +0 -150
- package/dist/tools/semantic-search-handler.d.ts +0 -7
- package/dist/tools/semantic-search-handler.js +0 -71
- package/dist/tools/skill-registry/search.d.ts +0 -11
- package/dist/tools/skill-registry/search.js +0 -159
|
@@ -16,90 +16,63 @@ function getSddProcess() {
|
|
|
16
16
|
{
|
|
17
17
|
id: 'initializing',
|
|
18
18
|
name: '1. Initialize',
|
|
19
|
-
tools: ['init_project'
|
|
20
|
-
description: '
|
|
21
|
-
'Generate the project constitution. Detect the AI agent platform in use.',
|
|
19
|
+
tools: ['init_project'],
|
|
20
|
+
description: 'Load or bootstrap the Planu project context for the current repository.',
|
|
22
21
|
},
|
|
23
22
|
{
|
|
24
|
-
id: '
|
|
25
|
-
name: '2.
|
|
26
|
-
tools: [
|
|
27
|
-
|
|
28
|
-
'
|
|
29
|
-
'check_versions',
|
|
30
|
-
'consult_docs',
|
|
31
|
-
'discover_mcps',
|
|
32
|
-
'suggest_mcps',
|
|
33
|
-
'suggest_tooling',
|
|
34
|
-
],
|
|
35
|
-
description: 'Clarify requirements, analyze the stack, check dependency versions, ' +
|
|
36
|
-
'discover available MCP servers, and assess dev lifecycle tooling.',
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: 'creating-spec',
|
|
40
|
-
name: '3. Create Spec',
|
|
41
|
-
tools: ['create_spec', 'reverse_engineer', 'estimate'],
|
|
42
|
-
description: 'Create a full SDD spec.md from requirements or ' +
|
|
43
|
-
'reverse-engineer from existing code. Estimate effort, cost, and tokens.',
|
|
23
|
+
id: 'defining',
|
|
24
|
+
name: '2. Define',
|
|
25
|
+
tools: ['facilitate', 'create_spec'],
|
|
26
|
+
description: 'Facilitate requirements discovery through the universal SDD entry point, ' +
|
|
27
|
+
'then create the spec.md that becomes the contract for implementation.',
|
|
44
28
|
},
|
|
45
29
|
{
|
|
46
|
-
id: '
|
|
47
|
-
name: '
|
|
30
|
+
id: 'approving',
|
|
31
|
+
name: '3. Refine & Approve',
|
|
48
32
|
tools: [
|
|
49
|
-
'generate_adr',
|
|
50
|
-
'design_schema',
|
|
51
|
-
'define_ui_contract',
|
|
52
33
|
'challenge_spec',
|
|
53
|
-
'
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
'resilience analysis, and step-by-step execution plans.',
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
id: 'reviewing',
|
|
60
|
-
name: '5. Review',
|
|
61
|
-
tools: [
|
|
62
|
-
'summarize_spec',
|
|
63
|
-
'generate_checklist',
|
|
64
|
-
'reconcile_spec',
|
|
65
|
-
'list_specs',
|
|
34
|
+
'check_readiness',
|
|
35
|
+
'estimate',
|
|
36
|
+
'request_changes',
|
|
66
37
|
'update_status',
|
|
67
38
|
],
|
|
68
|
-
description: '
|
|
69
|
-
'
|
|
39
|
+
description: 'Stress-test the spec, verify it has enough detail to implement, estimate ' +
|
|
40
|
+
'effort and cost, request changes if gaps remain, and move the spec through ' +
|
|
41
|
+
'draft → review → approved.',
|
|
70
42
|
},
|
|
71
43
|
{
|
|
72
44
|
id: 'implementing',
|
|
73
|
-
name: '
|
|
74
|
-
tools: [
|
|
75
|
-
|
|
76
|
-
'
|
|
77
|
-
'generate_rules',
|
|
78
|
-
'manage_git',
|
|
79
|
-
'manage_context',
|
|
80
|
-
'orchestrate',
|
|
81
|
-
],
|
|
82
|
-
description: 'Generate agent skills and rules. Manage git branches and PRs. ' +
|
|
83
|
-
'Orchestrate multi-agent workflows. Persist context across sessions.',
|
|
45
|
+
name: '4. Implement',
|
|
46
|
+
tools: ['package_handoff', 'bump_spec_version'],
|
|
47
|
+
description: 'Generate the implementation handoff package for the coding agent and bump ' +
|
|
48
|
+
"the spec's SemVer as its contract evolves.",
|
|
84
49
|
},
|
|
85
50
|
{
|
|
86
51
|
id: 'validating',
|
|
87
|
-
name: '
|
|
88
|
-
tools: ['validate', '
|
|
89
|
-
description: '
|
|
90
|
-
'
|
|
52
|
+
name: '5. Validate',
|
|
53
|
+
tools: ['validate', 'get_job', 'restart_job'],
|
|
54
|
+
description: 'Check the implementation against acceptance criteria, poll the durable ' +
|
|
55
|
+
'validation job to completion, and restart it if it fails or is cancelled.',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'closing',
|
|
59
|
+
name: '6. Reconcile & Close',
|
|
60
|
+
tools: ['reconcile_spec', 'migrate_legacy_spec', 'update_status_batch'],
|
|
61
|
+
description: 'Reconcile implementation drift back into the spec, migrate legacy spec docs ' +
|
|
62
|
+
'onto the canonical spec.md, and batch-transition specs to done. Shipping ' +
|
|
63
|
+
'runs the local-first release contract (`pnpm check:preflight`, then ' +
|
|
64
|
+
'`pnpm release:local`) outside the MCP tool surface.',
|
|
91
65
|
},
|
|
92
66
|
{
|
|
93
|
-
id: '
|
|
94
|
-
name: '
|
|
95
|
-
tools: ['
|
|
96
|
-
description: '
|
|
97
|
-
'
|
|
98
|
-
'sync with project management tools, and learn patterns for future estimations.',
|
|
67
|
+
id: 'tracking',
|
|
68
|
+
name: '7. Track',
|
|
69
|
+
tools: ['list_specs', 'planu_status', 'session_checkpoint'],
|
|
70
|
+
description: 'List specs and their status, check overall project health, and persist ' +
|
|
71
|
+
'session context so work can resume across sessions.',
|
|
99
72
|
},
|
|
100
73
|
],
|
|
101
74
|
specLifecycle: ['draft', 'review', 'approved', 'implementing', 'done'],
|
|
102
|
-
totalTools:
|
|
75
|
+
totalTools: 19,
|
|
103
76
|
};
|
|
104
77
|
}
|
|
105
78
|
/**
|
|
@@ -33,8 +33,8 @@ const CAPABILITY_SIGNALS = {
|
|
|
33
33
|
/\bbatch\s+upload\b/i,
|
|
34
34
|
],
|
|
35
35
|
scale: [
|
|
36
|
-
/\b(?:traffic|
|
|
37
|
-
/\b(?:auto[ -]?scal|load\s+test|capacity\s+plan)/i,
|
|
36
|
+
/\b(?:traffic|throughput|requests?\s+per\s+second|concurrent\s+users?)\b/i,
|
|
37
|
+
/\b(?:auto[ -]?scal|load\s+(?:test|balanc|shedding|envelope|spike)|(?:peak|heavy|normal|sustained|read|write)\s+load|capacity\s+plan)/i,
|
|
38
38
|
/\b(?:data\s+growth|growing\s+dataset|query\s+performance\s+at\s+scale)\b/i,
|
|
39
39
|
],
|
|
40
40
|
dataWrite: [
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// tools/configure-checkpoint-policy.ts — Configure auto checkpoint policy (SPEC-563).
|
|
2
|
-
import {
|
|
2
|
+
import { setCheckpointPolicy, getCheckpointPolicy } from '../engine/session/session-tracker.js';
|
|
3
3
|
import { compactResult } from './output-formatter.js';
|
|
4
4
|
/**
|
|
5
5
|
* Handle the configure_checkpoint_policy tool.
|
|
6
6
|
* Updates threshold and/or enabled flag, returns the current policy.
|
|
7
7
|
*/
|
|
8
8
|
export function handleConfigureCheckpointPolicy(args) {
|
|
9
|
-
|
|
9
|
+
setCheckpointPolicy({
|
|
10
10
|
threshold: args.threshold,
|
|
11
11
|
enabled: args.enabled,
|
|
12
12
|
});
|
|
13
|
-
const policy =
|
|
13
|
+
const policy = getCheckpointPolicy();
|
|
14
14
|
return compactResult(`Checkpoint policy updated for ${args.projectPath}.\n` +
|
|
15
15
|
`Threshold: every ${String(policy.threshold)} calls, ` +
|
|
16
16
|
`enabled: ${String(policy.enabled)}.`);
|
|
@@ -26,11 +26,8 @@ export async function tryAutoSetupGit(projectId, specId, options) {
|
|
|
26
26
|
/* v8 ignore start -- requires real git repo with branches */
|
|
27
27
|
try {
|
|
28
28
|
const r = await handleAutoSetup(projectId, specId, undefined, options);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (typeof data.newBranch !== 'string') {
|
|
32
|
-
return undefined;
|
|
33
|
-
}
|
|
29
|
+
const data = r.structuredContent;
|
|
30
|
+
if (!r.isError && data && typeof data.newBranch === 'string') {
|
|
34
31
|
return { data, branch: data.newBranch };
|
|
35
32
|
}
|
|
36
33
|
}
|
|
@@ -20,6 +20,7 @@ import { generateLeanTechnicalContent, } from '../engine/spec-format/lean-techni
|
|
|
20
20
|
import { extractFilesFromSpecBody, extractMarkerDeclaredPaths, } from '../engine/spec-format/technical-md-populator.js';
|
|
21
21
|
import { buildCanonicalUnifiedSpecContent, containsUnresolvedContractPlaceholder, validateUnifiedSpecCandidate, } from '../engine/spec-format/unified-spec-builder.js';
|
|
22
22
|
import { buildImplementationContractSection } from '../engine/implementation-contract/index.js';
|
|
23
|
+
import { updateFrontmatterField } from '../engine/frontmatter-parser.js';
|
|
23
24
|
import { resolveEnglishOnlySpecGate } from '../engine/spec-language/english-only.js';
|
|
24
25
|
import { FallbackGenerator } from '../engine/spec-generator/index.js';
|
|
25
26
|
import { analyzeProjectForSpec, getEmptyAutopilotResult, } from './create-spec/autopilot-analyzer.js';
|
|
@@ -1257,7 +1258,7 @@ async function prepareCreateSpecCandidate(initialParams, server) {
|
|
|
1257
1258
|
outOfScope,
|
|
1258
1259
|
verificationCommands,
|
|
1259
1260
|
});
|
|
1260
|
-
|
|
1261
|
+
let unifiedSpec = buildCanonicalUnifiedSpecContent({
|
|
1261
1262
|
leanSpecBody: leanSpec,
|
|
1262
1263
|
sourceDescription: params.description,
|
|
1263
1264
|
technicalBody: leanTechnical,
|
|
@@ -1269,12 +1270,18 @@ async function prepareCreateSpecCandidate(initialParams, server) {
|
|
|
1269
1270
|
const candidateValidation = validateUnifiedSpecCandidate(unifiedSpec, {
|
|
1270
1271
|
groundedFilePaths: groundedTechnical.records.map((record) => record.path),
|
|
1271
1272
|
});
|
|
1272
|
-
|
|
1273
|
+
// SPEC-1435: MISSING_EXECUTABLE_CRITERIA no longer blocks persistence — plain-text
|
|
1274
|
+
// criteria are accepted input today (checkbox items via extractAcceptanceCriteriaTexts),
|
|
1275
|
+
// and the constant GIVEN/WHEN/THEN scaffold that used to satisfy this check has been
|
|
1276
|
+
// retired. The readiness-checker approval gate now blocks a zero-BDD spec at
|
|
1277
|
+
// review -> approved instead; here it downgrades to a persisted quality warning.
|
|
1278
|
+
const blockingCandidateIssues = candidateValidation.issues.filter((issue) => issue.code !== 'MISSING_EXECUTABLE_CRITERIA');
|
|
1279
|
+
if (blockingCandidateIssues.length > 0) {
|
|
1273
1280
|
return earlyPreparation({
|
|
1274
1281
|
content: [
|
|
1275
1282
|
{
|
|
1276
1283
|
type: 'text',
|
|
1277
|
-
text: `Unified spec candidate is invalid: ${
|
|
1284
|
+
text: `Unified spec candidate is invalid: ${blockingCandidateIssues
|
|
1278
1285
|
.slice(0, 3)
|
|
1279
1286
|
.map((issue) => issue.message)
|
|
1280
1287
|
.join('; ')}`,
|
|
@@ -1285,10 +1292,20 @@ async function prepareCreateSpecCandidate(initialParams, server) {
|
|
|
1285
1292
|
error: 'SPEC_FORMAT_INVALID',
|
|
1286
1293
|
code: 422,
|
|
1287
1294
|
persisted: false,
|
|
1288
|
-
issues:
|
|
1295
|
+
issues: blockingCandidateIssues,
|
|
1289
1296
|
},
|
|
1290
1297
|
});
|
|
1291
1298
|
}
|
|
1299
|
+
if (candidateValidation.issues.some((issue) => issue.code === 'MISSING_EXECUTABLE_CRITERIA')) {
|
|
1300
|
+
const nonExecutableCriteriaWarning = 'Acceptance criteria are not executable GIVEN/WHEN/THEN — restate them before approval';
|
|
1301
|
+
spec.qualityWarnings = [
|
|
1302
|
+
...new Set([...(spec.qualityWarnings ?? []), nonExecutableCriteriaWarning]),
|
|
1303
|
+
];
|
|
1304
|
+
// unifiedSpec's frontmatter was already serialized from `spec` before this warning was
|
|
1305
|
+
// known — patch the persisted YAML field directly rather than re-serializing the whole
|
|
1306
|
+
// candidate.
|
|
1307
|
+
unifiedSpec = updateFrontmatterField(unifiedSpec, 'qualityWarnings', JSON.stringify(spec.qualityWarnings));
|
|
1308
|
+
}
|
|
1292
1309
|
const genericOutputGate = checkGenericSpecOutput(unifiedSpec);
|
|
1293
1310
|
if (!genericOutputGate.passed) {
|
|
1294
1311
|
return earlyPreparation({
|
package/dist/tools/facilitate.js
CHANGED
|
@@ -39,8 +39,8 @@ function buildExistingProjectResponse(description) {
|
|
|
39
39
|
return (`I'll run a diagnostic on your project.\n\n` +
|
|
40
40
|
`Please provide the project path and call:\n` +
|
|
41
41
|
`- \`init_project\` with your project path (if not yet initialized)\n` +
|
|
42
|
-
`- \`
|
|
43
|
-
`- \`
|
|
42
|
+
`- \`list_specs\` to see existing specs\n` +
|
|
43
|
+
`- \`planu_status\` to check overall project health\n\n` +
|
|
44
44
|
`Request received: "${description.slice(0, 120)}"`);
|
|
45
45
|
}
|
|
46
46
|
// ---------------------------------------------------------------------------
|
|
@@ -51,7 +51,6 @@ const PROBLEM_TO_TOOL = [
|
|
|
51
51
|
[/validat/i, 'validate', 'validate a spec'],
|
|
52
52
|
[/spec|user stor/i, 'create_spec', 'create a spec/user story'],
|
|
53
53
|
[/estimat/i, 'estimate', 'estimate effort and cost'],
|
|
54
|
-
[/test/i, 'generate_tests', 'generate tests'],
|
|
55
54
|
[/document|doc/i, 'generate_docs', 'generate documentation'],
|
|
56
55
|
[/drift|diverge/i, 'detect_drift', 'detect spec drift'],
|
|
57
56
|
[/schema|database|db/i, 'design_schema', 'design a database schema'],
|
|
@@ -69,10 +68,8 @@ function buildConcreteProblemResponse(description) {
|
|
|
69
68
|
}
|
|
70
69
|
return (`I can help with that! Here are the most relevant Planu tools:\n\n` +
|
|
71
70
|
`- \`create_spec\` — write a new user story / spec\n` +
|
|
72
|
-
`- \`clarify_requirements\` — clarify vague requirements\n` +
|
|
73
71
|
`- \`estimate\` — estimate effort and cost\n` +
|
|
74
|
-
`- \`validate\` — check if a spec is complete\n` +
|
|
75
|
-
`- \`generate_tests\` — generate test scaffolds\n\n` +
|
|
72
|
+
`- \`validate\` — check if a spec is complete\n\n` +
|
|
76
73
|
`What specifically would you like to do?`);
|
|
77
74
|
}
|
|
78
75
|
// ---------------------------------------------------------------------------
|
|
@@ -54,7 +54,10 @@ export async function handleCreateBranch(projectId, specId, config, resolvedProj
|
|
|
54
54
|
? `Switched to existing branch '${branchName}'`
|
|
55
55
|
: `Branch '${branchName}' already exists (checkout left untouched)`,
|
|
56
56
|
};
|
|
57
|
-
return
|
|
57
|
+
return {
|
|
58
|
+
...compactResult(formatKeyValue(result)),
|
|
59
|
+
structuredContent: result,
|
|
60
|
+
};
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
catch {
|
|
@@ -74,7 +77,10 @@ export async function handleCreateBranch(projectId, specId, config, resolvedProj
|
|
|
74
77
|
branchName,
|
|
75
78
|
message: ti('tools.manage_git.success', { action: 'create-branch' }),
|
|
76
79
|
};
|
|
77
|
-
return
|
|
80
|
+
return {
|
|
81
|
+
...compactResult(formatKeyValue(result)),
|
|
82
|
+
structuredContent: result,
|
|
83
|
+
};
|
|
78
84
|
}
|
|
79
85
|
export async function handleCheckBranch(projectId, _specId, config) {
|
|
80
86
|
const projectPath = await resolveProjectPath(projectId);
|
|
@@ -217,7 +223,10 @@ export async function handleAutoSetup(projectId, specId, config, options) {
|
|
|
217
223
|
? `Switched to existing branch '${branchName}' (${gitFlowType} workflow detected)`
|
|
218
224
|
: `Branch '${branchName}' already exists (checkout left untouched)`,
|
|
219
225
|
};
|
|
220
|
-
return
|
|
226
|
+
return {
|
|
227
|
+
...compactResult(formatKeyValue(result)),
|
|
228
|
+
structuredContent: result,
|
|
229
|
+
};
|
|
221
230
|
}
|
|
222
231
|
}
|
|
223
232
|
catch {
|
|
@@ -235,7 +244,10 @@ export async function handleAutoSetup(projectId, specId, config, options) {
|
|
|
235
244
|
? `Created branch '${branchName}' from '${baseBranch}' (${gitFlowType} workflow detected)`
|
|
236
245
|
: `Created branch '${branchName}' from '${baseBranch}' without switching the checkout`,
|
|
237
246
|
};
|
|
238
|
-
return
|
|
247
|
+
return {
|
|
248
|
+
...compactResult(formatKeyValue(result)),
|
|
249
|
+
structuredContent: result,
|
|
250
|
+
};
|
|
239
251
|
}
|
|
240
252
|
// ---------------------------------------------------------------------------
|
|
241
253
|
// Worktree operations (SPEC-260)
|
|
@@ -252,26 +252,7 @@ export async function handleCreateRelease(args, exec = defaultExec) {
|
|
|
252
252
|
/* best-effort — release_completed cascade never blocks the release response */
|
|
253
253
|
}
|
|
254
254
|
})();
|
|
255
|
-
|
|
256
|
-
void (async () => {
|
|
257
|
-
try {
|
|
258
|
-
const releasePath = process.cwd();
|
|
259
|
-
const run = promisify(nodeExecFile);
|
|
260
|
-
const { stdout: currentBranch } = await run('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
261
|
-
cwd: releasePath,
|
|
262
|
-
});
|
|
263
|
-
if (currentBranch.trim() === 'develop') {
|
|
264
|
-
await run('git', ['checkout', 'main'], { cwd: releasePath });
|
|
265
|
-
await run('git', ['merge', 'develop', '--no-edit'], { cwd: releasePath });
|
|
266
|
-
await run('git', ['push', '--no-verify', 'origin', 'main'], { cwd: releasePath });
|
|
267
|
-
await run('git', ['checkout', 'develop'], { cwd: releasePath });
|
|
268
|
-
outputLines.push(' Auto-merge: develop → main');
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
catch {
|
|
272
|
-
/* best-effort — auto-merge never blocks release */
|
|
273
|
-
}
|
|
274
|
-
})();
|
|
255
|
+
outputLines.push(' Mirror sync (run manually if develop exists): git checkout develop && git merge --ff-only origin/main && git push origin develop');
|
|
275
256
|
return {
|
|
276
257
|
content: [
|
|
277
258
|
{
|
|
@@ -13,6 +13,7 @@ import { replaceSectionInSpec } from '../engine/spec-format/replace-section.js';
|
|
|
13
13
|
import { executionRemove } from '../engine/execution/deadline-io.js';
|
|
14
14
|
import { buildMigrationDirective, scanLegacyArtifacts, } from '../engine/spec-migrator/legacy-classifier.js';
|
|
15
15
|
import { escapeRegex } from '../core/shared/strings.js';
|
|
16
|
+
import { isPlaceholderTechnical } from '../engine/spec-migrator/placeholder-technical.js';
|
|
16
17
|
const SPANISH_INDICATORS = [
|
|
17
18
|
'de',
|
|
18
19
|
'del',
|
|
@@ -36,19 +37,6 @@ const SPANISH_INDICATORS = [
|
|
|
36
37
|
// ---------------------------------------------------------------------------
|
|
37
38
|
// Placeholder detection
|
|
38
39
|
// ---------------------------------------------------------------------------
|
|
39
|
-
function isPlaceholderTechnical(content) {
|
|
40
|
-
if (content.includes('(pending)')) {
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
if (/--[a-z]/.test(content)) {
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
|
-
if (content.includes('(to be determined)') &&
|
|
47
|
-
!/\.(ts|tsx|js|jsx|py|rb|go|java|cs)/.test(content)) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
40
|
function hasInlineTechnicalFilesPlaceholder(content) {
|
|
53
41
|
return /^##\s+Technical\b[\s\S]*?^##\s+Files\b[\s\S]*?(?:\(pending\)|\(to be determined\)|\bTBD\b|--[a-z])/im.test(content);
|
|
54
42
|
}
|
|
@@ -34,13 +34,13 @@ Auto-generated by \`init_project\`. Mirrors CLAUDE.md for IDEs that read AGENTS.
|
|
|
34
34
|
\`\`\`
|
|
35
35
|
facilitate("what to build") → create_spec → challenge_spec → check_readiness
|
|
36
36
|
→ update_status(review) → approve → update_status(approved) → implement
|
|
37
|
-
→ validate (ack) →
|
|
37
|
+
→ validate (ack) → get_job (poll until completed) → inspect job.result → update_status(done)
|
|
38
38
|
\`\`\`
|
|
39
39
|
|
|
40
40
|
## Durable Validation Gate
|
|
41
41
|
|
|
42
|
-
1. Call \`validate\` and capture \`operationId\`, \`projectId\`,
|
|
43
|
-
2.
|
|
42
|
+
1. Call \`validate\` and capture \`operationId\`, \`projectId\`, and \`workspaceId\` from the acknowledgement
|
|
43
|
+
2. Poll \`get_job\` with those identifiers until the job reaches a terminal state
|
|
44
44
|
3. Require \`completed\` and inspect \`job.result.structuredContent\`; stop on \`failed\`, \`dead-letter\`, or \`cancelled\`
|
|
45
45
|
4. Call \`update_status(done)\` only when the completed result reports \`ready: true\`, \`status: "passing"\`, and passing quality gates
|
|
46
46
|
|
|
@@ -52,7 +52,7 @@ facilitate("what to build") → create_spec → challenge_spec → check_readine
|
|
|
52
52
|
## Session End
|
|
53
53
|
|
|
54
54
|
- Call \`session_checkpoint\` to save context
|
|
55
|
-
- Run \`validate\`,
|
|
55
|
+
- Run \`validate\`, poll \`get_job\` until completed, inspect \`job.result.structuredContent\`, then call \`update_status(done)\`
|
|
56
56
|
|
|
57
57
|
## Quick Reference
|
|
58
58
|
|
|
@@ -79,7 +79,7 @@ Auto-generated by init_project.
|
|
|
79
79
|
1. Before writing any code, call facilitate() or create_spec() first.
|
|
80
80
|
2. Never write code without an approved Planu spec.
|
|
81
81
|
3. Always call validate() after implementation; it returns a durable job acknowledgement, not pass/fail.
|
|
82
|
-
4.
|
|
82
|
+
4. Poll get_job() until completed and inspect job.result.structuredContent before marking done.
|
|
83
83
|
5. Use update_status() to track progress: draft → review → approved → implementing → done.
|
|
84
84
|
|
|
85
85
|
## Session
|
|
@@ -91,7 +91,7 @@ Auto-generated by init_project.
|
|
|
91
91
|
|
|
92
92
|
- New feature: facilitate("what to build")
|
|
93
93
|
- Check status: planu_status
|
|
94
|
-
- Mark done: validate,
|
|
94
|
+
- Mark done: validate, poll get_job until completed, inspect job.result.structuredContent, then update_status(done)
|
|
95
95
|
`;
|
|
96
96
|
async function writeIfMissing(path, content) {
|
|
97
97
|
try {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import type { ProjectKnowledge } from '../../types/project/core.js';
|
|
2
|
-
export declare function buildTeamCoordinationSection(knowledge: ProjectKnowledge): string | null;
|
|
3
2
|
export declare function buildProjectSections(knowledge: ProjectKnowledge): string;
|
|
4
3
|
//# sourceMappingURL=claude-md-generator.d.ts.map
|
|
@@ -214,37 +214,6 @@ function buildDeployment(knowledge) {
|
|
|
214
214
|
const label = key ? DEPLOY_PLATFORM_MAP[key] : raw;
|
|
215
215
|
return wrap('deployment', `## Deployment\n- **Platform**: ${label}`);
|
|
216
216
|
}
|
|
217
|
-
export function buildTeamCoordinationSection(knowledge) {
|
|
218
|
-
const isMultiLayer = knowledge.layers.length > 2;
|
|
219
|
-
const isMonorepo = knowledge.monorepo;
|
|
220
|
-
if (!isMultiLayer && !isMonorepo) {
|
|
221
|
-
return null;
|
|
222
|
-
}
|
|
223
|
-
const patternList = [
|
|
224
|
-
'- `implement-and-test` — one agent implements, another writes tests (no shared files)',
|
|
225
|
-
'- `full-stack` — frontend/backend split with clear API boundary',
|
|
226
|
-
'- `research-then-build` — researcher gathers context, builder implements',
|
|
227
|
-
'- `parallel-specs` — N agents implement N independent specs simultaneously',
|
|
228
|
-
];
|
|
229
|
-
const lines = [
|
|
230
|
-
'## Agent Teams (for 3+ specs in parallel)',
|
|
231
|
-
'',
|
|
232
|
-
'When implementing multiple independent specs simultaneously, use Agent Teams:',
|
|
233
|
-
'',
|
|
234
|
-
'1. Call `plan_team_distribution` with spec IDs → assigns exclusive file ownership per agent',
|
|
235
|
-
'2. Call `generate_teammate_prompt` for each teammate → generates isolated prompt with context',
|
|
236
|
-
'3. Spawn N Claude Code agents with the generated prompts (`claude -p "<prompt>"`)',
|
|
237
|
-
'4. Call `validate_team_results` after completion → verifies merged code integrity',
|
|
238
|
-
'',
|
|
239
|
-
'**When to use teams**: 3+ independent specs ready, estimated effort >8h, clear module boundaries.',
|
|
240
|
-
'',
|
|
241
|
-
'**Available patterns:**',
|
|
242
|
-
...patternList,
|
|
243
|
-
'',
|
|
244
|
-
'> MANDATORY: two teammates NEVER modify the same file — `plan_team_distribution` enforces this.',
|
|
245
|
-
];
|
|
246
|
-
return wrap('team-coordination', lines.join('\n'));
|
|
247
|
-
}
|
|
248
217
|
function buildGitWorkflow(knowledge) {
|
|
249
218
|
const hasConventional = 'commitlint' in knowledge.conventions ||
|
|
250
219
|
(knowledge.conventions['commit-style']?.toLowerCase().includes('conventional') ?? false) ||
|
|
@@ -288,10 +257,6 @@ export function buildProjectSections(knowledge) {
|
|
|
288
257
|
if (gitWorkflow) {
|
|
289
258
|
sections.push(gitWorkflow);
|
|
290
259
|
}
|
|
291
|
-
const teamCoordination = buildTeamCoordinationSection(knowledge);
|
|
292
|
-
if (teamCoordination) {
|
|
293
|
-
sections.push(teamCoordination);
|
|
294
|
-
}
|
|
295
260
|
// SPEC-655: Single hardcoded skill entry point — all others discovered via find-skills
|
|
296
261
|
sections.push(wrap('find-skills', '## Skill Discovery\nUse find-skills to discover available workflows.'));
|
|
297
262
|
// SPEC-755: Spec location preference — overrides brainstorming skill default (docs/superpowers/specs/)
|
|
@@ -21,8 +21,11 @@ import { regeneratePages } from '../../engine/doc-generator/portal/index.js';
|
|
|
21
21
|
import { detectStackPatterns } from './stack-detector.js';
|
|
22
22
|
import { buildProjectConfig } from './config-builder.js';
|
|
23
23
|
import { runSpecMigrations, listProjectSpecs } from './migration-runner.js';
|
|
24
|
-
import { reconcilePortableSpecIndex,
|
|
24
|
+
import { reconcilePortableSpecIndex, buildAlreadyInitializedResult, buildAuthorizedMigrationResult, } from './portable-index-reconciler.js';
|
|
25
25
|
import { refreshCoreHostAssets } from './host-assets-writer.js';
|
|
26
|
+
import { generateWorkflowSkills } from '../../engine/skill-generator/workflow-skill-generator.js';
|
|
27
|
+
import { fileExists } from '../../core/shared/fs.js';
|
|
28
|
+
import { scanLegacyGuidance, summarizeLegacyGuidanceScan } from './legacy-guidance-scanner.js';
|
|
26
29
|
import { runScaffoldWriter } from './scaffold-writer.js';
|
|
27
30
|
import { readAutoInstallFlag, orchestrateSkillInstalls, runHealthCheckWithBaseline, runConventionScanSafe, fireTelemetry, } from './lifecycle-helpers.js';
|
|
28
31
|
import { injectProactiveRules } from '../../engine/claude-md-injector/index.js';
|
|
@@ -31,7 +34,7 @@ import { join } from 'node:path';
|
|
|
31
34
|
import { createHash } from 'node:crypto';
|
|
32
35
|
import { homedir } from 'node:os';
|
|
33
36
|
import { mkdir, stat } from 'node:fs/promises';
|
|
34
|
-
import {
|
|
37
|
+
import { generateWorkflowRulesIfMissing } from './rules-generator.js';
|
|
35
38
|
import { installUniversalRules } from '../../engine/universal-rules/installer.js';
|
|
36
39
|
import { detectHost } from '../../engine/host-detection/detect-host.js';
|
|
37
40
|
import { configurePlanuHooks } from './hooks-configurator.js';
|
|
@@ -223,28 +226,15 @@ export async function handleInitProject(params, server) {
|
|
|
223
226
|
const authorizedMigrations = params.authorizedMigrations ?? [];
|
|
224
227
|
if (isUpdate && authorizedMigrations.length === 0) {
|
|
225
228
|
const reconciliation = await reconcilePortableSpecIndex(projectPath, projectId);
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
projectId,
|
|
236
|
-
...(reconciliation.failures.length === 0 ? { projectPath } : {}),
|
|
237
|
-
isUpdate: true,
|
|
238
|
-
repositoryFilesChanged,
|
|
239
|
-
authorizedMigrations: [],
|
|
240
|
-
importedSpecIds: reconciliation.importedSpecIds,
|
|
241
|
-
failures: reconciliation.failures,
|
|
242
|
-
skippedLegacy: reconciliation.skippedLegacy,
|
|
243
|
-
strayRepoRemovals: reconciliation.strayRepoRemovals,
|
|
244
|
-
migratedLegacyPaths: legacyMigration.migrated,
|
|
245
|
-
},
|
|
246
|
-
...(reconciliation.failures.length > 0 ? { isError: true } : {}),
|
|
247
|
-
};
|
|
229
|
+
const canRefresh = reconciliation.failures.length === 0;
|
|
230
|
+
const legacyGuidanceScan = canRefresh
|
|
231
|
+
? await scanLegacyGuidance(projectPath)
|
|
232
|
+
: { healed: [], warnings: [] };
|
|
233
|
+
const refreshedAssets = canRefresh ? await refreshCoreHostAssets(projectPath) : [];
|
|
234
|
+
const skillSync = canRefresh && existing !== null && (await fileExists(join(projectPath, '.claude/skills')))
|
|
235
|
+
? await generateWorkflowSkills(projectPath, existing).catch(() => null)
|
|
236
|
+
: null;
|
|
237
|
+
return buildAlreadyInitializedResult(projectId, reconciliation, legacyMigration.migrated, refreshedAssets, legacyGuidanceScan, projectPath, skillSync);
|
|
248
238
|
}
|
|
249
239
|
if (isUpdate) {
|
|
250
240
|
if (existing === null) {
|
|
@@ -261,26 +251,8 @@ export async function handleInitProject(params, server) {
|
|
|
261
251
|
const migrationResult = await runSpecMigrations(projectPath, projectId, existing, {
|
|
262
252
|
repositoryMigration: 'planu-spec-format-v1',
|
|
263
253
|
});
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
{
|
|
267
|
-
type: 'text',
|
|
268
|
-
text: migrationResult.criticalMigrationFailures.length === 0
|
|
269
|
-
? 'Authorized planu-spec-format-v1 migration completed.'
|
|
270
|
-
: `Authorized migration completed with ${String(migrationResult.criticalMigrationFailures.length)} blocking issue(s).`,
|
|
271
|
-
},
|
|
272
|
-
],
|
|
273
|
-
structuredContent: {
|
|
274
|
-
projectId,
|
|
275
|
-
projectPath,
|
|
276
|
-
isUpdate: true,
|
|
277
|
-
authorizedMigrations,
|
|
278
|
-
repositoryFilesChanged: migrationResult.changedPaths ?? [],
|
|
279
|
-
migrationReportPath: migrationResult.migrationReportPath,
|
|
280
|
-
criticalMigrationFailures: migrationResult.criticalMigrationFailures,
|
|
281
|
-
},
|
|
282
|
-
...(migrationResult.criticalMigrationFailures.length > 0 ? { isError: true } : {}),
|
|
283
|
-
};
|
|
254
|
+
const legacyGuidanceScan = await scanLegacyGuidance(projectPath).catch(() => ({ healed: [], warnings: [] }));
|
|
255
|
+
return buildAuthorizedMigrationResult(projectId, projectPath, authorizedMigrations, migrationResult, legacyGuidanceScan);
|
|
284
256
|
}
|
|
285
257
|
// Get global config for defaults
|
|
286
258
|
const globalConfig = await globalStore.getGlobalConfig();
|
|
@@ -439,6 +411,7 @@ export async function handleInitProject(params, server) {
|
|
|
439
411
|
// Write scaffold files: rules, git setup, constitution, CLAUDE.md, lint, architecture rules
|
|
440
412
|
const scaffoldResult = await runScaffoldWriter(projectPath, projectId, knowledge, recommendedSkills, params.permissionsMode, params.pluginsMode, autoInstallFromConfig);
|
|
441
413
|
const { platform, generatedRules, rulesWritten, additionalFilesWritten, hooksInstalled, gitFlowType, gitignoreUpdated, gitRepoDetected, layoutOffenders, constitutionInitialized, claudeMdUpdated, eslintCreated, prettierCreated, lintSuggestions, architectureRulesWritten, architectureRulesSkipped, planuWorkflowInjected, planuHooksConfigured, planuRulesWritten, gitAutoStageInjected, } = scaffoldResult;
|
|
414
|
+
const legacyGuidanceScan = await scanLegacyGuidance(projectPath).catch(() => ({ healed: [], warnings: [] }));
|
|
442
415
|
// SPEC-444: Inject proactive behavior rules into project CLAUDE.md
|
|
443
416
|
const proactiveRulesInjected = await injectProactiveRules(join(projectPath, 'CLAUDE.md'), '1.22.0')
|
|
444
417
|
.then(() => true)
|
|
@@ -497,9 +470,6 @@ export async function handleInitProject(params, server) {
|
|
|
497
470
|
// SPEC-200: Anonymous opt-in telemetry — fire-and-forget, never blocks response
|
|
498
471
|
const neverPrompted = await fireTelemetry(knowledge).catch(() => false);
|
|
499
472
|
// SPEC-457: Auto-bootstrap rules, hooks, skills for detected stack (fire-and-forget)
|
|
500
|
-
void withAudit(projectPath, 'init_project', 'generateAgentTeamsRulesIfMissing', () => generateAgentTeamsRulesIfMissing(projectPath)).catch(() => {
|
|
501
|
-
/* best-effort */
|
|
502
|
-
});
|
|
503
473
|
void withAudit(projectPath, 'init_project', 'generateWorkflowRulesIfMissing', () => generateWorkflowRulesIfMissing(projectPath)).catch(() => {
|
|
504
474
|
/* best-effort */
|
|
505
475
|
});
|
|
@@ -561,6 +531,7 @@ export async function handleInitProject(params, server) {
|
|
|
561
531
|
if (skillsAutoInstalled.length > 0) {
|
|
562
532
|
collector.pushOk('skills-installed', `Auto-installed skills: ${skillsAutoInstalled.join(', ')}`);
|
|
563
533
|
}
|
|
534
|
+
summarizeLegacyGuidanceScan(collector, legacyGuidanceScan);
|
|
564
535
|
const toolResult = buildInitProjectResult({
|
|
565
536
|
projectId,
|
|
566
537
|
projectPath,
|
|
@@ -620,8 +591,12 @@ export async function handleInitProject(params, server) {
|
|
|
620
591
|
branchInfo,
|
|
621
592
|
});
|
|
622
593
|
if (toolResult.structuredContent) {
|
|
623
|
-
toolResult.structuredContent
|
|
624
|
-
|
|
594
|
+
Object.assign(toolResult.structuredContent, {
|
|
595
|
+
repositoryFilesChanged: [...migrationChangedPaths, ...legacyGuidanceScan.healed],
|
|
596
|
+
authorizedMigrations,
|
|
597
|
+
legacyGuidanceHealed: legacyGuidanceScan.healed,
|
|
598
|
+
legacyGuidanceWarnings: legacyGuidanceScan.warnings,
|
|
599
|
+
});
|
|
625
600
|
}
|
|
626
601
|
// Inject autopilotSummary into structuredContent
|
|
627
602
|
if (collector.hasEntries() && toolResult.structuredContent) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AutopilotSummaryCollector } from '../../engine/autopilot/summary-collector.js';
|
|
2
|
+
import type { LegacyGuidanceScanResult } from '../../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Scan the bounded set of Planu-installed host guidance surfaces for stale
|
|
5
|
+
* directives that contradict the current spec.md-only contract, and
|
|
6
|
+
* neutralize what can be neutralized fail-closed. Never touches files
|
|
7
|
+
* outside the inventoried scan surface (no repo-wide walk).
|
|
8
|
+
*/
|
|
9
|
+
export declare function scanLegacyGuidance(projectPath: string): Promise<LegacyGuidanceScanResult>;
|
|
10
|
+
/** Records a legacy-guidance scan outcome onto an init_project autopilot summary. */
|
|
11
|
+
export declare function summarizeLegacyGuidanceScan(collector: AutopilotSummaryCollector, scan: LegacyGuidanceScanResult): void;
|
|
12
|
+
//# sourceMappingURL=legacy-guidance-scanner.d.ts.map
|