@planu/cli 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/ai-tool-registry.json +71 -0
- package/dist/config/autopilot-config.json +21 -0
- package/dist/config/competitive-catalog.json +83 -0
- package/dist/config/license-plans.json +43 -2
- package/dist/engine/agent-registry/lifecycle-manager.d.ts +8 -0
- package/dist/engine/agent-registry/lifecycle-manager.d.ts.map +1 -0
- package/dist/engine/agent-registry/lifecycle-manager.js +81 -0
- package/dist/engine/agent-registry/lifecycle-manager.js.map +1 -0
- package/dist/engine/agent-registry/role-catalog.d.ts +17 -0
- package/dist/engine/agent-registry/role-catalog.d.ts.map +1 -0
- package/dist/engine/agent-registry/role-catalog.js +55 -0
- package/dist/engine/agent-registry/role-catalog.js.map +1 -0
- package/dist/engine/api-compat/compatibility-checker.d.ts +4 -0
- package/dist/engine/api-compat/compatibility-checker.d.ts.map +1 -0
- package/dist/engine/api-compat/compatibility-checker.js +118 -0
- package/dist/engine/api-compat/compatibility-checker.js.map +1 -0
- package/dist/engine/autopilot/action-executor.d.ts +18 -0
- package/dist/engine/autopilot/action-executor.d.ts.map +1 -0
- package/dist/engine/autopilot/action-executor.js +91 -0
- package/dist/engine/autopilot/action-executor.js.map +1 -0
- package/dist/engine/autopilot/event-bus.d.ts +8 -0
- package/dist/engine/autopilot/event-bus.d.ts.map +1 -0
- package/dist/engine/autopilot/event-bus.js +28 -0
- package/dist/engine/autopilot/event-bus.js.map +1 -0
- package/dist/engine/autopilot/trigger-rules.d.ts +3 -0
- package/dist/engine/autopilot/trigger-rules.d.ts.map +1 -0
- package/dist/engine/autopilot/trigger-rules.js +125 -0
- package/dist/engine/autopilot/trigger-rules.js.map +1 -0
- package/dist/engine/checkpoint/checkpoint-manager.d.ts +22 -0
- package/dist/engine/checkpoint/checkpoint-manager.d.ts.map +1 -0
- package/dist/engine/checkpoint/checkpoint-manager.js +76 -0
- package/dist/engine/checkpoint/checkpoint-manager.js.map +1 -0
- package/dist/engine/checkpoint/policy-engine.d.ts +10 -0
- package/dist/engine/checkpoint/policy-engine.d.ts.map +1 -0
- package/dist/engine/checkpoint/policy-engine.js +87 -0
- package/dist/engine/checkpoint/policy-engine.js.map +1 -0
- package/dist/engine/competitive/gap-analyzer.d.ts +12 -0
- package/dist/engine/competitive/gap-analyzer.d.ts.map +1 -0
- package/dist/engine/competitive/gap-analyzer.js +214 -0
- package/dist/engine/competitive/gap-analyzer.js.map +1 -0
- package/dist/engine/compliance/auto-remediator.d.ts +9 -0
- package/dist/engine/compliance/auto-remediator.d.ts.map +1 -0
- package/dist/engine/compliance/auto-remediator.js +118 -0
- package/dist/engine/compliance/auto-remediator.js.map +1 -0
- package/dist/engine/context-profile/profile-catalog.d.ts +5 -0
- package/dist/engine/context-profile/profile-catalog.d.ts.map +1 -0
- package/dist/engine/context-profile/profile-catalog.js +145 -0
- package/dist/engine/context-profile/profile-catalog.js.map +1 -0
- package/dist/engine/critical-path/path-analyzer.d.ts +3 -0
- package/dist/engine/critical-path/path-analyzer.d.ts.map +1 -0
- package/dist/engine/critical-path/path-analyzer.js +145 -0
- package/dist/engine/critical-path/path-analyzer.js.map +1 -0
- package/dist/engine/drift/violation-resolver.d.ts +9 -0
- package/dist/engine/drift/violation-resolver.d.ts.map +1 -0
- package/dist/engine/drift/violation-resolver.js +128 -0
- package/dist/engine/drift/violation-resolver.js.map +1 -0
- package/dist/engine/ears/criterion-scorer.d.ts +7 -0
- package/dist/engine/ears/criterion-scorer.d.ts.map +1 -0
- package/dist/engine/ears/criterion-scorer.js +87 -0
- package/dist/engine/ears/criterion-scorer.js.map +1 -0
- package/dist/engine/ears/pattern-matcher.d.ts +5 -0
- package/dist/engine/ears/pattern-matcher.d.ts.map +1 -0
- package/dist/engine/ears/pattern-matcher.js +48 -0
- package/dist/engine/ears/pattern-matcher.js.map +1 -0
- package/dist/engine/ears/rewriter.d.ts +7 -0
- package/dist/engine/ears/rewriter.d.ts.map +1 -0
- package/dist/engine/ears/rewriter.js +45 -0
- package/dist/engine/ears/rewriter.js.map +1 -0
- package/dist/engine/ears/spec-linter.d.ts +7 -0
- package/dist/engine/ears/spec-linter.d.ts.map +1 -0
- package/dist/engine/ears/spec-linter.js +127 -0
- package/dist/engine/ears/spec-linter.js.map +1 -0
- package/dist/engine/health/auto-fixer.d.ts +7 -0
- package/dist/engine/health/auto-fixer.d.ts.map +1 -0
- package/dist/engine/health/auto-fixer.js +130 -0
- package/dist/engine/health/auto-fixer.js.map +1 -0
- package/dist/engine/hook-generator/ai-hook-templates.d.ts +8 -0
- package/dist/engine/hook-generator/ai-hook-templates.d.ts.map +1 -0
- package/dist/engine/hook-generator/ai-hook-templates.js +43 -0
- package/dist/engine/hook-generator/ai-hook-templates.js.map +1 -0
- package/dist/engine/hook-generator/hook-merger.d.ts +13 -0
- package/dist/engine/hook-generator/hook-merger.d.ts.map +1 -0
- package/dist/engine/hook-generator/hook-merger.js +148 -0
- package/dist/engine/hook-generator/hook-merger.js.map +1 -0
- package/dist/engine/hook-generator/stack-hook-templates.d.ts +10 -0
- package/dist/engine/hook-generator/stack-hook-templates.d.ts.map +1 -0
- package/dist/engine/hook-generator/stack-hook-templates.js +105 -0
- package/dist/engine/hook-generator/stack-hook-templates.js.map +1 -0
- package/dist/engine/mcp-catalog/catalog-advisor.d.ts +3 -0
- package/dist/engine/mcp-catalog/catalog-advisor.d.ts.map +1 -0
- package/dist/engine/mcp-catalog/catalog-advisor.js +180 -0
- package/dist/engine/mcp-catalog/catalog-advisor.js.map +1 -0
- package/dist/engine/project-dna/ai-tool-detector.d.ts +12 -0
- package/dist/engine/project-dna/ai-tool-detector.d.ts.map +1 -0
- package/dist/engine/project-dna/ai-tool-detector.js +103 -0
- package/dist/engine/project-dna/ai-tool-detector.js.map +1 -0
- package/dist/engine/project-dna/rules-generator.d.ts +18 -0
- package/dist/engine/project-dna/rules-generator.d.ts.map +1 -0
- package/dist/engine/project-dna/rules-generator.js +193 -0
- package/dist/engine/project-dna/rules-generator.js.map +1 -0
- package/dist/engine/project-dna/stack-detector.d.ts +24 -0
- package/dist/engine/project-dna/stack-detector.d.ts.map +1 -0
- package/dist/engine/project-dna/stack-detector.js +309 -0
- package/dist/engine/project-dna/stack-detector.js.map +1 -0
- package/dist/engine/similar-problems/similarity-finder.d.ts +3 -0
- package/dist/engine/similar-problems/similarity-finder.d.ts.map +1 -0
- package/dist/engine/similar-problems/similarity-finder.js +144 -0
- package/dist/engine/similar-problems/similarity-finder.js.map +1 -0
- package/dist/engine/sync/asana-puller.d.ts +9 -0
- package/dist/engine/sync/asana-puller.d.ts.map +1 -0
- package/dist/engine/sync/asana-puller.js +91 -0
- package/dist/engine/sync/asana-puller.js.map +1 -0
- package/dist/engine/sync/conflict-resolver.d.ts +17 -0
- package/dist/engine/sync/conflict-resolver.d.ts.map +1 -0
- package/dist/engine/sync/conflict-resolver.js +58 -0
- package/dist/engine/sync/conflict-resolver.js.map +1 -0
- package/dist/engine/sync/monday-puller.d.ts +9 -0
- package/dist/engine/sync/monday-puller.d.ts.map +1 -0
- package/dist/engine/sync/monday-puller.js +110 -0
- package/dist/engine/sync/monday-puller.js.map +1 -0
- package/dist/engine/sync/notion-puller.d.ts +15 -0
- package/dist/engine/sync/notion-puller.d.ts.map +1 -0
- package/dist/engine/sync/notion-puller.js +101 -0
- package/dist/engine/sync/notion-puller.js.map +1 -0
- package/dist/engine/verifier/code-scanner.d.ts +8 -0
- package/dist/engine/verifier/code-scanner.d.ts.map +1 -0
- package/dist/engine/verifier/code-scanner.js +73 -0
- package/dist/engine/verifier/code-scanner.js.map +1 -0
- package/dist/engine/verifier/compliance-scorer.d.ts +17 -0
- package/dist/engine/verifier/compliance-scorer.d.ts.map +1 -0
- package/dist/engine/verifier/compliance-scorer.js +131 -0
- package/dist/engine/verifier/compliance-scorer.js.map +1 -0
- package/dist/engine/verifier/criterion-matcher.d.ts +15 -0
- package/dist/engine/verifier/criterion-matcher.d.ts.map +1 -0
- package/dist/engine/verifier/criterion-matcher.js +210 -0
- package/dist/engine/verifier/criterion-matcher.js.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/agent-registry-store.d.ts +11 -0
- package/dist/storage/agent-registry-store.d.ts.map +1 -0
- package/dist/storage/agent-registry-store.js +45 -0
- package/dist/storage/agent-registry-store.js.map +1 -0
- package/dist/storage/compliance-score-store.d.ts +16 -0
- package/dist/storage/compliance-score-store.d.ts.map +1 -0
- package/dist/storage/compliance-score-store.js +30 -0
- package/dist/storage/compliance-score-store.js.map +1 -0
- package/dist/storage/context-profile-store.d.ts +14 -0
- package/dist/storage/context-profile-store.d.ts.map +1 -0
- package/dist/storage/context-profile-store.js +34 -0
- package/dist/storage/context-profile-store.js.map +1 -0
- package/dist/storage/workflow-checkpoint-store.d.ts +16 -0
- package/dist/storage/workflow-checkpoint-store.d.ts.map +1 -0
- package/dist/storage/workflow-checkpoint-store.js +71 -0
- package/dist/storage/workflow-checkpoint-store.js.map +1 -0
- package/dist/tools/checkpoint/approve-checkpoint-handler.d.ts +3 -0
- package/dist/tools/checkpoint/approve-checkpoint-handler.d.ts.map +1 -0
- package/dist/tools/checkpoint/approve-checkpoint-handler.js +32 -0
- package/dist/tools/checkpoint/approve-checkpoint-handler.js.map +1 -0
- package/dist/tools/checkpoint/configure-policy-handler.d.ts +3 -0
- package/dist/tools/checkpoint/configure-policy-handler.d.ts.map +1 -0
- package/dist/tools/checkpoint/configure-policy-handler.js +60 -0
- package/dist/tools/checkpoint/configure-policy-handler.js.map +1 -0
- package/dist/tools/checkpoint/list-checkpoints-handler.d.ts +3 -0
- package/dist/tools/checkpoint/list-checkpoints-handler.d.ts.map +1 -0
- package/dist/tools/checkpoint/list-checkpoints-handler.js +25 -0
- package/dist/tools/checkpoint/list-checkpoints-handler.js.map +1 -0
- package/dist/tools/checkpoint/reject-checkpoint-handler.d.ts +3 -0
- package/dist/tools/checkpoint/reject-checkpoint-handler.d.ts.map +1 -0
- package/dist/tools/checkpoint/reject-checkpoint-handler.js +32 -0
- package/dist/tools/checkpoint/reject-checkpoint-handler.js.map +1 -0
- package/dist/tools/checkpoint/require-checkpoint-handler.d.ts +3 -0
- package/dist/tools/checkpoint/require-checkpoint-handler.d.ts.map +1 -0
- package/dist/tools/checkpoint/require-checkpoint-handler.js +44 -0
- package/dist/tools/checkpoint/require-checkpoint-handler.js.map +1 -0
- package/dist/tools/competitive-handlers.d.ts +30 -0
- package/dist/tools/competitive-handlers.d.ts.map +1 -0
- package/dist/tools/competitive-handlers.js +155 -0
- package/dist/tools/competitive-handlers.js.map +1 -0
- package/dist/tools/create-spec/post-creation.d.ts +1 -1
- package/dist/tools/create-spec/post-creation.d.ts.map +1 -1
- package/dist/tools/create-spec/post-creation.js +13 -1
- package/dist/tools/create-spec/post-creation.js.map +1 -1
- package/dist/tools/create-spec.js +1 -1
- package/dist/tools/create-spec.js.map +1 -1
- package/dist/tools/hook-generator-handler.d.ts +8 -0
- package/dist/tools/hook-generator-handler.d.ts.map +1 -0
- package/dist/tools/hook-generator-handler.js +154 -0
- package/dist/tools/hook-generator-handler.js.map +1 -0
- package/dist/tools/project-dna-handler.d.ts +34 -0
- package/dist/tools/project-dna-handler.d.ts.map +1 -0
- package/dist/tools/project-dna-handler.js +261 -0
- package/dist/tools/project-dna-handler.js.map +1 -0
- package/dist/tools/pull-sync-handler.d.ts +25 -0
- package/dist/tools/pull-sync-handler.d.ts.map +1 -0
- package/dist/tools/pull-sync-handler.js +161 -0
- package/dist/tools/pull-sync-handler.js.map +1 -0
- package/dist/tools/register-agent-registry.d.ts +5 -0
- package/dist/tools/register-agent-registry.d.ts.map +1 -0
- package/dist/tools/register-agent-registry.js +254 -0
- package/dist/tools/register-agent-registry.js.map +1 -0
- package/dist/tools/register-auto-remediation.d.ts +3 -0
- package/dist/tools/register-auto-remediation.d.ts.map +1 -0
- package/dist/tools/register-auto-remediation.js +174 -0
- package/dist/tools/register-auto-remediation.js.map +1 -0
- package/dist/tools/register-autopilot.d.ts +3 -0
- package/dist/tools/register-autopilot.d.ts.map +1 -0
- package/dist/tools/register-autopilot.js +78 -0
- package/dist/tools/register-autopilot.js.map +1 -0
- package/dist/tools/register-checkpoints.d.ts +3 -0
- package/dist/tools/register-checkpoints.d.ts.map +1 -0
- package/dist/tools/register-checkpoints.js +134 -0
- package/dist/tools/register-checkpoints.js.map +1 -0
- package/dist/tools/register-competitive.d.ts +3 -0
- package/dist/tools/register-competitive.d.ts.map +1 -0
- package/dist/tools/register-competitive.js +88 -0
- package/dist/tools/register-competitive.js.map +1 -0
- package/dist/tools/register-context-profile.d.ts +3 -0
- package/dist/tools/register-context-profile.d.ts.map +1 -0
- package/dist/tools/register-context-profile.js +106 -0
- package/dist/tools/register-context-profile.js.map +1 -0
- package/dist/tools/register-ears.d.ts +3 -0
- package/dist/tools/register-ears.d.ts.map +1 -0
- package/dist/tools/register-ears.js +148 -0
- package/dist/tools/register-ears.js.map +1 -0
- package/dist/tools/register-enterprise-compliance.js +1 -1
- package/dist/tools/register-enterprise-compliance.js.map +1 -1
- package/dist/tools/register-hook-generator.d.ts +3 -0
- package/dist/tools/register-hook-generator.d.ts.map +1 -0
- package/dist/tools/register-hook-generator.js +96 -0
- package/dist/tools/register-hook-generator.js.map +1 -0
- package/dist/tools/register-project-dna.d.ts +3 -0
- package/dist/tools/register-project-dna.d.ts.map +1 -0
- package/dist/tools/register-project-dna.js +43 -0
- package/dist/tools/register-project-dna.js.map +1 -0
- package/dist/tools/register-pull-sync.d.ts +3 -0
- package/dist/tools/register-pull-sync.d.ts.map +1 -0
- package/dist/tools/register-pull-sync.js +71 -0
- package/dist/tools/register-pull-sync.js.map +1 -0
- package/dist/tools/register-spec405-tools.d.ts +7 -0
- package/dist/tools/register-spec405-tools.d.ts.map +1 -0
- package/dist/tools/register-spec405-tools.js +194 -0
- package/dist/tools/register-spec405-tools.js.map +1 -0
- package/dist/tools/register-verifier.d.ts +3 -0
- package/dist/tools/register-verifier.d.ts.map +1 -0
- package/dist/tools/register-verifier.js +141 -0
- package/dist/tools/register-verifier.js.map +1 -0
- package/dist/tools/update-status/side-effects.d.ts.map +1 -1
- package/dist/tools/update-status/side-effects.js +32 -0
- package/dist/tools/update-status/side-effects.js.map +1 -1
- package/dist/types/agent-registry.d.ts +53 -0
- package/dist/types/agent-registry.d.ts.map +1 -0
- package/dist/types/agent-registry.js +2 -0
- package/dist/types/agent-registry.js.map +1 -0
- package/dist/types/analysis.d.ts +98 -0
- package/dist/types/analysis.d.ts.map +1 -1
- package/dist/types/autopilot.d.ts +36 -0
- package/dist/types/autopilot.d.ts.map +1 -0
- package/dist/types/autopilot.js +3 -0
- package/dist/types/autopilot.js.map +1 -0
- package/dist/types/competitive.d.ts +41 -0
- package/dist/types/competitive.d.ts.map +1 -0
- package/dist/types/competitive.js +3 -0
- package/dist/types/competitive.js.map +1 -0
- package/dist/types/context-profile.d.ts +22 -0
- package/dist/types/context-profile.d.ts.map +1 -0
- package/dist/types/context-profile.js +2 -0
- package/dist/types/context-profile.js.map +1 -0
- package/dist/types/ears.d.ts +34 -0
- package/dist/types/ears.d.ts.map +1 -0
- package/dist/types/ears.js +3 -0
- package/dist/types/ears.js.map +1 -0
- package/dist/types/health.d.ts +40 -0
- package/dist/types/health.d.ts.map +1 -0
- package/dist/types/health.js +3 -0
- package/dist/types/health.js.map +1 -0
- package/dist/types/hook-generator.d.ts +49 -0
- package/dist/types/hook-generator.d.ts.map +1 -0
- package/dist/types/hook-generator.js +3 -0
- package/dist/types/hook-generator.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/notion-asana-monday.d.ts +38 -0
- package/dist/types/notion-asana-monday.d.ts.map +1 -1
- package/dist/types/project-dna.d.ts +46 -0
- package/dist/types/project-dna.d.ts.map +1 -0
- package/dist/types/project-dna.js +4 -0
- package/dist/types/project-dna.js.map +1 -0
- package/dist/types/workflow-checkpoint.d.ts +66 -0
- package/dist/types/workflow-checkpoint.d.ts.map +1 -0
- package/dist/types/workflow-checkpoint.js +4 -0
- package/dist/types/workflow-checkpoint.js.map +1 -0
- package/package.json +1 -1
- package/src/config/ai-tool-registry.json +71 -0
- package/src/config/autopilot-config.json +21 -0
- package/src/config/competitive-catalog.json +83 -0
- package/src/config/license-plans.json +43 -2
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a single conflict using the given strategy.
|
|
3
|
+
*
|
|
4
|
+
* Strategies:
|
|
5
|
+
* - spec-wins → Planu value is authoritative; external change is discarded.
|
|
6
|
+
* - external-wins → External PM value is authoritative; applied to Planu.
|
|
7
|
+
* - newest-wins → The most recently updated side wins. Falls back to spec-wins
|
|
8
|
+
* when timestamps are equal or unparseable.
|
|
9
|
+
* - manual → Conflict is flagged for human review; no automatic resolution.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveConflict(conflict, strategy) {
|
|
12
|
+
const resolution = determineResolution(conflict, strategy);
|
|
13
|
+
return { ...conflict, resolution };
|
|
14
|
+
}
|
|
15
|
+
function determineResolution(conflict, strategy) {
|
|
16
|
+
switch (strategy) {
|
|
17
|
+
case 'spec-wins':
|
|
18
|
+
return 'planu-kept';
|
|
19
|
+
case 'external-wins':
|
|
20
|
+
return 'external-applied';
|
|
21
|
+
case 'newest-wins':
|
|
22
|
+
return resolveByTimestamp(conflict.planuValue, conflict.externalValue);
|
|
23
|
+
case 'manual':
|
|
24
|
+
return 'pending-manual';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse ISO timestamp from a value string of the form "status|2024-01-01T00:00:00.000Z".
|
|
29
|
+
* If the value does not contain a timestamp suffix, returns null.
|
|
30
|
+
*/
|
|
31
|
+
function extractTimestamp(value) {
|
|
32
|
+
const idx = value.lastIndexOf('|');
|
|
33
|
+
if (idx === -1) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const ts = value.slice(idx + 1);
|
|
37
|
+
const d = new Date(ts);
|
|
38
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
39
|
+
}
|
|
40
|
+
function resolveByTimestamp(planuValue, externalValue) {
|
|
41
|
+
const planuTs = extractTimestamp(planuValue);
|
|
42
|
+
const externalTs = extractTimestamp(externalValue);
|
|
43
|
+
if (planuTs === null || externalTs === null) {
|
|
44
|
+
// Cannot compare — default to spec-wins for safety
|
|
45
|
+
return 'planu-kept';
|
|
46
|
+
}
|
|
47
|
+
if (externalTs > planuTs) {
|
|
48
|
+
return 'external-applied';
|
|
49
|
+
}
|
|
50
|
+
return 'planu-kept';
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve a list of conflicts using the given strategy.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveConflicts(conflicts, strategy) {
|
|
56
|
+
return conflicts.map((c) => resolveConflict(c, strategy));
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=conflict-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict-resolver.js","sourceRoot":"","sources":["../../../src/engine/sync/conflict-resolver.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,QAA4C,EAC5C,QAA4B;IAE5B,MAAM,UAAU,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC3D,OAAO,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,mBAAmB,CAC1B,QAA4C,EAC5C,QAA4B;IAE5B,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,WAAW;YACd,OAAO,YAAY,CAAC;QAEtB,KAAK,eAAe;YAClB,OAAO,kBAAkB,CAAC;QAE5B,KAAK,aAAa;YAChB,OAAO,kBAAkB,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;QAEzE,KAAK,QAAQ;YACX,OAAO,gBAAgB,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,kBAAkB,CACzB,UAAkB,EAClB,aAAqB;IAErB,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAEnD,IAAI,OAAO,KAAK,IAAI,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QAC5C,mDAAmD;QACnD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,UAAU,GAAG,OAAO,EAAE,CAAC;QACzB,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,SAA+C,EAC/C,QAA4B;IAE5B,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PmPullSyncResult, PmConflictStrategy } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Pull updates from Monday.com into Planu.
|
|
4
|
+
*
|
|
5
|
+
* Compares current Planu spec status against Monday.com item column values,
|
|
6
|
+
* detecting divergence and resolving conflicts per the chosen strategy.
|
|
7
|
+
*/
|
|
8
|
+
export declare function pullFromMonday(projectPath: string, conflictStrategy: PmConflictStrategy): Promise<PmPullSyncResult>;
|
|
9
|
+
//# sourceMappingURL=monday-puller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monday-puller.d.ts","sourceRoot":"","sources":["../../../src/engine/sync/monday-puller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAEhB,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAM9B;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,kBAAkB,GACnC,OAAO,CAAC,gBAAgB,CAAC,CAgE3B"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { getMondayConfig, getMondaySyncMap } from '../../storage/monday-config-store.js';
|
|
2
|
+
import { getSpec } from '../../storage/spec-store.js';
|
|
3
|
+
import { hashProjectPath } from '../../storage/base-store.js';
|
|
4
|
+
import { resolveConflicts } from './conflict-resolver.js';
|
|
5
|
+
/**
|
|
6
|
+
* Pull updates from Monday.com into Planu.
|
|
7
|
+
*
|
|
8
|
+
* Compares current Planu spec status against Monday.com item column values,
|
|
9
|
+
* detecting divergence and resolving conflicts per the chosen strategy.
|
|
10
|
+
*/
|
|
11
|
+
export async function pullFromMonday(projectPath, conflictStrategy) {
|
|
12
|
+
const config = await getMondayConfig(projectPath);
|
|
13
|
+
if (config === null) {
|
|
14
|
+
throw new Error('Monday.com not configured. Run configure_monday first.');
|
|
15
|
+
}
|
|
16
|
+
const projectId = hashProjectPath(projectPath);
|
|
17
|
+
const syncMap = await getMondaySyncMap(projectPath);
|
|
18
|
+
const entries = Object.values(syncMap);
|
|
19
|
+
const pulled = [];
|
|
20
|
+
const rawConflicts = [];
|
|
21
|
+
const now = new Date().toISOString();
|
|
22
|
+
for (const entry of entries) {
|
|
23
|
+
const spec = await getSpec(projectId, entry.specId);
|
|
24
|
+
if (spec === null) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
28
|
+
const columnId = config.columnMapping?.['status'] ?? 'status';
|
|
29
|
+
const liveStatus = await fetchMondayItemStatus(config.apiKey, entry.itemId, columnId);
|
|
30
|
+
if (liveStatus === null) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (liveStatus === spec.status) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
rawConflicts.push({
|
|
37
|
+
specId: spec.id,
|
|
38
|
+
field: 'status',
|
|
39
|
+
planuValue: spec.status,
|
|
40
|
+
externalValue: liveStatus,
|
|
41
|
+
strategy: conflictStrategy,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const conflicts = resolveConflicts(rawConflicts, conflictStrategy);
|
|
45
|
+
for (const conflict of conflicts) {
|
|
46
|
+
if (conflict.resolution === 'external-applied') {
|
|
47
|
+
pulled.push({
|
|
48
|
+
externalId: syncMap[conflict.specId]?.itemId ?? '',
|
|
49
|
+
externalTitle: conflict.specId,
|
|
50
|
+
specId: conflict.specId,
|
|
51
|
+
field: conflict.field,
|
|
52
|
+
oldValue: conflict.planuValue,
|
|
53
|
+
newValue: conflict.externalValue,
|
|
54
|
+
appliedAt: now,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
integration: 'monday',
|
|
60
|
+
pulled,
|
|
61
|
+
conflicts,
|
|
62
|
+
newSpecsCreated: [],
|
|
63
|
+
executedAt: now,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Fetch the status column value of a Monday.com item via GraphQL API.
|
|
68
|
+
* Returns a normalized string or null on failure.
|
|
69
|
+
*/
|
|
70
|
+
async function fetchMondayItemStatus(apiKey, itemId, columnId) {
|
|
71
|
+
const query = `
|
|
72
|
+
query {
|
|
73
|
+
items(ids: [${itemId}]) {
|
|
74
|
+
column_values(ids: ["${columnId}"]) {
|
|
75
|
+
id
|
|
76
|
+
text
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
81
|
+
try {
|
|
82
|
+
const response = await fetch('https://api.monday.com/v2', {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
headers: {
|
|
85
|
+
Authorization: apiKey,
|
|
86
|
+
'Content-Type': 'application/json',
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify({ query }),
|
|
89
|
+
});
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const data = (await response.json());
|
|
94
|
+
const items = data.data?.items;
|
|
95
|
+
if (items === undefined || items.length === 0) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const firstItem = items[0];
|
|
99
|
+
if (firstItem === undefined) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const colValues = firstItem.column_values ?? [];
|
|
103
|
+
const col = colValues.find((cv) => cv.id === columnId);
|
|
104
|
+
return col?.text ?? null;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=monday-puller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monday-puller.js","sourceRoot":"","sources":["../../../src/engine/sync/monday-puller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PmPullSyncResult, PmConflictStrategy } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Pull updates from Notion into Planu.
|
|
4
|
+
*
|
|
5
|
+
* Implementation note: Planu operates as an MCP server without persistent
|
|
6
|
+
* HTTP credentials at runtime. Actual Notion API reads would require the
|
|
7
|
+
* user's token to be available in the current process. This implementation
|
|
8
|
+
* performs a local-cache diff: it compares the current Planu spec status
|
|
9
|
+
* against the last-synced status stored in the sync map, surfacing any
|
|
10
|
+
* local changes that have not been pushed yet as "conflicts" from the
|
|
11
|
+
* perspective of the external system. A full bidirectional pull (reading
|
|
12
|
+
* live Notion pages) is performed when the token is available via fetch.
|
|
13
|
+
*/
|
|
14
|
+
export declare function pullFromNotion(projectPath: string, conflictStrategy: PmConflictStrategy): Promise<PmPullSyncResult>;
|
|
15
|
+
//# sourceMappingURL=notion-puller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notion-puller.d.ts","sourceRoot":"","sources":["../../../src/engine/sync/notion-puller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAEhB,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAM9B;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,kBAAkB,GACnC,OAAO,CAAC,gBAAgB,CAAC,CAmE3B"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { getNotionConfig, getNotionSyncMap } from '../../storage/notion-config-store.js';
|
|
2
|
+
import { getSpec } from '../../storage/spec-store.js';
|
|
3
|
+
import { hashProjectPath } from '../../storage/base-store.js';
|
|
4
|
+
import { resolveConflicts } from './conflict-resolver.js';
|
|
5
|
+
/**
|
|
6
|
+
* Pull updates from Notion into Planu.
|
|
7
|
+
*
|
|
8
|
+
* Implementation note: Planu operates as an MCP server without persistent
|
|
9
|
+
* HTTP credentials at runtime. Actual Notion API reads would require the
|
|
10
|
+
* user's token to be available in the current process. This implementation
|
|
11
|
+
* performs a local-cache diff: it compares the current Planu spec status
|
|
12
|
+
* against the last-synced status stored in the sync map, surfacing any
|
|
13
|
+
* local changes that have not been pushed yet as "conflicts" from the
|
|
14
|
+
* perspective of the external system. A full bidirectional pull (reading
|
|
15
|
+
* live Notion pages) is performed when the token is available via fetch.
|
|
16
|
+
*/
|
|
17
|
+
export async function pullFromNotion(projectPath, conflictStrategy) {
|
|
18
|
+
const config = await getNotionConfig(projectPath);
|
|
19
|
+
if (config === null) {
|
|
20
|
+
throw new Error('Notion not configured. Run configure_notion first.');
|
|
21
|
+
}
|
|
22
|
+
const projectId = hashProjectPath(projectPath);
|
|
23
|
+
const syncMap = await getNotionSyncMap(projectPath);
|
|
24
|
+
const entries = Object.values(syncMap);
|
|
25
|
+
const pulled = [];
|
|
26
|
+
const rawConflicts = [];
|
|
27
|
+
const now = new Date().toISOString();
|
|
28
|
+
for (const entry of entries) {
|
|
29
|
+
const spec = await getSpec(projectId, entry.specId);
|
|
30
|
+
if (spec === null) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// Attempt live fetch from Notion API
|
|
34
|
+
const liveStatus = await fetchNotionPageStatus(config.token, entry.pageId);
|
|
35
|
+
if (liveStatus === null) {
|
|
36
|
+
// API unavailable or page not found — skip this entry
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (liveStatus === spec.status) {
|
|
40
|
+
// No divergence
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Divergence detected: spec status differs from Notion page status
|
|
44
|
+
rawConflicts.push({
|
|
45
|
+
specId: spec.id,
|
|
46
|
+
field: 'status',
|
|
47
|
+
planuValue: spec.status,
|
|
48
|
+
externalValue: liveStatus,
|
|
49
|
+
strategy: conflictStrategy,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const conflicts = resolveConflicts(rawConflicts, conflictStrategy);
|
|
53
|
+
// Record applied updates
|
|
54
|
+
for (const conflict of conflicts) {
|
|
55
|
+
if (conflict.resolution === 'external-applied') {
|
|
56
|
+
pulled.push({
|
|
57
|
+
externalId: syncMap[conflict.specId]?.pageId ?? '',
|
|
58
|
+
externalTitle: conflict.specId,
|
|
59
|
+
specId: conflict.specId,
|
|
60
|
+
field: conflict.field,
|
|
61
|
+
oldValue: conflict.planuValue,
|
|
62
|
+
newValue: conflict.externalValue,
|
|
63
|
+
appliedAt: now,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
integration: 'notion',
|
|
69
|
+
pulled,
|
|
70
|
+
conflicts,
|
|
71
|
+
newSpecsCreated: [],
|
|
72
|
+
executedAt: now,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fetch the current status of a Notion page via the Notion API.
|
|
77
|
+
* Returns null if the request fails (token missing, network error, etc.)
|
|
78
|
+
*/
|
|
79
|
+
async function fetchNotionPageStatus(token, pageId) {
|
|
80
|
+
try {
|
|
81
|
+
const response = await fetch(`https://api.notion.com/v1/pages/${pageId}`, {
|
|
82
|
+
headers: {
|
|
83
|
+
Authorization: `Bearer ${token}`,
|
|
84
|
+
'Notion-Version': '2022-06-28',
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const data = (await response.json());
|
|
91
|
+
// Try common status property names
|
|
92
|
+
const props = data.properties ?? {};
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
94
|
+
const statusProp = props['status'] ?? props['Status'] ?? props['select'] ?? props['Select'];
|
|
95
|
+
return statusProp?.select?.name ?? null;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=notion-puller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notion-puller.js","sourceRoot":"","sources":["../../../src/engine/sync/notion-puller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { VerifierScanResult } from '../../types/index.js';
|
|
2
|
+
export type { VerifierScanResult };
|
|
3
|
+
/**
|
|
4
|
+
* Scans the codebase for evidence that a spec has been implemented.
|
|
5
|
+
* Searches source files, git commits, and test files.
|
|
6
|
+
*/
|
|
7
|
+
export declare function scanForSpecEvidence(specId: string, projectPath: string): Promise<VerifierScanResult>;
|
|
8
|
+
//# sourceMappingURL=code-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-scanner.d.ts","sourceRoot":"","sources":["../../../src/engine/verifier/code-scanner.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,YAAY,EAAE,kBAAkB,EAAE,CAAC;AAsCnC;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAwC7B"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// engine/verifier/code-scanner.ts — Spec evidence scanner (SPEC-406)
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { exec } from 'node:child_process';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { glob } from 'glob';
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
const SOURCE_GLOBS = ['**/*.ts', '**/*.js', '**/*.py', '**/*.go', '**/*.java', '**/*.rs'];
|
|
8
|
+
const TEST_GLOBS = ['**/*.test.ts', '**/*.spec.ts', '**/*.test.js', '**/*.spec.js'];
|
|
9
|
+
const IGNORE_PATTERNS = ['**/node_modules/**', '**/dist/**', '**/.git/**', '**/build/**'];
|
|
10
|
+
/**
|
|
11
|
+
* Searches a file for a string reference.
|
|
12
|
+
*/
|
|
13
|
+
async function fileContains(filePath, term) {
|
|
14
|
+
try {
|
|
15
|
+
const content = await readFile(filePath, 'utf-8');
|
|
16
|
+
return content.includes(term);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Retrieves git commit messages that reference the spec ID.
|
|
24
|
+
*/
|
|
25
|
+
async function findGitCommits(specId, projectPath) {
|
|
26
|
+
try {
|
|
27
|
+
const { stdout } = await execAsync(`git log --oneline --all --grep="${specId}" 2>/dev/null | head -20`, { cwd: projectPath });
|
|
28
|
+
return stdout
|
|
29
|
+
.split('\n')
|
|
30
|
+
.map((l) => l.trim())
|
|
31
|
+
.filter(Boolean);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Scans the codebase for evidence that a spec has been implemented.
|
|
39
|
+
* Searches source files, git commits, and test files.
|
|
40
|
+
*/
|
|
41
|
+
export async function scanForSpecEvidence(specId, projectPath) {
|
|
42
|
+
// Find all source files containing the spec ID
|
|
43
|
+
const allFiles = await glob(SOURCE_GLOBS, {
|
|
44
|
+
cwd: projectPath,
|
|
45
|
+
ignore: IGNORE_PATTERNS,
|
|
46
|
+
absolute: true,
|
|
47
|
+
});
|
|
48
|
+
const filesFoundResults = await Promise.all(allFiles.map(async (f) => {
|
|
49
|
+
const found = await fileContains(f, specId);
|
|
50
|
+
return found ? f : null;
|
|
51
|
+
}));
|
|
52
|
+
const filesFound = filesFoundResults.filter((f) => f !== null);
|
|
53
|
+
// Find git commits mentioning the spec ID
|
|
54
|
+
const gitCommitsFound = await findGitCommits(specId, projectPath);
|
|
55
|
+
// Find test files referencing the spec ID or its slug
|
|
56
|
+
const testFiles = await glob(TEST_GLOBS, {
|
|
57
|
+
cwd: projectPath,
|
|
58
|
+
ignore: IGNORE_PATTERNS,
|
|
59
|
+
absolute: true,
|
|
60
|
+
});
|
|
61
|
+
const testFilesResults = await Promise.all(testFiles.map(async (f) => {
|
|
62
|
+
const found = await fileContains(f, specId);
|
|
63
|
+
return found ? f : null;
|
|
64
|
+
}));
|
|
65
|
+
const testFilesFound = testFilesResults.filter((f) => f !== null);
|
|
66
|
+
return {
|
|
67
|
+
specId,
|
|
68
|
+
filesFound,
|
|
69
|
+
gitCommitsFound,
|
|
70
|
+
testFilesFound,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=code-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-scanner.js","sourceRoot":"","sources":["../../../src/engine/verifier/code-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SpecComplianceScore } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses acceptance criteria lines from spec.md content.
|
|
4
|
+
* Recognizes both "- [ ]" (unchecked) and "- [x]" (checked) task list items.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseCriteria(content: string): string[];
|
|
7
|
+
/**
|
|
8
|
+
* Computes a compliance score for a spec by matching each acceptance criterion
|
|
9
|
+
* against the codebase.
|
|
10
|
+
*
|
|
11
|
+
* Scoring formula:
|
|
12
|
+
* - verified criterion = 100/N points
|
|
13
|
+
* - partial criterion = 50/N points
|
|
14
|
+
* - unverified criterion = 0 points
|
|
15
|
+
*/
|
|
16
|
+
export declare function scoreCompliance(specId: string, projectPath: string): Promise<SpecComplianceScore>;
|
|
17
|
+
//# sourceMappingURL=compliance-scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compliance-scorer.d.ts","sourceRoot":"","sources":["../../../src/engine/verifier/compliance-scorer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAgBhE;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBvD;AAuBD;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CA0E9B"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// engine/verifier/compliance-scorer.ts — Spec compliance scoring (SPEC-406)
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { glob } from 'glob';
|
|
4
|
+
import { matchCriterion } from './criterion-matcher.js';
|
|
5
|
+
/**
|
|
6
|
+
* Determines compliance level based on score.
|
|
7
|
+
*/
|
|
8
|
+
function toLevel(score) {
|
|
9
|
+
if (score >= 80) {
|
|
10
|
+
return 'compliant';
|
|
11
|
+
}
|
|
12
|
+
if (score >= 60) {
|
|
13
|
+
return 'partial';
|
|
14
|
+
}
|
|
15
|
+
return 'non-compliant';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parses acceptance criteria lines from spec.md content.
|
|
19
|
+
* Recognizes both "- [ ]" (unchecked) and "- [x]" (checked) task list items.
|
|
20
|
+
*/
|
|
21
|
+
export function parseCriteria(content) {
|
|
22
|
+
const lines = content.split('\n');
|
|
23
|
+
const criteria = [];
|
|
24
|
+
for (const line of lines) {
|
|
25
|
+
const trimmed = line.trim();
|
|
26
|
+
// Match "- [ ] ..." or "- [x] ..." or "- [X] ..."
|
|
27
|
+
if (/^-\s*\[[xX ]\]\s+/.test(trimmed)) {
|
|
28
|
+
const text = trimmed.replace(/^-\s*\[[xX ]\]\s+/, '').trim();
|
|
29
|
+
if (text.length > 0) {
|
|
30
|
+
criteria.push(text);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return criteria;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Locates the spec.md file for a given specId within the projectPath.
|
|
38
|
+
* Searches in common locations: planu/specs/SPEC-NNN-slug or specs/SPEC-NNN-slug.
|
|
39
|
+
*/
|
|
40
|
+
async function findSpecFile(specId, projectPath) {
|
|
41
|
+
const patterns = [
|
|
42
|
+
`planu/specs/${specId}-*/spec.md`,
|
|
43
|
+
`specs/${specId}-*/spec.md`,
|
|
44
|
+
`planu/specs/${specId}/spec.md`,
|
|
45
|
+
`specs/${specId}/spec.md`,
|
|
46
|
+
];
|
|
47
|
+
for (const pattern of patterns) {
|
|
48
|
+
const matches = await glob(pattern, { cwd: projectPath, absolute: true });
|
|
49
|
+
if (matches.length > 0 && matches[0] !== undefined) {
|
|
50
|
+
return matches[0];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Computes a compliance score for a spec by matching each acceptance criterion
|
|
57
|
+
* against the codebase.
|
|
58
|
+
*
|
|
59
|
+
* Scoring formula:
|
|
60
|
+
* - verified criterion = 100/N points
|
|
61
|
+
* - partial criterion = 50/N points
|
|
62
|
+
* - unverified criterion = 0 points
|
|
63
|
+
*/
|
|
64
|
+
export async function scoreCompliance(specId, projectPath) {
|
|
65
|
+
const checkedAt = new Date().toISOString();
|
|
66
|
+
// Locate spec.md
|
|
67
|
+
const specFile = await findSpecFile(specId, projectPath);
|
|
68
|
+
if (specFile === null) {
|
|
69
|
+
return {
|
|
70
|
+
specId,
|
|
71
|
+
score: 0,
|
|
72
|
+
level: 'non-compliant',
|
|
73
|
+
verifiedCriteria: 0,
|
|
74
|
+
partialCriteria: 0,
|
|
75
|
+
unverifiedCriteria: 0,
|
|
76
|
+
totalCriteria: 0,
|
|
77
|
+
criteriaDetails: [],
|
|
78
|
+
checkedAt,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// Read and parse acceptance criteria
|
|
82
|
+
const content = await readFile(specFile, 'utf-8');
|
|
83
|
+
const criteria = parseCriteria(content);
|
|
84
|
+
if (criteria.length === 0) {
|
|
85
|
+
return {
|
|
86
|
+
specId,
|
|
87
|
+
score: 0,
|
|
88
|
+
level: 'non-compliant',
|
|
89
|
+
verifiedCriteria: 0,
|
|
90
|
+
partialCriteria: 0,
|
|
91
|
+
unverifiedCriteria: 0,
|
|
92
|
+
totalCriteria: 0,
|
|
93
|
+
criteriaDetails: [],
|
|
94
|
+
checkedAt,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Match each criterion against the codebase
|
|
98
|
+
const criteriaDetails = await Promise.all(criteria.map((criterion) => matchCriterion(criterion, projectPath)));
|
|
99
|
+
// Compute score
|
|
100
|
+
const N = criteria.length;
|
|
101
|
+
let rawScore = 0;
|
|
102
|
+
let verifiedCriteria = 0;
|
|
103
|
+
let partialCriteria = 0;
|
|
104
|
+
let unverifiedCriteria = 0;
|
|
105
|
+
for (const detail of criteriaDetails) {
|
|
106
|
+
if (detail.status === 'verified') {
|
|
107
|
+
rawScore += 100 / N;
|
|
108
|
+
verifiedCriteria++;
|
|
109
|
+
}
|
|
110
|
+
else if (detail.status === 'partial') {
|
|
111
|
+
rawScore += 50 / N;
|
|
112
|
+
partialCriteria++;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
unverifiedCriteria++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const score = Math.round(rawScore * 10) / 10;
|
|
119
|
+
return {
|
|
120
|
+
specId,
|
|
121
|
+
score,
|
|
122
|
+
level: toLevel(score),
|
|
123
|
+
verifiedCriteria,
|
|
124
|
+
partialCriteria,
|
|
125
|
+
unverifiedCriteria,
|
|
126
|
+
totalCriteria: N,
|
|
127
|
+
criteriaDetails,
|
|
128
|
+
checkedAt,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=compliance-scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compliance-scorer.js","sourceRoot":"","sources":["../../../src/engine/verifier/compliance-scorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CriterionMatch } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts meaningful keywords from a criterion text.
|
|
4
|
+
* Captures: camelCase/PascalCase identifiers, route patterns,
|
|
5
|
+
* quoted strings, and significant technical terms.
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractKeywords(criterion: string): string[];
|
|
8
|
+
/**
|
|
9
|
+
* Scans the codebase for evidence matching the criterion.
|
|
10
|
+
* If 2+ keywords found across files → verified
|
|
11
|
+
* If 1 keyword found → partial
|
|
12
|
+
* If 0 keywords found → unverified
|
|
13
|
+
*/
|
|
14
|
+
export declare function matchCriterion(criterion: string, projectPath: string): Promise<CriterionMatch>;
|
|
15
|
+
//# sourceMappingURL=criterion-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"criterion-matcher.d.ts","sourceRoot":"","sources":["../../../src/engine/verifier/criterion-matcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA+F3D;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAyC3D;AAkBD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC,CAyDzB"}
|