@planu/cli 5.3.3 → 5.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/engine/autopilot/action-registry.js +20 -2
  3. package/dist/engine/constitution/sdd-rules-registry.js +8 -4
  4. package/dist/engine/drift/violation-resolver.js +30 -8
  5. package/dist/engine/evidence-gates/evidence-skeletons.js +9 -4
  6. package/dist/engine/execution/validate-job-executor.js +25 -10
  7. package/dist/engine/handoff-packager.js +10 -3
  8. package/dist/engine/implementation-contract/common.d.ts +13 -1
  9. package/dist/engine/implementation-contract/common.js +19 -3
  10. package/dist/engine/implementation-contract/evaluator.js +116 -35
  11. package/dist/engine/implementation-contract/renderer.js +62 -31
  12. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
  13. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +4 -4
  14. package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
  15. package/dist/engine/planu-core.darwin-x64.node.sbom.json +4 -4
  16. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
  17. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +4 -4
  18. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
  19. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +4 -4
  20. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
  21. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +4 -4
  22. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
  23. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +4 -4
  24. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
  25. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +4 -4
  26. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
  27. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +4 -4
  28. package/dist/engine/reconcile/apply-changes.d.ts +0 -12
  29. package/dist/engine/reconcile/apply-changes.js +11 -33
  30. package/dist/engine/reconcile/verify-write.js +2 -3
  31. package/dist/engine/rules-reconciler.js +21 -2
  32. package/dist/engine/spec-format/acceptance-criteria.js +7 -1
  33. package/dist/engine/spec-format/unified-spec-builder.js +32 -8
  34. package/dist/engine/spec-generator/fallback-generator.js +5 -3
  35. package/dist/engine/spec-quality/generic-output-gate.d.ts +7 -1
  36. package/dist/engine/spec-quality/generic-output-gate.js +199 -8
  37. package/dist/engine/spec-quality-scorer.js +9 -5
  38. package/dist/engine/universal-rules/catalog.js +6 -0
  39. package/dist/engine/universal-rules/rules/agent-teams.js +0 -2
  40. package/dist/engine/universal-rules/rules/planu-approval-gates.js +0 -1
  41. package/dist/engine/universal-rules/rules/planu-bdd-criteria.js +0 -1
  42. package/dist/engine/universal-rules/rules/planu-clean-code-no-comments.d.ts +3 -0
  43. package/dist/engine/universal-rules/rules/planu-clean-code-no-comments.js +30 -0
  44. package/dist/engine/universal-rules/rules/planu-debate-review.d.ts +3 -0
  45. package/dist/engine/universal-rules/rules/planu-debate-review.js +38 -0
  46. package/dist/engine/universal-rules/rules/planu-dogfood-bugs.js +0 -2
  47. package/dist/engine/universal-rules/rules/planu-english-specs.js +0 -1
  48. package/dist/engine/universal-rules/rules/planu-minimal-change.js +0 -2
  49. package/dist/engine/universal-rules/rules/planu-modes.js +0 -2
  50. package/dist/engine/universal-rules/rules/planu-release-policy.js +0 -1
  51. package/dist/engine/universal-rules/rules/planu-revert-proof-tests.d.ts +3 -0
  52. package/dist/engine/universal-rules/rules/planu-revert-proof-tests.js +34 -0
  53. package/dist/engine/universal-rules/rules/planu-sdd-model-routing.js +0 -1
  54. package/dist/engine/universal-rules/rules/planu-workflow.js +0 -2
  55. package/dist/engine/validator/validation-report-writer.js +1 -1
  56. package/dist/engine/workers/handlers/auto-drift.js +22 -8
  57. package/dist/tools/create-spec.js +5 -0
  58. package/dist/tools/reconcile-spec.d.ts +1 -1
  59. package/dist/tools/reconcile-spec.js +303 -178
  60. package/dist/tools/update-status/dod-gates.js +3 -3
  61. package/dist/tools/update-status/evidence-gate.js +10 -17
  62. package/dist/tools/update-status/transition-guard.js +26 -14
  63. package/dist/types/reconcile.d.ts +5 -17
  64. package/dist/types/reconcile.js +1 -7
  65. package/dist/types/spec-quality.d.ts +6 -1
  66. package/package.json +9 -9
  67. package/planu-native.json +1 -1
  68. package/planu-plugin.json +1 -1
@@ -0,0 +1,3 @@
1
+ import type { UniversalRule } from '../../../types/universal-rules/index.js';
2
+ export declare const planuDebateReviewRule: UniversalRule;
3
+ //# sourceMappingURL=planu-debate-review.d.ts.map
@@ -0,0 +1,38 @@
1
+ function buildBody() {
2
+ return `# Planu Debate Review
3
+
4
+ Auto-generated by \`init_project\`. Do not edit manually.
5
+
6
+ This rule assumes \`planu-approval-gates\` (reviewer independence, self-approval prohibitions) and \`planu-sdd-model-routing\` (arbitration) and restates neither.
7
+
8
+ ## Reviewer Plurality And Provider Diversity
9
+
10
+ Every spec and every implementation is reviewed by two independent reviewers from DIFFERENT providers, in ONE parallel round.
11
+
12
+ Prohibited: running a single reviewer, or running two reviewers from the same provider, and calling the result a debate round.
13
+
14
+ Replacement action: launch both reviewers in the same message so they run concurrently, and pick two different providers (for example one Claude-family model and one external model).
15
+
16
+ ## One Parallel Round, No Serial Confirmation Loops
17
+
18
+ Prohibited: re-launching a reviewer for pass 2, pass 3, or a "confirm the fix" loop after the first round already produced verdicts.
19
+
20
+ Replacement action: cross the two verdicts once — coincident findings apply directly, divergent findings are arbitrated against the source code — then close the round. Re-open a reviewer only for a specific disagreement the arbiter cannot resolve by reading the code directly.
21
+
22
+ ## Degradation Ladder
23
+
24
+ Prohibited: silently reviewing with only one provider when a second is unavailable and presenting it as a debate round.
25
+
26
+ Replacement action: when only one provider is available, run two isolated sessions of the same model instead of one, so two independent verdicts still exist before arbitration.
27
+ `;
28
+ }
29
+ export const planuDebateReviewRule = {
30
+ id: 'planu-debate-review',
31
+ name: 'Planu Debate Review',
32
+ description: 'Requires two-provider parallel review rounds with no serial confirmation loops and a single-provider degradation ladder.',
33
+ category: 'quality',
34
+ applicableHosts: ['all'],
35
+ defaultEnabled: true,
36
+ buildContent: (_host) => buildBody(),
37
+ };
38
+ //# sourceMappingURL=planu-debate-review.js.map
@@ -1,5 +1,3 @@
1
- // engine/universal-rules/rules/planu-dogfood-bugs.ts — SPEC-779
2
- // Universal rule: Planu Dogfood Bugs (mandatory for all Planu-using projects)
3
1
  /** Shared markdown body (same for all hosts). */
4
2
  function buildBody() {
5
3
  return `# Planu Dogfood Bugs (MANDATORY — STRICT)
@@ -1,4 +1,3 @@
1
- // engine/universal-rules/rules/planu-english-specs.ts — Universal rule: specs are written in English
2
1
  function buildBody() {
3
2
  return `# Planu Artifacts Must Be Written in English
4
3
 
@@ -1,5 +1,3 @@
1
- // engine/universal-rules/rules/planu-minimal-change.ts
2
- // Universal rule: minimal-change implementation discipline.
3
1
  function buildBody() {
4
2
  return `# Planu Minimal Change
5
3
 
@@ -1,5 +1,3 @@
1
- // engine/universal-rules/rules/planu-modes.ts — SPEC-779
2
- // Universal rule: Claude Code Mode Hints per spec phase (SPEC-494)
3
1
  function buildBody(host) {
4
2
  if (host === 'claude-code') {
5
3
  return `# Claude Code Mode Hints (MANDATORY — Planu SDD)
@@ -1,4 +1,3 @@
1
- // engine/universal-rules/rules/planu-release-policy.ts — Universal rule: release decision
2
1
  function buildBody() {
3
2
  return `# Planu Release Policy
4
3
 
@@ -0,0 +1,3 @@
1
+ import type { UniversalRule } from '../../../types/universal-rules/index.js';
2
+ export declare const planuRevertProofTestsRule: UniversalRule;
3
+ //# sourceMappingURL=planu-revert-proof-tests.d.ts.map
@@ -0,0 +1,34 @@
1
+ function buildBody() {
2
+ return `# Planu Revert-Proof Tests
3
+
4
+ Auto-generated by \`init_project\`. Do not edit manually.
5
+
6
+ A new test that never fails against the unfixed source proves nothing.
7
+
8
+ ## The Rule
9
+
10
+ Prohibited: reporting a new test as passing evidence without ever having watched it fail. This includes an assertion that compares a value to itself, a mock that echoes back what it was given, and a negative assertion that holds vacuously regardless of the source under test.
11
+
12
+ Replacement action: before reporting the test as evidence, revert only the source change it covers — invert the specific guard line in place, or run the test against the pre-change body read with \`git show <ref>:<path>\` — run the test, and observe it fail. Then restore the source and confirm the test passes again. Report the observed failure output, not just the final green run.
13
+
14
+ Prohibited: using \`git stash\`, \`git checkout\` or \`git restore\` on a shared checkout to stage the revert. Stashes are a process-wide LIFO stack, so a concurrent agent can pop work that is not its own.
15
+
16
+ A guard's regression test must fail against the unguarded variant specifically, not merely against an unrelated point in history such as HEAD.
17
+
18
+ ## Hard Blocks
19
+
20
+ - Do not accept a test whose only run is against already-fixed source.
21
+ - Do not accept an assertion that compares a value to itself.
22
+ - Do not accept an assertion that cannot fail for any input.
23
+ `;
24
+ }
25
+ export const planuRevertProofTestsRule = {
26
+ id: 'planu-revert-proof-tests',
27
+ name: 'Planu Revert-Proof Tests',
28
+ description: 'Requires new tests to be proven to fail against the unfixed source before being reported as evidence.',
29
+ category: 'quality',
30
+ applicableHosts: ['all'],
31
+ defaultEnabled: true,
32
+ buildContent: (_host) => buildBody(),
33
+ };
34
+ //# sourceMappingURL=planu-revert-proof-tests.js.map
@@ -1,4 +1,3 @@
1
- // engine/universal-rules/rules/planu-sdd-model-routing.ts — Universal rule: model routing + context continuity
2
1
  function buildBody() {
3
2
  return `# Planu SDD Model Routing and Context Guarantee
4
3
 
@@ -1,5 +1,3 @@
1
- // engine/universal-rules/rules/planu-workflow.ts — SPEC-779
2
- // Universal rule: Planu Workflow (migrated from rules-generator.ts)
3
1
  function buildBody() {
4
2
  return `# Planu SDD Workflow (MANDATORY)
5
3
 
@@ -39,7 +39,7 @@ export async function writeImplementationReviewReport(input) {
39
39
  return {
40
40
  written: true,
41
41
  path: artifact.path,
42
- sha: artifact.sha,
42
+ sha: `sha256:${artifact.sha}`,
43
43
  reviewer,
44
44
  passed,
45
45
  gates: mergedGates,
@@ -154,14 +154,6 @@ async function buildDriftFindings(projectDir, effectiveChanged, activeSpecs, pro
154
154
  driftedFiles,
155
155
  cachedAt: new Date().toISOString(),
156
156
  });
157
- // Wire drift:detected event so autopilot trigger-rules can react
158
- emitAutopilotEvent({
159
- name: 'drift:detected',
160
- projectPath: projectDir,
161
- projectId,
162
- specId: spec.id,
163
- payload: { driftScore, driftLevel: driftScore >= 0.7 ? 'high' : 'warning' },
164
- });
165
157
  findings.push({
166
158
  severity: driftScore >= 0.7 ? 'high' : 'warning',
167
159
  file: '',
@@ -171,6 +163,28 @@ async function buildDriftFindings(projectDir, effectiveChanged, activeSpecs, pro
171
163
  });
172
164
  }
173
165
  }
166
+ if (driftScore >= threshold) {
167
+ // Wire drift:detected event so autopilot trigger-rules can react.
168
+ // Emitted once per project run — driftScore is project-wide, not per-spec,
169
+ // so emitting inside the loop would fire N identical events for N specs.
170
+ //
171
+ // MUST run after the cache-persistence loop above: emitAutopilotEvent
172
+ // dispatches handlers in a microtask (event-bus.ts), and the enabled
173
+ // rule drift-detected:resolve_drift_violations calls resolveDriftViolations,
174
+ // which loads the drift cache as its first action. Emitting before the
175
+ // cache entries are persisted lets that microtask race ahead and read an
176
+ // empty cache, silently resolving nothing.
177
+ emitAutopilotEvent({
178
+ name: 'drift:detected',
179
+ projectPath: projectDir,
180
+ projectId,
181
+ payload: {
182
+ driftScore,
183
+ driftLevel: driftScore >= 0.7 ? 'high' : 'warning',
184
+ specIds: activeSpecs.map((s) => s.id),
185
+ },
186
+ });
187
+ }
174
188
  return findings;
175
189
  }
176
190
  // ---------------------------------------------------------------------------
@@ -1030,6 +1030,11 @@ async function prepareCreateSpecCandidate(initialParams, server) {
1030
1030
  },
1031
1031
  }));
1032
1032
  spec.generation = generatedSpec.generation;
1033
+ // SPEC-1406 (DEFECT 4, round 2): FallbackGenerator no longer emits an unconditional
1034
+ // warning, so qualityWarnings only needs the non-empty guard now — the redundant
1035
+ // constant-string filter was removed from create-spec.ts, fallback-generator.ts and
1036
+ // opus-generator.ts (dead code, reverted) so the literal doesn't have to stay
1037
+ // byte-identical across three files.
1033
1038
  spec.qualityWarnings =
1034
1039
  generatedSpec.qualityWarnings.length > 0 ? generatedSpec.qualityWarnings : undefined;
1035
1040
  const baseCriteria = extractCriteria(generatedSpec.specBody).map((criterion) => criterion.text);
@@ -1,4 +1,4 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import type { ReconcileSpecInput, ToolResult } from '../types/index.js';
2
+ import { type ReconcileSpecInput, type ToolResult } from '../types/index.js';
3
3
  export declare function handleReconcileSpec(params: ReconcileSpecInput, server?: McpServer): Promise<ToolResult>;
4
4
  //# sourceMappingURL=reconcile-spec.d.ts.map