@planu/cli 5.7.5 → 5.7.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.
- package/CHANGELOG.md +88 -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-review-panel-trigger.sh +2 -3
- 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/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 +8 -12
- 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/evidence-skeletons.js +3 -1
- 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 +43 -5
- 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 +32 -12
- 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.d.ts +3 -3
- package/dist/engine/spec-grounding/contract.js +65 -4
- package/dist/engine/spec-grounding/grounding-entry-parser.d.ts +5 -0
- package/dist/engine/spec-grounding/grounding-entry-parser.js +185 -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/storage/spec-store.js +8 -1
- package/dist/tools/bump-spec-version.js +5 -5
- 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/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 +7 -5
- 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 +2 -1
- package/dist/tools/init-project/portable-index-reconciler.js +7 -2
- 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/init-project/skills-multi-teammate-review-writer.js +1 -1
- 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/multi-teammate-review.js +1 -14
- 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-platform-tools/design-stack-tools.js +3 -3
- package/dist/tools/register-sdd-tools.js +0 -23
- package/dist/tools/register-spec-tools/analysis-tools.js +22 -9
- package/dist/tools/register-spec-tools/core-spec-tools.js +115 -70
- 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 +72 -164
- package/dist/tools/tool-registry/group-infra.js +2 -39
- package/dist/tools/tool-registry/group-quality-compliance.js +20 -15
- package/dist/tools/tool-registry-helpers.js +6 -2
- 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/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 +26 -0
- 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
- package/dist/tools/tool-registry/deprecated-stubs.d.ts +0 -19
- package/dist/tools/tool-registry/deprecated-stubs.js +0 -65
package/dist/tools/validate.js
CHANGED
|
@@ -162,10 +162,15 @@ export async function handleValidate(args) {
|
|
|
162
162
|
},
|
|
163
163
|
};
|
|
164
164
|
}
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
const knowledge = await knowledgeStore.getKnowledge(projectId);
|
|
166
|
+
if (!knowledge) {
|
|
167
|
+
return {
|
|
168
|
+
content: [{ type: 'text', text: t('project.notFound') }],
|
|
169
|
+
isError: true,
|
|
170
|
+
structuredContent: { error: 'project_not_found', code: 404, context: { projectId } },
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
const spec = await specStore.getSpec(projectId, args.specId, knowledge.projectPath);
|
|
169
174
|
if (!spec) {
|
|
170
175
|
return {
|
|
171
176
|
content: [{ type: 'text', text: ti('spec.notFound', { id: args.specId }) }],
|
|
@@ -177,13 +182,6 @@ export async function handleValidate(args) {
|
|
|
177
182
|
},
|
|
178
183
|
};
|
|
179
184
|
}
|
|
180
|
-
if (!knowledge) {
|
|
181
|
-
return {
|
|
182
|
-
content: [{ type: 'text', text: t('project.notFound') }],
|
|
183
|
-
isError: true,
|
|
184
|
-
structuredContent: { error: 'project_not_found', code: 404, context: { projectId } },
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
185
|
let validationWorktree;
|
|
188
186
|
try {
|
|
189
187
|
validationWorktree = await resolveValidationWorktree({
|
|
@@ -259,6 +257,11 @@ function validationWorktreeErrorResult(error, specId) {
|
|
|
259
257
|
specId: failure.specId,
|
|
260
258
|
...(failure.relativeSpecPath ? { path: failure.relativeSpecPath } : {}),
|
|
261
259
|
},
|
|
260
|
+
...(failure.code === 'VALIDATION_STALE_SPEC_PATH'
|
|
261
|
+
? {
|
|
262
|
+
fixHint: `The spec registry still points at a stale checkout for ${failure.relativeSpecPath ?? 'this spec'}. Re-run validate from the canonical checkout (or call list_specs against the canonical projectPath) to self-heal the registry entry, then retry.`,
|
|
263
|
+
}
|
|
264
|
+
: {}),
|
|
262
265
|
},
|
|
263
266
|
};
|
|
264
267
|
}
|
|
@@ -281,27 +284,30 @@ async function acquireValidationSubmissionLock(projectId, specId) {
|
|
|
281
284
|
}
|
|
282
285
|
function validationAcceptedResult(job, projectId, runtime, { justCreated }) {
|
|
283
286
|
const observation = runtime.observe(job);
|
|
287
|
+
const reused = !justCreated;
|
|
284
288
|
const accepted = {
|
|
285
289
|
schemaVersion: 1,
|
|
286
290
|
operationId: job.id,
|
|
287
291
|
projectId,
|
|
288
292
|
workspaceId: job.workspaceId,
|
|
289
293
|
state: job.state,
|
|
290
|
-
submittedAt: job.createdAt,
|
|
291
|
-
attachedAt: justCreated ? job.
|
|
294
|
+
submittedAt: justCreated ? job.updatedAt : job.createdAt,
|
|
295
|
+
attachedAt: justCreated ? job.updatedAt : new Date().toISOString(),
|
|
296
|
+
reused,
|
|
292
297
|
cursor: publicJobCursor(observation),
|
|
293
298
|
queue: observation.queue,
|
|
294
299
|
terminalStates: ['completed', 'failed', 'cancelled', 'dead-letter'],
|
|
295
300
|
resultSchema: 'validate-completion/v1',
|
|
296
301
|
observation: {
|
|
297
302
|
get: 'get_job',
|
|
298
|
-
watch: 'watch_job',
|
|
299
|
-
cancel: 'cancel_job',
|
|
300
303
|
restart: 'restart_job',
|
|
301
304
|
},
|
|
302
305
|
};
|
|
306
|
+
const text = reused
|
|
307
|
+
? `Attached to already-running validation job ${job.id}; no new work was scheduled. Follow it with get_job. To force re-execution after it reaches a terminal state, run validate again.`
|
|
308
|
+
: `Validation accepted as durable job ${job.id}.`;
|
|
303
309
|
return {
|
|
304
|
-
content: [{ type: 'text', text
|
|
310
|
+
content: [{ type: 'text', text }],
|
|
305
311
|
structuredContent: accepted,
|
|
306
312
|
};
|
|
307
313
|
}
|
|
@@ -313,29 +319,29 @@ export async function executeValidate(args, server, onProgress) {
|
|
|
313
319
|
if (!projectId) {
|
|
314
320
|
return missingProjectIdError;
|
|
315
321
|
}
|
|
316
|
-
const
|
|
317
|
-
if (!
|
|
322
|
+
const knowledge = await knowledgeStore.getKnowledge(projectId);
|
|
323
|
+
if (!knowledge) {
|
|
318
324
|
return {
|
|
319
|
-
content: [{ type: 'text', text:
|
|
325
|
+
content: [{ type: 'text', text: t('project.notFound') }],
|
|
320
326
|
isError: true,
|
|
321
327
|
structuredContent: {
|
|
322
|
-
error: '
|
|
328
|
+
error: 'project_not_found',
|
|
323
329
|
code: 404,
|
|
324
|
-
context: {
|
|
325
|
-
fixHint:
|
|
330
|
+
context: { projectId },
|
|
331
|
+
fixHint: 'Run init_project first to initialize the project knowledge.',
|
|
326
332
|
},
|
|
327
333
|
};
|
|
328
334
|
}
|
|
329
|
-
const
|
|
330
|
-
if (!
|
|
335
|
+
const spec = await specStore.getSpec(projectId, specId, knowledge.projectPath);
|
|
336
|
+
if (!spec) {
|
|
331
337
|
return {
|
|
332
|
-
content: [{ type: 'text', text:
|
|
338
|
+
content: [{ type: 'text', text: ti('spec.notFound', { id: specId }) }],
|
|
333
339
|
isError: true,
|
|
334
340
|
structuredContent: {
|
|
335
|
-
error: '
|
|
341
|
+
error: 'spec_not_found',
|
|
336
342
|
code: 404,
|
|
337
|
-
context: { projectId },
|
|
338
|
-
fixHint:
|
|
343
|
+
context: { specId, projectId },
|
|
344
|
+
fixHint: `Verify the specId is correct and the spec exists in project ${projectId}.`,
|
|
339
345
|
},
|
|
340
346
|
};
|
|
341
347
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// 1. API key (SDD_OAUTH_API_KEY) — simplest: token must match env var
|
|
4
4
|
// 2. HMAC-signed JWT (SDD_OAUTH_JWT_SECRET) — validates HS256 JWT signature
|
|
5
5
|
// Configure via environment variables — no accounts or external services needed.
|
|
6
|
+
import { timingSafeEqual } from 'node:crypto';
|
|
6
7
|
export function loadOAuthConfig() {
|
|
7
8
|
const apiKey = process.env.SDD_OAUTH_API_KEY;
|
|
8
9
|
const jwtSecret = process.env.SDD_OAUTH_JWT_SECRET;
|
|
@@ -32,13 +33,23 @@ export async function validateToken(token, config) {
|
|
|
32
33
|
return { valid: true };
|
|
33
34
|
}
|
|
34
35
|
if (config.mode === 'api-key') {
|
|
35
|
-
return token
|
|
36
|
+
return isMatchingApiKey(token, config.apiKey ?? '')
|
|
37
|
+
? { valid: true }
|
|
38
|
+
: { valid: false, reason: 'Invalid API key' };
|
|
36
39
|
}
|
|
37
40
|
if (config.mode === 'jwt-hmac') {
|
|
38
41
|
return validateHmacJwt(token, config);
|
|
39
42
|
}
|
|
40
43
|
return { valid: false, reason: 'Unknown auth mode' };
|
|
41
44
|
}
|
|
45
|
+
function isMatchingApiKey(token, apiKey) {
|
|
46
|
+
const tokenBuffer = Buffer.from(token);
|
|
47
|
+
const apiKeyBuffer = Buffer.from(apiKey);
|
|
48
|
+
if (tokenBuffer.byteLength !== apiKeyBuffer.byteLength) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return timingSafeEqual(tokenBuffer, apiKeyBuffer);
|
|
52
|
+
}
|
|
42
53
|
// Validate HS256 JWT using Node.js built-in crypto (no external deps).
|
|
43
54
|
async function validateHmacJwt(token, config) {
|
|
44
55
|
const parts = token.split('.');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import type { TransportConfig } from '../types/index.js';
|
|
2
|
+
import type { TransportConfig, OAuthConfig } from '../types/index.js';
|
|
3
3
|
export declare function parseTransportConfig(args: string[]): TransportConfig;
|
|
4
|
+
export declare function assertHttpExposureAllowed(config: TransportConfig, oauth: OAuthConfig): void;
|
|
4
5
|
export declare function selectTransport(server: McpServer, args: string[], serverFactory?: () => McpServer): Promise<void>;
|
|
5
6
|
//# sourceMappingURL=transport-factory.d.ts.map
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { execFileSync } from 'node:child_process';
|
|
4
4
|
import { createHttpTransport } from './http-transport.js';
|
|
5
|
+
import { loadOAuthConfig } from './oauth-validator.js';
|
|
5
6
|
import { compactToolsListMessage, isToolsListResponse, } from '../engine/compact/tool-list-compactor.js';
|
|
6
7
|
import { reportClassifiedDegradation } from '../errors/classified-degradation.js';
|
|
7
8
|
const VALID_TRANSPORTS = ['stdio', 'http'];
|
|
@@ -84,8 +85,25 @@ export function parseTransportConfig(args) {
|
|
|
84
85
|
port,
|
|
85
86
|
host: getFlag(args, 'host') ?? process.env.HOST ?? DEFAULT_HOST,
|
|
86
87
|
corsOrigin: getFlag(args, 'cors-origin') ?? process.env.CORS_ORIGIN,
|
|
88
|
+
insecure: args.includes('--insecure'),
|
|
87
89
|
};
|
|
88
90
|
}
|
|
91
|
+
const LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost']);
|
|
92
|
+
function isLoopbackHost(host) {
|
|
93
|
+
return LOOPBACK_HOSTS.has(host);
|
|
94
|
+
}
|
|
95
|
+
export function assertHttpExposureAllowed(config, oauth) {
|
|
96
|
+
if (config.transport !== 'http' || isLoopbackHost(config.host) || oauth.enabled) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (config.insecure) {
|
|
100
|
+
console.error(`[Planu] WARNING: running UNAUTHENTICATED on non-loopback host "${config.host}" because --insecure was passed.`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
console.error(`[Planu] Refusing to start: HTTP transport on non-loopback host "${config.host}" has no authentication configured. ` +
|
|
104
|
+
'Set SDD_OAUTH_API_KEY or SDD_OAUTH_JWT_SECRET, or pass --insecure to bypass this at your own risk.');
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
89
107
|
export async function selectTransport(server, args, serverFactory) {
|
|
90
108
|
const config = parseTransportConfig(args);
|
|
91
109
|
if (config.transport === 'stdio') {
|
|
@@ -102,6 +120,7 @@ export async function selectTransport(server, args, serverFactory) {
|
|
|
102
120
|
return;
|
|
103
121
|
}
|
|
104
122
|
// HTTP mode: each session needs its own McpServer instance
|
|
123
|
+
assertHttpExposureAllowed(config, loadOAuthConfig());
|
|
105
124
|
const factory = serverFactory ?? (() => server);
|
|
106
125
|
await createHttpTransport(factory, config);
|
|
107
126
|
}
|
|
@@ -3,6 +3,8 @@ export type Difficulty = 1 | 2 | 3 | 4 | 5;
|
|
|
3
3
|
export type RiskLevel = 'low' | 'medium' | 'high' | 'critical';
|
|
4
4
|
export type SupportedLocale = 'en' | 'es' | 'pt';
|
|
5
5
|
export type ExperienceLevel = 'beginner' | 'intermediate' | 'expert';
|
|
6
|
+
/** SDD model tier evidence for lifecycle transitions. */
|
|
7
|
+
export type ModelTierUsed = 'max' | 'implementation' | 'review';
|
|
6
8
|
/** SPEC-313: Preferred interaction style with Planu (stored in planu.json) */
|
|
7
9
|
export type WorkMode = 'guided' | 'standard' | 'expert';
|
|
8
10
|
export type SpecType = 'feature' | 'refactor' | 'bugfix' | 'infra' | 'docs' | 'project' | 'agent' | 'tech-debt';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ValidationArtifactDigests, ValidationFreshnessLease } from './validation-receipt.js';
|
|
2
|
+
import type { HandoffPackage } from './readiness.js';
|
|
2
3
|
export interface DurableJobIdentity {
|
|
3
4
|
readonly operationId: string;
|
|
4
5
|
readonly projectId: string;
|
|
@@ -35,6 +36,50 @@ export interface ValidateDurableJobPayload {
|
|
|
35
36
|
readonly freshnessLease?: ValidationFreshnessLease;
|
|
36
37
|
readonly specPath: string;
|
|
37
38
|
}
|
|
39
|
+
export interface PackageHandoffDurableJobPayload {
|
|
40
|
+
readonly kind: 'package-handoff';
|
|
41
|
+
readonly schemaVersion: 1;
|
|
42
|
+
readonly projectId: string;
|
|
43
|
+
readonly specId: string;
|
|
44
|
+
readonly specVersion: string;
|
|
45
|
+
}
|
|
46
|
+
/** Outcome of one deadline-bounded package-handoff stage execution. */
|
|
47
|
+
export interface PackageHandoffStageOutcome<T> {
|
|
48
|
+
readonly ok: boolean;
|
|
49
|
+
readonly value?: T;
|
|
50
|
+
readonly timedOut: boolean;
|
|
51
|
+
readonly error?: unknown;
|
|
52
|
+
}
|
|
53
|
+
export interface PackageHandoffStageResult<T> {
|
|
54
|
+
readonly stage: string;
|
|
55
|
+
readonly durationMs: number;
|
|
56
|
+
readonly outcome: PackageHandoffStageOutcome<T>;
|
|
57
|
+
}
|
|
58
|
+
export interface PackageHandoffDegradation {
|
|
59
|
+
readonly stage: string;
|
|
60
|
+
readonly code: 'HANDOFF_ENRICHMENT_TIMEOUT' | 'HANDOFF_ENRICHMENT_FAILURE' | 'HANDOFF_STALE_VERSION_SKIPPED';
|
|
61
|
+
readonly remediation: string;
|
|
62
|
+
}
|
|
63
|
+
export interface PackageHandoffCoreStageOutput {
|
|
64
|
+
readonly readinessScore: number;
|
|
65
|
+
readonly pkg: HandoffPackage & {
|
|
66
|
+
readonly staleVersionSkipped?: boolean;
|
|
67
|
+
};
|
|
68
|
+
readonly stageTimings: Record<string, number>;
|
|
69
|
+
}
|
|
70
|
+
export interface PackageHandoffEnrichmentOutput {
|
|
71
|
+
readonly pkgWithConstraints: HandoffPackage;
|
|
72
|
+
readonly graphContext: {
|
|
73
|
+
text: string;
|
|
74
|
+
structured: unknown;
|
|
75
|
+
} | null;
|
|
76
|
+
readonly minimalityBlocked: boolean | null;
|
|
77
|
+
readonly minimalitySummary: Record<string, unknown> | undefined;
|
|
78
|
+
readonly tokenWasteRiskCount: number | null;
|
|
79
|
+
readonly tokenWasteSummary: Record<string, unknown> | undefined;
|
|
80
|
+
readonly stageTimings: Record<string, number>;
|
|
81
|
+
readonly degradations: readonly PackageHandoffDegradation[];
|
|
82
|
+
}
|
|
38
83
|
export declare const DURABLE_JOB_STATES: readonly ['accepted', 'running', 'checkpointed', 'cancelled', 'failed', 'dead-letter', 'completed'];
|
|
39
84
|
export type DurableJobState = (typeof DURABLE_JOB_STATES)[number];
|
|
40
85
|
export interface DurableJobRecord {
|
|
@@ -9,7 +9,7 @@ export interface DurableValidationBindings {
|
|
|
9
9
|
readonly policyHash: string;
|
|
10
10
|
readonly toolchainHash: string;
|
|
11
11
|
}
|
|
12
|
-
export type ValidationWorktreeErrorCode = 'VALIDATION_PAYLOAD_VERSION_UNSUPPORTED' | 'VALIDATION_ROOT_ID_MALFORMED' | 'VALIDATION_ROOT_ID_MISMATCH' | 'VALIDATION_ROOT_BUSY' | 'VALIDATION_ROOT_NOT_GIT_WORKTREE' | 'VALIDATION_COMMON_DIR_MISMATCH' | 'VALIDATION_SPEC_PATH_TRAVERSAL' | 'VALIDATION_SPEC_PATH_SYMLINK' | 'VALIDATION_SPEC_NOT_FOUND' | 'VALIDATION_SPEC_ID_MISMATCH';
|
|
12
|
+
export type ValidationWorktreeErrorCode = 'VALIDATION_PAYLOAD_VERSION_UNSUPPORTED' | 'VALIDATION_ROOT_ID_MALFORMED' | 'VALIDATION_ROOT_ID_MISMATCH' | 'VALIDATION_ROOT_BUSY' | 'VALIDATION_ROOT_NOT_GIT_WORKTREE' | 'VALIDATION_COMMON_DIR_MISMATCH' | 'VALIDATION_SPEC_PATH_TRAVERSAL' | 'VALIDATION_STALE_SPEC_PATH' | 'VALIDATION_SPEC_PATH_SYMLINK' | 'VALIDATION_SPEC_NOT_FOUND' | 'VALIDATION_SPEC_ID_MISMATCH';
|
|
13
13
|
export interface ResolvedValidationWorktree {
|
|
14
14
|
readonly projectPath: string;
|
|
15
15
|
readonly gitCommonDir: string;
|
|
@@ -28,9 +28,21 @@ export type AutofillTraceabilityMatrixResult = {
|
|
|
28
28
|
written: true;
|
|
29
29
|
path: string;
|
|
30
30
|
rowCount: number;
|
|
31
|
+
reason?: 'regenerated-stale';
|
|
31
32
|
} | {
|
|
32
33
|
written: false;
|
|
33
|
-
reason: 'already-exists' | 'no-criteria' | 'write-failed';
|
|
34
|
+
reason: 'already-exists-manual' | 'already-exists-current' | 'no-criteria' | 'write-failed';
|
|
34
35
|
error?: string;
|
|
35
36
|
};
|
|
37
|
+
/** Classification of an on-disk traceability-matrix.json relative to the
|
|
38
|
+
* generator's own prose templates: absent, hand-written/mixed/unparseable
|
|
39
|
+
* ("manual" — never touched), or autofill-shaped and safe to regenerate. */
|
|
40
|
+
export type ExistingMatrixLookup = {
|
|
41
|
+
kind: 'absent';
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'manual';
|
|
44
|
+
} | {
|
|
45
|
+
kind: 'autofill-shaped';
|
|
46
|
+
raw: string;
|
|
47
|
+
};
|
|
36
48
|
//# sourceMappingURL=evidence-autofill.d.ts.map
|
|
@@ -48,6 +48,7 @@ export interface ImplementationReviewV1 {
|
|
|
48
48
|
kind: 'implementation-review-agent' | 'human';
|
|
49
49
|
agent: string;
|
|
50
50
|
verdict: 'approved' | 'changes-requested';
|
|
51
|
+
sessionId?: string;
|
|
51
52
|
};
|
|
52
53
|
blockers: string[];
|
|
53
54
|
suggestions: string[];
|
|
@@ -147,7 +148,7 @@ export interface ArtifactPayloadMap {
|
|
|
147
148
|
}
|
|
148
149
|
export type ArtifactPayload<K extends ArtifactKind> = ArtifactPayloadMap[K];
|
|
149
150
|
import type { MinimalImplementationReport } from './minimal-implementation-gate.js';
|
|
150
|
-
export type ImplementationReviewRejectionReason = 'missing' | 'unreadable' | 'schema_invalid' | 'stub_body' | 'wrong_agent_or_kind' | 'not_approved' | 'self_review' | 'actor_unreadable' | 'wrong_spec';
|
|
151
|
+
export type ImplementationReviewRejectionReason = 'missing' | 'unreadable' | 'schema_invalid' | 'stub_body' | 'wrong_agent_or_kind' | 'not_approved' | 'self_review' | 'actor_unreadable' | 'wrong_spec' | 'identity_unverifiable';
|
|
151
152
|
export interface VerifiedImplementationReviewOk {
|
|
152
153
|
ok: true;
|
|
153
154
|
review: ImplementationReviewV1;
|
|
@@ -63,8 +63,15 @@ export interface AmbiguityReport {
|
|
|
63
63
|
violations: AmbiguityViolation[];
|
|
64
64
|
blockers: string[];
|
|
65
65
|
}
|
|
66
|
+
/** Version fence for the durable executor: skip publishing a stale-version artifact. */
|
|
67
|
+
export interface HandoffVersionFence {
|
|
68
|
+
readonly specVersion: string;
|
|
69
|
+
readonly getCurrentSpecVersion: () => Promise<string | undefined>;
|
|
70
|
+
readonly signal?: AbortSignal;
|
|
71
|
+
}
|
|
66
72
|
export interface PackageHandoffInput {
|
|
67
|
-
projectId
|
|
73
|
+
projectId?: string;
|
|
74
|
+
projectPath?: string;
|
|
68
75
|
specId: string;
|
|
69
76
|
}
|
|
70
77
|
/**
|
|
@@ -26,6 +26,12 @@ export interface SectionBounds {
|
|
|
26
26
|
start: number;
|
|
27
27
|
end: number;
|
|
28
28
|
}
|
|
29
|
+
export type AppliedSections = ReadonlySet<string>;
|
|
30
|
+
export interface ParsedFilesSection {
|
|
31
|
+
create: string[];
|
|
32
|
+
modify: string[];
|
|
33
|
+
test: string[];
|
|
34
|
+
}
|
|
29
35
|
export interface CurrentStatus {
|
|
30
36
|
totalSpecs: number;
|
|
31
37
|
content: Record<string, unknown>;
|
|
@@ -398,9 +398,34 @@ export interface WorkflowSkillGenerationOptions {
|
|
|
398
398
|
export interface WorkflowSkillGenerationResult {
|
|
399
399
|
/** Skill names that were written (new or updated). */
|
|
400
400
|
written: string[];
|
|
401
|
-
/** Skill names that were skipped (
|
|
401
|
+
/** Skill names that were skipped (content unchanged). */
|
|
402
402
|
skipped: string[];
|
|
403
|
+
/** Skill names left untouched because the on-disk file was user-authored or user-edited. */
|
|
404
|
+
userModified: string[];
|
|
403
405
|
/** Any non-fatal errors (skill name → error message). */
|
|
404
406
|
errors: Record<string, string>;
|
|
405
407
|
}
|
|
408
|
+
/** Fail-closed result of reading the hash marker from an on-disk skill file. */
|
|
409
|
+
export type MarkerReadResult = {
|
|
410
|
+
kind: 'absent';
|
|
411
|
+
} | {
|
|
412
|
+
kind: 'invalid';
|
|
413
|
+
} | {
|
|
414
|
+
kind: 'legacy';
|
|
415
|
+
} | {
|
|
416
|
+
kind: 'current';
|
|
417
|
+
hash: string;
|
|
418
|
+
lineIndex: number;
|
|
419
|
+
};
|
|
420
|
+
/** Per-file write decision made by generateWorkflowSkills for one skill definition. */
|
|
421
|
+
export type SkillFileDecision = {
|
|
422
|
+
action: 'write';
|
|
423
|
+
} | {
|
|
424
|
+
action: 'skip-unchanged';
|
|
425
|
+
} | {
|
|
426
|
+
action: 'skip-user-modified';
|
|
427
|
+
} | {
|
|
428
|
+
action: 'skip-error';
|
|
429
|
+
message: string;
|
|
430
|
+
};
|
|
406
431
|
//# sourceMappingURL=skill-registry.d.ts.map
|
|
@@ -435,6 +435,11 @@ export interface SyncDivergence {
|
|
|
435
435
|
yamlStatus: string;
|
|
436
436
|
dataStatus: string;
|
|
437
437
|
}
|
|
438
|
+
/** Options controlling how syncSpecState reconciles divergences. */
|
|
439
|
+
export interface SyncSpecStateOptions {
|
|
440
|
+
/** When false, non-terminal drift is reported read-only instead of applied via handleUpdateStatus. */
|
|
441
|
+
applyTransitions?: boolean;
|
|
442
|
+
}
|
|
438
443
|
/** Report produced by spec state synchronisation. */
|
|
439
444
|
export interface SyncReport {
|
|
440
445
|
synced: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SpecStatus, SpecType, SpecScope, SpecTarget, ToolResult } from '../common/index.js';
|
|
1
|
+
import type { ModelTierUsed, SpecStatus, SpecType, SpecScope, SpecTarget, ToolResult } from '../common/index.js';
|
|
2
2
|
import type { Actuals } from '../estimation.js';
|
|
3
3
|
import type { GlobalConfig } from '../project/config-metrics.js';
|
|
4
4
|
import type { ProjectKnowledge } from '../project.js';
|
|
@@ -58,7 +58,7 @@ export interface UpdateStatusInput {
|
|
|
58
58
|
* - implementation: lower/intermediate implementer tier
|
|
59
59
|
* - review: reviewer tier
|
|
60
60
|
*/
|
|
61
|
-
modelTierUsed?:
|
|
61
|
+
modelTierUsed?: ModelTierUsed;
|
|
62
62
|
/** SHA-256 hash of the persisted context package used for this transition. */
|
|
63
63
|
contextHash?: string;
|
|
64
64
|
/** Path to the persisted handoff artifact generated by package_handoff. */
|
|
@@ -1,6 +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
|
+
import type { ModelTierUsed, SpecStatus } from './common/index.js';
|
|
4
4
|
import type { CriterionGroundingRecord, TechnicalReferenceGroundingRecord } from './spec-grounding.js';
|
|
5
5
|
/** A criterion in the lean spec frontmatter. */
|
|
6
6
|
export interface LeanCriterion {
|
|
@@ -110,6 +110,15 @@ export interface LegacyMigrationDirective {
|
|
|
110
110
|
legacyFiles: LegacyArtifactHit[];
|
|
111
111
|
directive: 'migrate_legacy_spec';
|
|
112
112
|
}
|
|
113
|
+
export interface UpdateStatusBatchEvidence {
|
|
114
|
+
modelTierUsed?: ModelTierUsed;
|
|
115
|
+
modelId?: string;
|
|
116
|
+
contextHash?: string;
|
|
117
|
+
handoffPath?: string;
|
|
118
|
+
handoffArtifactId?: string;
|
|
119
|
+
reviewedBy?: string;
|
|
120
|
+
arbitratedBy?: string;
|
|
121
|
+
}
|
|
113
122
|
export interface UpdateStatusBatchInput {
|
|
114
123
|
specIds: string[];
|
|
115
124
|
status: Exclude<SpecStatus, 'done'>;
|
|
@@ -117,6 +126,7 @@ export interface UpdateStatusBatchInput {
|
|
|
117
126
|
projectPath?: string;
|
|
118
127
|
dryRun?: boolean;
|
|
119
128
|
reviewNotes?: string;
|
|
129
|
+
evidence?: Record<string, UpdateStatusBatchEvidence>;
|
|
120
130
|
}
|
|
121
131
|
/** Report of detected migration drift (SPEC-715). Read-only — no FS mutations. */
|
|
122
132
|
export interface MigrationDriftReport {
|
|
@@ -19,4 +19,30 @@ export interface GroundingGateResult {
|
|
|
19
19
|
issues: string[];
|
|
20
20
|
records: CriterionGroundingRecord[];
|
|
21
21
|
}
|
|
22
|
+
export interface RawGroundingFrontmatter {
|
|
23
|
+
grounding?: {
|
|
24
|
+
criteria?: unknown;
|
|
25
|
+
technicalReferences?: unknown;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export type FrontmatterYamlOutcome = {
|
|
29
|
+
parsed: true;
|
|
30
|
+
document: Record<string, unknown> | undefined;
|
|
31
|
+
} | {
|
|
32
|
+
parsed: false;
|
|
33
|
+
};
|
|
34
|
+
export interface GroundingParseDiagnostic {
|
|
35
|
+
identifier: string;
|
|
36
|
+
field: string;
|
|
37
|
+
value: string;
|
|
38
|
+
allowed: string[];
|
|
39
|
+
}
|
|
40
|
+
export interface GroundingParseResult<T> {
|
|
41
|
+
records: T[];
|
|
42
|
+
diagnostics: GroundingParseDiagnostic[];
|
|
43
|
+
}
|
|
44
|
+
export interface GroundingEntryOutcome<T> {
|
|
45
|
+
record: T | null;
|
|
46
|
+
diagnostics: GroundingParseDiagnostic[];
|
|
47
|
+
}
|
|
22
48
|
//# sourceMappingURL=spec-grounding.d.ts.map
|
|
@@ -15,6 +15,16 @@ export interface ValidationArtifactDigests {
|
|
|
15
15
|
readonly traceability: string;
|
|
16
16
|
readonly contractValidation: string;
|
|
17
17
|
}
|
|
18
|
+
export interface ValidationArtifactProvenanceWriteResult {
|
|
19
|
+
readonly writtenPaths: readonly string[];
|
|
20
|
+
readonly absentArtifacts: readonly string[];
|
|
21
|
+
}
|
|
22
|
+
export interface PerFileArtifactSentinel {
|
|
23
|
+
readonly name: string;
|
|
24
|
+
readonly digestValue: string;
|
|
25
|
+
readonly sentinel: string;
|
|
26
|
+
readonly payloadFile?: string;
|
|
27
|
+
}
|
|
18
28
|
export interface ValidationArtifactProvenance {
|
|
19
29
|
readonly receiptId: string;
|
|
20
30
|
/** Digest of canonical artifact content excluding this provenance envelope. */
|
|
@@ -28,6 +38,23 @@ export interface ValidationFreshnessLease {
|
|
|
28
38
|
readonly epoch: string;
|
|
29
39
|
readonly generation: number;
|
|
30
40
|
}
|
|
41
|
+
export type ValidationFreshnessBarrierReason = 'lease-superseded' | 'invalidation-drain-failed' | 'evidence-check-failed' | 'evidence-changed' | 'source-changed' | 'source-check-failed' | 'state-lost' | 'lease-expired' | 'bindings-mismatch';
|
|
42
|
+
export type ValidationFreshnessBarrierResult = {
|
|
43
|
+
readonly fresh: true;
|
|
44
|
+
} | {
|
|
45
|
+
readonly fresh: false;
|
|
46
|
+
readonly reason: ValidationFreshnessBarrierReason;
|
|
47
|
+
readonly changedInput?: string;
|
|
48
|
+
};
|
|
49
|
+
export type ValidationFreshnessRebaselineReason = 'lease-expired' | 'recompute-failed' | 'bindings-mismatch' | 'lease-unstable';
|
|
50
|
+
export type ValidationFreshnessRebaselineResult = {
|
|
51
|
+
readonly lease: ValidationFreshnessLease;
|
|
52
|
+
} | {
|
|
53
|
+
readonly rejection: {
|
|
54
|
+
readonly reason: ValidationFreshnessRebaselineReason;
|
|
55
|
+
readonly changedInput?: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
31
58
|
/**
|
|
32
59
|
* Classification of one raw filesystem watcher event feeding the freshness
|
|
33
60
|
* barrier: a direct relevant/ignored child path, a synthetic root event (the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planu/cli",
|
|
3
|
-
"version": "5.7.
|
|
3
|
+
"version": "5.7.7",
|
|
4
4
|
"description": "Planu — MCP Server for Spec Driven Development. Cross-platform (Linux/macOS/Windows, x64/arm64).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"LICENSE"
|
|
21
21
|
],
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=
|
|
23
|
+
"node": ">=22.13.0"
|
|
24
24
|
},
|
|
25
25
|
"packageManager": "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b",
|
|
26
26
|
"scripts": {
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"test:watch": "vitest",
|
|
49
49
|
"test:coverage": "vitest run --coverage --testTimeout=60000 --maxWorkers=4",
|
|
50
50
|
"test:release-gate": "vitest run --exclude 'tests/integration/**'",
|
|
51
|
+
"test:pre-push-scripts": "PLANU_PRE_PUSH_SCRIPTS_LANE=1 vitest run tests/scripts --reporter=dot",
|
|
51
52
|
"test:integration": "vitest run tests/integration",
|
|
52
53
|
"test:website:unit": "vitest run tests/website tests/scripts/generate-website-proof.test.ts tests/scripts/website-tool-counts.test.ts",
|
|
53
54
|
"test:website:browser": "playwright test --config playwright.website.config.ts",
|
package/planu-plugin.json
CHANGED
|
@@ -2,44 +2,31 @@
|
|
|
2
2
|
"name": "dev.planu.cli",
|
|
3
3
|
"displayName": "Planu — Spec Driven Development",
|
|
4
4
|
"description": "Manage software specs, estimations, and autonomous SDD workflows. Language-agnostic MCP server for Claude Code.",
|
|
5
|
-
"version": "5.7.
|
|
5
|
+
"version": "5.7.7",
|
|
6
6
|
"icon": "assets/plugin/icon.svg",
|
|
7
7
|
"command": ["npx", "@planu/cli@latest"],
|
|
8
8
|
"packageName": "@planu/cli",
|
|
9
9
|
"capabilities": {
|
|
10
10
|
"tools": [
|
|
11
|
-
"planu_status",
|
|
12
|
-
"session_checkpoint",
|
|
13
|
-
"facilitate",
|
|
14
11
|
"init_project",
|
|
15
|
-
"
|
|
12
|
+
"facilitate",
|
|
16
13
|
"create_spec",
|
|
17
14
|
"list_specs",
|
|
18
|
-
"challenge_spec",
|
|
19
|
-
"check_readiness",
|
|
20
15
|
"update_status",
|
|
21
16
|
"update_status_batch",
|
|
22
|
-
"request_changes",
|
|
23
|
-
"estimate",
|
|
24
|
-
"package_handoff",
|
|
25
17
|
"validate",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"cancel_job",
|
|
29
|
-
"restart_job",
|
|
30
|
-
"reconcile_spec",
|
|
31
|
-
"create_rule",
|
|
32
|
-
"create_skill",
|
|
33
|
-
"skill_search",
|
|
34
|
-
"configure_code_graph",
|
|
35
|
-
"code_graph_status",
|
|
36
|
-
"submit_feedback",
|
|
37
|
-
"triage_feedback",
|
|
38
|
-
"resolve_feedback",
|
|
39
|
-
"sync_feedback",
|
|
40
|
-
"feedback_status",
|
|
18
|
+
"challenge_spec",
|
|
19
|
+
"check_readiness",
|
|
41
20
|
"bump_spec_version",
|
|
42
|
-
"
|
|
21
|
+
"reconcile_spec",
|
|
22
|
+
"migrate_legacy_spec",
|
|
23
|
+
"package_handoff",
|
|
24
|
+
"planu_status",
|
|
25
|
+
"session_checkpoint",
|
|
26
|
+
"estimate",
|
|
27
|
+
"request_changes",
|
|
28
|
+
"get_job",
|
|
29
|
+
"restart_job"
|
|
43
30
|
],
|
|
44
31
|
"resources": ["planu://specs/list", "planu://specs/{id}", "planu://project/status", "planu://roadmap"],
|
|
45
32
|
"prompts": ["create-spec-from-idea", "review-spec-readiness", "generate-implementation-plan"],
|
|
@@ -307,7 +307,7 @@
|
|
|
307
307
|
"description": "Check if a plan has enough detail to start building. Verifies that the description is complete, acceptance criteria are clear, and all dependencies are met. Tells you if the plan is ready or what is missing."
|
|
308
308
|
},
|
|
309
309
|
"package_handoff": {
|
|
310
|
-
"description": "
|
|
310
|
+
"description": "Submit a durable job that builds a complete instruction package so an AI agent can implement a feature. Returns an acknowledgment immediately; poll get_job for the completed package (objective, acceptance criteria, file list, what is out of scope, and any constraints)."
|
|
311
311
|
},
|
|
312
312
|
"context_budget": {
|
|
313
313
|
"description": "Manage context window budget and optimization — configure limits, save checkpoints, and get suggestions to reduce token usage.",
|
|
@@ -307,7 +307,7 @@
|
|
|
307
307
|
"description": "Verificar si un plan tiene suficiente detalle para empezar a construir. Verifica que la descripción esté completa, los criterios de aceptación sean claros y todas las dependencias estén cumplidas. Te dice si el plan está listo o qué falta."
|
|
308
308
|
},
|
|
309
309
|
"package_handoff": {
|
|
310
|
-
"description": "
|
|
310
|
+
"description": "Enviar un job durable que construye un paquete completo de instrucciones para que un agente de IA implemente una feature. Devuelve un acuse de recibo de inmediato; usa get_job para obtener el paquete completado (objetivo, criterios de aceptación, lista de archivos, qué está fuera de scope y cualquier restricción)."
|
|
311
311
|
},
|
|
312
312
|
"context_budget": {
|
|
313
313
|
"description": "Gestionar el presupuesto de ventana de contexto y optimización — configurar límites, guardar checkpoints y obtener sugerencias para reducir uso de tokens.",
|
|
@@ -307,7 +307,7 @@
|
|
|
307
307
|
"description": "Verificar se um plano tem detalhes suficientes para começar a construir. Verifica se a descrição está completa, se os critérios de aceitação estão claros e se todas as dependências estão atendidas. Te diz se o plano está pronto ou o que está faltando."
|
|
308
308
|
},
|
|
309
309
|
"package_handoff": {
|
|
310
|
-
"description": "
|
|
310
|
+
"description": "Enviar um job durável que constrói um pacote completo de instruções para um agente de IA implementar uma feature. Retorna uma confirmação imediatamente; use get_job para obter o pacote concluído (objetivo, critérios de aceitação, lista de arquivos, o que está fora do escopo e quaisquer restrições)."
|
|
311
311
|
},
|
|
312
312
|
"context_budget": {
|
|
313
313
|
"description": "Gerenciar o orçamento da janela de contexto e otimização — configurar limites, salvar checkpoints e obter sugestões para reduzir uso de tokens.",
|