@planu/cli 0.90.1 → 0.91.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/license-plans.json +3 -1
- package/dist/engine/batch-script-generator/index.d.ts +6 -0
- package/dist/engine/batch-script-generator/index.d.ts.map +1 -0
- package/dist/engine/batch-script-generator/index.js +126 -0
- package/dist/engine/batch-script-generator/index.js.map +1 -0
- package/dist/engine/ci-generator/index.d.ts.map +1 -1
- package/dist/engine/ci-generator/index.js +32 -1
- package/dist/engine/ci-generator/index.js.map +1 -1
- package/dist/engine/ci-generator/output-formats.d.ts +15 -0
- package/dist/engine/ci-generator/output-formats.d.ts.map +1 -0
- package/dist/engine/ci-generator/output-formats.js +52 -0
- package/dist/engine/ci-generator/output-formats.js.map +1 -0
- package/dist/engine/claude-config-auditor/claudemd-auditor.d.ts.map +1 -1
- package/dist/engine/claude-config-auditor/claudemd-auditor.js +139 -31
- package/dist/engine/claude-config-auditor/claudemd-auditor.js.map +1 -1
- package/dist/engine/claude-config-auditor/rules-auditor.d.ts.map +1 -1
- package/dist/engine/claude-config-auditor/rules-auditor.js +87 -49
- package/dist/engine/claude-config-auditor/rules-auditor.js.map +1 -1
- package/dist/engine/claude-config-auditor/scoring.d.ts.map +1 -1
- package/dist/engine/claude-config-auditor/scoring.js +37 -1
- package/dist/engine/claude-config-auditor/scoring.js.map +1 -1
- package/dist/engine/claude-config-auditor/settings-auditor.d.ts.map +1 -1
- package/dist/engine/claude-config-auditor/settings-auditor.js +55 -40
- package/dist/engine/claude-config-auditor/settings-auditor.js.map +1 -1
- package/dist/engine/config-schemas.d.ts.map +1 -1
- package/dist/engine/config-schemas.js +1 -0
- package/dist/engine/config-schemas.js.map +1 -1
- package/dist/engine/context-advisor/btw-advisor.d.ts +11 -0
- package/dist/engine/context-advisor/btw-advisor.d.ts.map +1 -0
- package/dist/engine/context-advisor/btw-advisor.js +29 -0
- package/dist/engine/context-advisor/btw-advisor.js.map +1 -0
- package/dist/engine/facilitate/context-loader.d.ts +12 -0
- package/dist/engine/facilitate/context-loader.d.ts.map +1 -0
- package/dist/engine/facilitate/context-loader.js +156 -0
- package/dist/engine/facilitate/context-loader.js.map +1 -0
- package/dist/engine/facilitate/intent-classifier.d.ts +6 -0
- package/dist/engine/facilitate/intent-classifier.d.ts.map +1 -0
- package/dist/engine/facilitate/intent-classifier.js +153 -0
- package/dist/engine/facilitate/intent-classifier.js.map +1 -0
- package/dist/engine/facilitate/plan-parser.d.ts +7 -0
- package/dist/engine/facilitate/plan-parser.d.ts.map +1 -0
- package/dist/engine/facilitate/plan-parser.js +115 -0
- package/dist/engine/facilitate/plan-parser.js.map +1 -0
- package/dist/engine/facilitate/router.d.ts +6 -0
- package/dist/engine/facilitate/router.d.ts.map +1 -0
- package/dist/engine/facilitate/router.js +71 -0
- package/dist/engine/facilitate/router.js.map +1 -0
- package/dist/engine/hooks/context-injector.d.ts +11 -0
- package/dist/engine/hooks/context-injector.d.ts.map +1 -0
- package/dist/engine/hooks/context-injector.js +163 -0
- package/dist/engine/hooks/context-injector.js.map +1 -0
- package/dist/engine/hooks/hook-templates.d.ts +16 -0
- package/dist/engine/hooks/hook-templates.d.ts.map +1 -0
- package/dist/engine/hooks/hook-templates.js +148 -0
- package/dist/engine/hooks/hook-templates.js.map +1 -0
- package/dist/engine/hooks/plan-mode-detector.d.ts +27 -0
- package/dist/engine/hooks/plan-mode-detector.d.ts.map +1 -0
- package/dist/engine/hooks/plan-mode-detector.js +68 -0
- package/dist/engine/hooks/plan-mode-detector.js.map +1 -0
- package/dist/engine/hooks/plan-mode-scripts.d.ts +10 -0
- package/dist/engine/hooks/plan-mode-scripts.d.ts.map +1 -0
- package/dist/engine/hooks/plan-mode-scripts.js +45 -0
- package/dist/engine/hooks/plan-mode-scripts.js.map +1 -0
- package/dist/engine/model-router/complexity-analyzer.d.ts +9 -1
- package/dist/engine/model-router/complexity-analyzer.d.ts.map +1 -1
- package/dist/engine/model-router/complexity-analyzer.js +44 -1
- package/dist/engine/model-router/complexity-analyzer.js.map +1 -1
- package/dist/engine/model-router/rules-engine.d.ts.map +1 -1
- package/dist/engine/model-router/rules-engine.js +14 -1
- package/dist/engine/model-router/rules-engine.js.map +1 -1
- package/dist/engine/nfr-profile-detector.d.ts.map +1 -1
- package/dist/engine/nfr-profile-detector.js +2 -1
- package/dist/engine/nfr-profile-detector.js.map +1 -1
- package/dist/engine/spec-coverage/core.js.map +1 -1
- package/dist/engine/spec-migrator/frontmatter-parser.d.ts.map +1 -1
- package/dist/engine/spec-migrator/frontmatter-parser.js.map +1 -1
- package/dist/engine/spec-summary-html.d.ts.map +1 -1
- package/dist/engine/spec-summary-html.js +1 -1
- package/dist/engine/spec-summary-html.js.map +1 -1
- package/dist/engine/team-planner/writer-reviewer.d.ts +12 -0
- package/dist/engine/team-planner/writer-reviewer.d.ts.map +1 -0
- package/dist/engine/team-planner/writer-reviewer.js +48 -0
- package/dist/engine/team-planner/writer-reviewer.js.map +1 -0
- package/dist/engine/tool-groups/group-manager.js.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/storage/drift-cache-store.js.map +1 -1
- package/dist/storage/error-telemetry-store.js.map +1 -1
- package/dist/storage/federation-store.js.map +1 -1
- package/dist/storage/global-store.js.map +1 -1
- package/dist/storage/ideas-store.d.ts.map +1 -1
- package/dist/storage/ideas-store.js.map +1 -1
- package/dist/storage/living-dashboard-store.js.map +1 -1
- package/dist/storage/metrics-store.js.map +1 -1
- package/dist/storage/rbac-store.js.map +1 -1
- package/dist/storage/spec-observability-store.js.map +1 -1
- package/dist/storage/worker-metrics-store.js.map +1 -1
- package/dist/storage/worker-store.js.map +1 -1
- package/dist/tools/checkpoint-handler.d.ts.map +1 -1
- package/dist/tools/checkpoint-handler.js +11 -0
- package/dist/tools/checkpoint-handler.js.map +1 -1
- package/dist/tools/clarify-requirements/interview-mode.d.ts +42 -0
- package/dist/tools/clarify-requirements/interview-mode.d.ts.map +1 -0
- package/dist/tools/clarify-requirements/interview-mode.js +342 -0
- package/dist/tools/clarify-requirements/interview-mode.js.map +1 -0
- package/dist/tools/configure-workers-handler.d.ts.map +1 -1
- package/dist/tools/configure-workers-handler.js +81 -0
- package/dist/tools/configure-workers-handler.js.map +1 -1
- package/dist/tools/facilitate.d.ts +1 -5
- package/dist/tools/facilitate.d.ts.map +1 -1
- package/dist/tools/facilitate.js +100 -23
- package/dist/tools/facilitate.js.map +1 -1
- package/dist/tools/generate-automation-guide.d.ts +10 -0
- package/dist/tools/generate-automation-guide.d.ts.map +1 -0
- package/dist/tools/generate-automation-guide.js +222 -0
- package/dist/tools/generate-automation-guide.js.map +1 -0
- package/dist/tools/generate-batch-script.d.ts +27 -0
- package/dist/tools/generate-batch-script.d.ts.map +1 -0
- package/dist/tools/generate-batch-script.js +77 -0
- package/dist/tools/generate-batch-script.js.map +1 -0
- package/dist/tools/generate-sub-agent.d.ts.map +1 -1
- package/dist/tools/generate-sub-agent.js +16 -2
- package/dist/tools/generate-sub-agent.js.map +1 -1
- package/dist/tools/git/branch-ops.d.ts +18 -0
- package/dist/tools/git/branch-ops.d.ts.map +1 -1
- package/dist/tools/git/branch-ops.js +121 -0
- package/dist/tools/git/branch-ops.js.map +1 -1
- package/dist/tools/git/pr-ops.d.ts.map +1 -1
- package/dist/tools/git/pr-ops.js +7 -0
- package/dist/tools/git/pr-ops.js.map +1 -1
- package/dist/tools/init-project/git-setup.d.ts.map +1 -1
- package/dist/tools/init-project/git-setup.js.map +1 -1
- package/dist/tools/init-project/handler.d.ts.map +1 -1
- package/dist/tools/init-project/handler.js +5 -2
- package/dist/tools/init-project/handler.js.map +1 -1
- package/dist/tools/init-project/hooks-configurator.d.ts +17 -0
- package/dist/tools/init-project/hooks-configurator.d.ts.map +1 -0
- package/dist/tools/init-project/hooks-configurator.js +102 -0
- package/dist/tools/init-project/hooks-configurator.js.map +1 -0
- package/dist/tools/init-project/lifecycle-helpers.d.ts.map +1 -1
- package/dist/tools/init-project/lifecycle-helpers.js +1 -1
- package/dist/tools/init-project/lifecycle-helpers.js.map +1 -1
- package/dist/tools/init-project/migration-runner.d.ts.map +1 -1
- package/dist/tools/init-project/migration-runner.js +1 -1
- package/dist/tools/init-project/migration-runner.js.map +1 -1
- package/dist/tools/init-project/planu-workflow-generator.d.ts +21 -0
- package/dist/tools/init-project/planu-workflow-generator.d.ts.map +1 -0
- package/dist/tools/init-project/planu-workflow-generator.js +73 -0
- package/dist/tools/init-project/planu-workflow-generator.js.map +1 -0
- package/dist/tools/init-project/rules-generator.d.ts +15 -0
- package/dist/tools/init-project/rules-generator.d.ts.map +1 -0
- package/dist/tools/init-project/rules-generator.js +110 -0
- package/dist/tools/init-project/rules-generator.js.map +1 -0
- package/dist/tools/init-project/scaffold-writer.d.ts +3 -0
- package/dist/tools/init-project/scaffold-writer.d.ts.map +1 -1
- package/dist/tools/init-project/scaffold-writer.js +33 -0
- package/dist/tools/init-project/scaffold-writer.js.map +1 -1
- package/dist/tools/integrate-pm.js.map +1 -1
- package/dist/tools/license-status.js +4 -4
- package/dist/tools/license-status.js.map +1 -1
- package/dist/tools/list-backlog-handler.d.ts.map +1 -1
- package/dist/tools/list-backlog-handler.js +4 -1
- package/dist/tools/list-backlog-handler.js.map +1 -1
- package/dist/tools/list-sessions.d.ts.map +1 -1
- package/dist/tools/list-sessions.js +8 -0
- package/dist/tools/list-sessions.js.map +1 -1
- package/dist/tools/manage-git.d.ts.map +1 -1
- package/dist/tools/manage-git.js +15 -1
- package/dist/tools/manage-git.js.map +1 -1
- package/dist/tools/orchestrate/state.js.map +1 -1
- package/dist/tools/promote-idea-handler.d.ts.map +1 -1
- package/dist/tools/promote-idea-handler.js +1 -3
- package/dist/tools/promote-idea-handler.js.map +1 -1
- package/dist/tools/recommend-model-handler.d.ts.map +1 -1
- package/dist/tools/recommend-model-handler.js +7 -0
- package/dist/tools/recommend-model-handler.js.map +1 -1
- package/dist/tools/register-backlog-tools.d.ts.map +1 -1
- package/dist/tools/register-backlog-tools.js +3 -13
- package/dist/tools/register-backlog-tools.js.map +1 -1
- package/dist/tools/register-facilitator-tools.d.ts.map +1 -1
- package/dist/tools/register-facilitator-tools.js +12 -7
- package/dist/tools/register-facilitator-tools.js.map +1 -1
- package/dist/tools/register-generate-automation-guide.d.ts +3 -0
- package/dist/tools/register-generate-automation-guide.d.ts.map +1 -0
- package/dist/tools/register-generate-automation-guide.js +10 -0
- package/dist/tools/register-generate-automation-guide.js.map +1 -0
- package/dist/tools/register-generate-batch-script.d.ts +3 -0
- package/dist/tools/register-generate-batch-script.d.ts.map +1 -0
- package/dist/tools/register-generate-batch-script.js +10 -0
- package/dist/tools/register-generate-batch-script.js.map +1 -0
- package/dist/tools/register-hooks-tools.d.ts.map +1 -1
- package/dist/tools/register-hooks-tools.js +27 -0
- package/dist/tools/register-hooks-tools.js.map +1 -1
- package/dist/tools/register-platform-tools/design-stack-tools.d.ts.map +1 -1
- package/dist/tools/register-platform-tools/design-stack-tools.js +4 -0
- package/dist/tools/register-platform-tools/design-stack-tools.js.map +1 -1
- package/dist/tools/restore-session.d.ts.map +1 -1
- package/dist/tools/restore-session.js +10 -0
- package/dist/tools/restore-session.js.map +1 -1
- package/dist/tools/schemas/ide-config.d.ts +2 -2
- package/dist/tools/schemas/workers-schema.d.ts +1 -0
- package/dist/tools/schemas/workers-schema.d.ts.map +1 -1
- package/dist/tools/schemas/workers-schema.js +10 -2
- package/dist/tools/schemas/workers-schema.js.map +1 -1
- package/dist/tools/start-hooks.d.ts.map +1 -1
- package/dist/tools/start-hooks.js +104 -1
- package/dist/tools/start-hooks.js.map +1 -1
- package/dist/tools/status-handler.d.ts.map +1 -1
- package/dist/tools/status-handler.js +9 -0
- package/dist/tools/status-handler.js.map +1 -1
- package/dist/types/analysis.d.ts +8 -0
- package/dist/types/analysis.d.ts.map +1 -1
- package/dist/types/batch-script.d.ts +36 -0
- package/dist/types/batch-script.d.ts.map +1 -0
- package/dist/types/batch-script.js +3 -0
- package/dist/types/batch-script.js.map +1 -0
- package/dist/types/ci.d.ts +4 -0
- package/dist/types/ci.d.ts.map +1 -1
- package/dist/types/common/tech-enums.d.ts +1 -1
- package/dist/types/common/tech-enums.d.ts.map +1 -1
- package/dist/types/execution.d.ts +9 -0
- package/dist/types/execution.d.ts.map +1 -1
- package/dist/types/facilitator.d.ts +67 -0
- package/dist/types/facilitator.d.ts.map +1 -1
- package/dist/types/file-hooks.d.ts +7 -0
- package/dist/types/file-hooks.d.ts.map +1 -1
- package/dist/types/file-hooks.js +0 -1
- package/dist/types/file-hooks.js.map +1 -1
- package/dist/types/git.d.ts +12 -0
- package/dist/types/git.d.ts.map +1 -1
- package/dist/types/hooks.d.ts +77 -0
- package/dist/types/hooks.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/model-routing.d.ts +16 -0
- package/dist/types/model-routing.d.ts.map +1 -1
- package/dist/types/project/planu-config.d.ts +6 -0
- package/dist/types/project/planu-config.d.ts.map +1 -1
- package/dist/types/session.d.ts +2 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/stack/recommend.d.ts +1 -0
- package/dist/types/stack/recommend.d.ts.map +1 -1
- package/dist/types/status.d.ts +7 -0
- package/dist/types/status.d.ts.map +1 -1
- package/dist/types/team-planner.d.ts +18 -0
- package/dist/types/team-planner.d.ts.map +1 -1
- package/dist/types/workers.d.ts +1 -1
- package/dist/types/workers.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/config/license-plans.json +3 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// engine/facilitate/context-loader.ts — SPEC-264 Loads project context from disk
|
|
2
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Internal helpers
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const ACTIVE_STATUSES = new Set(['implementing', 'approved', 'review']);
|
|
9
|
+
/**
|
|
10
|
+
* Minimal frontmatter parser — reads YAML between `---` delimiters.
|
|
11
|
+
* Supports string scalar fields only (sufficient for our use case).
|
|
12
|
+
*/
|
|
13
|
+
function parseFrontmatter(content) {
|
|
14
|
+
const match = /^---\n([\s\S]*?)\n---/m.exec(content);
|
|
15
|
+
if (!match?.[1]) {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
const result = {};
|
|
19
|
+
for (const line of match[1].split('\n')) {
|
|
20
|
+
const colonIdx = line.indexOf(':');
|
|
21
|
+
if (colonIdx === -1) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const key = line.slice(0, colonIdx).trim();
|
|
25
|
+
const value = line
|
|
26
|
+
.slice(colonIdx + 1)
|
|
27
|
+
.trim()
|
|
28
|
+
.replace(/^["']|["']$/g, '');
|
|
29
|
+
if (key === 'id') {
|
|
30
|
+
result.id = value;
|
|
31
|
+
}
|
|
32
|
+
else if (key === 'title') {
|
|
33
|
+
result.title = value;
|
|
34
|
+
}
|
|
35
|
+
else if (key === 'status') {
|
|
36
|
+
result.status = value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Compute project hash the same way base-store does (SHA-256, first 16 chars).
|
|
43
|
+
*/
|
|
44
|
+
function hashProjectPath(projectPath) {
|
|
45
|
+
return createHash('sha256').update(projectPath).digest('hex').slice(0, 16);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if two sets of keywords overlap (case-insensitive).
|
|
49
|
+
*/
|
|
50
|
+
function hasKeywordOverlap(title, keywords) {
|
|
51
|
+
const lower = title.toLowerCase();
|
|
52
|
+
return keywords.some((kw) => lower.includes(kw));
|
|
53
|
+
}
|
|
54
|
+
function toSpecRecord(s) {
|
|
55
|
+
if (typeof s.id === 'string' && typeof s.title === 'string' && typeof s.status === 'string') {
|
|
56
|
+
return { id: s.id, title: s.title, status: s.status };
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
async function loadSpecsFromFile(specsFile) {
|
|
61
|
+
try {
|
|
62
|
+
const raw = await readFile(specsFile, 'utf-8');
|
|
63
|
+
const all = JSON.parse(raw);
|
|
64
|
+
return all.flatMap((s) => {
|
|
65
|
+
const rec = toSpecRecord(s);
|
|
66
|
+
return rec ? [rec] : [];
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function loadCheckpoint(checkpointFile) {
|
|
74
|
+
try {
|
|
75
|
+
const raw = await readFile(checkpointFile, 'utf-8');
|
|
76
|
+
const state = JSON.parse(raw);
|
|
77
|
+
return typeof state.lastCheckpoint === 'string' ? state.lastCheckpoint : null;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// Public API
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
/**
|
|
87
|
+
* Load spec context directly from disk — no MCP tool calls.
|
|
88
|
+
* Gracefully handles empty/missing project directories.
|
|
89
|
+
*/
|
|
90
|
+
export async function loadContext(projectPath, keywords) {
|
|
91
|
+
const projectId = hashProjectPath(projectPath);
|
|
92
|
+
const specsFile = join('data', 'projects', projectId, 'specs.json');
|
|
93
|
+
const checkpointFile = join('data', 'projects', projectId, 'session-state.json');
|
|
94
|
+
const specs = await loadSpecsFromFile(specsFile);
|
|
95
|
+
const lastCheckpoint = await loadCheckpoint(checkpointFile);
|
|
96
|
+
const activeSpecs = specs.filter((s) => ACTIVE_STATUSES.has(s.status));
|
|
97
|
+
const relatedSpecs = specs
|
|
98
|
+
.filter((s) => !ACTIVE_STATUSES.has(s.status) && hasKeywordOverlap(s.title, keywords))
|
|
99
|
+
.slice(0, 5)
|
|
100
|
+
.map((s) => ({
|
|
101
|
+
id: s.id,
|
|
102
|
+
title: s.title,
|
|
103
|
+
relevanceReason: 'Title matches keyword from request',
|
|
104
|
+
}));
|
|
105
|
+
return {
|
|
106
|
+
activeSpecs,
|
|
107
|
+
relatedSpecs,
|
|
108
|
+
hasActiveWork: activeSpecs.length > 0,
|
|
109
|
+
lastCheckpoint,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Load context from a planu/ specs directory (alternative path — reads spec.md frontmatter).
|
|
114
|
+
* Used when data/ is not available but planu/ is present.
|
|
115
|
+
*/
|
|
116
|
+
export async function loadContextFromPlanuDir(planuSpecsDir, keywords) {
|
|
117
|
+
let entries;
|
|
118
|
+
try {
|
|
119
|
+
entries = await readdir(planuSpecsDir);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return { activeSpecs: [], relatedSpecs: [], hasActiveWork: false, lastCheckpoint: null };
|
|
123
|
+
}
|
|
124
|
+
const activeSpecs = [];
|
|
125
|
+
const relatedSpecs = [];
|
|
126
|
+
for (const entry of entries) {
|
|
127
|
+
const specMdPath = join(planuSpecsDir, entry, 'spec.md');
|
|
128
|
+
try {
|
|
129
|
+
const content = await readFile(specMdPath, 'utf-8');
|
|
130
|
+
const fm = parseFrontmatter(content);
|
|
131
|
+
if (!fm.id || !fm.title || !fm.status) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (ACTIVE_STATUSES.has(fm.status)) {
|
|
135
|
+
activeSpecs.push({ id: fm.id, title: fm.title, status: fm.status });
|
|
136
|
+
}
|
|
137
|
+
else if (hasKeywordOverlap(fm.title, keywords) && relatedSpecs.length < 5) {
|
|
138
|
+
relatedSpecs.push({
|
|
139
|
+
id: fm.id,
|
|
140
|
+
title: fm.title,
|
|
141
|
+
relevanceReason: 'Title matches keyword from request',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Skip unreadable spec
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
activeSpecs,
|
|
151
|
+
relatedSpecs,
|
|
152
|
+
hasActiveWork: activeSpecs.length > 0,
|
|
153
|
+
lastCheckpoint: null,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=context-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-loader.js","sourceRoot":"","sources":["../../../src/engine/facilitate/context-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ClassifiedIntent } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Classify a natural-language request into type, complexity, and keywords.
|
|
4
|
+
*/
|
|
5
|
+
export declare function classifyIntent(request: string): ClassifiedIntent;
|
|
6
|
+
//# sourceMappingURL=intent-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent-classifier.d.ts","sourceRoot":"","sources":["../../../src/engine/facilitate/intent-classifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAA0B,MAAM,sBAAsB,CAAC;AAuJrF;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAahE"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// engine/facilitate/intent-classifier.ts — SPEC-264 Request intent classifier
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Keyword patterns
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
const BUGFIX_RE = /\b(?:fix|bug|error|broken|crash|issue|fail|failing|exception|traceback)\b/i;
|
|
6
|
+
// Note: "what is" removed — handled by short-question path instead
|
|
7
|
+
const EXPLORATION_RE = /\b(?:explore|understand|how does|explain|learn|why does)\b/i;
|
|
8
|
+
const REFACTOR_RE = /\b(?:refactor|clean up|reorganize|restructure|simplify|rename|move)\b/i;
|
|
9
|
+
const ARCHITECTURAL_TERMS_RE = /\b(?:migrate|migration|replace|redesign|overhaul|rewrite|platform|framework)\b/i;
|
|
10
|
+
const COMPLEXITY_TERMS_PATTERN = '\\b(?:service|worker|queue|cache|database|schema|api|endpoints?|integration|auth|payment)\\b';
|
|
11
|
+
const TRIVIAL_THRESHOLD_WORDS = 15;
|
|
12
|
+
// Minute estimates per complexity
|
|
13
|
+
const MINUTES = {
|
|
14
|
+
trivial: 5,
|
|
15
|
+
simple: 30,
|
|
16
|
+
feature: 120,
|
|
17
|
+
architectural: 480,
|
|
18
|
+
};
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Classification helpers
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
function classifyType(request) {
|
|
23
|
+
if (BUGFIX_RE.test(request)) {
|
|
24
|
+
return 'bugfix';
|
|
25
|
+
}
|
|
26
|
+
// Exploration takes priority when explicit exploration keywords present
|
|
27
|
+
if (EXPLORATION_RE.test(request)) {
|
|
28
|
+
return 'exploration';
|
|
29
|
+
}
|
|
30
|
+
// Short question without exploration keywords → question
|
|
31
|
+
const wordCount = request.trim().split(/\s+/).length;
|
|
32
|
+
if (request.trim().endsWith('?') && wordCount <= 8) {
|
|
33
|
+
return 'question';
|
|
34
|
+
}
|
|
35
|
+
if (REFACTOR_RE.test(request)) {
|
|
36
|
+
return 'refactor';
|
|
37
|
+
}
|
|
38
|
+
return 'feature';
|
|
39
|
+
}
|
|
40
|
+
function countComplexTerms(request) {
|
|
41
|
+
return (request.match(new RegExp(COMPLEXITY_TERMS_PATTERN, 'gi')) ?? []).length;
|
|
42
|
+
}
|
|
43
|
+
function classifyComplexity(request, type) {
|
|
44
|
+
const words = request.trim().split(/\s+/);
|
|
45
|
+
if (ARCHITECTURAL_TERMS_RE.test(request)) {
|
|
46
|
+
return 'architectural';
|
|
47
|
+
}
|
|
48
|
+
if (type === 'exploration' || type === 'question') {
|
|
49
|
+
return 'trivial';
|
|
50
|
+
}
|
|
51
|
+
const complexCount = countComplexTerms(request);
|
|
52
|
+
if (words.length <= TRIVIAL_THRESHOLD_WORDS && complexCount === 0) {
|
|
53
|
+
return 'trivial';
|
|
54
|
+
}
|
|
55
|
+
if (complexCount >= 2) {
|
|
56
|
+
return 'feature';
|
|
57
|
+
}
|
|
58
|
+
if (complexCount >= 1) {
|
|
59
|
+
return 'simple';
|
|
60
|
+
}
|
|
61
|
+
return 'feature';
|
|
62
|
+
}
|
|
63
|
+
function extractKeywords(request) {
|
|
64
|
+
// Remove common stop words and keep meaningful terms
|
|
65
|
+
const stopWords = new Set([
|
|
66
|
+
'a',
|
|
67
|
+
'an',
|
|
68
|
+
'the',
|
|
69
|
+
'and',
|
|
70
|
+
'or',
|
|
71
|
+
'but',
|
|
72
|
+
'in',
|
|
73
|
+
'on',
|
|
74
|
+
'at',
|
|
75
|
+
'to',
|
|
76
|
+
'for',
|
|
77
|
+
'of',
|
|
78
|
+
'with',
|
|
79
|
+
'by',
|
|
80
|
+
'from',
|
|
81
|
+
'is',
|
|
82
|
+
'it',
|
|
83
|
+
'i',
|
|
84
|
+
'we',
|
|
85
|
+
'my',
|
|
86
|
+
'our',
|
|
87
|
+
'this',
|
|
88
|
+
'that',
|
|
89
|
+
'be',
|
|
90
|
+
'are',
|
|
91
|
+
'was',
|
|
92
|
+
'were',
|
|
93
|
+
'will',
|
|
94
|
+
'can',
|
|
95
|
+
'do',
|
|
96
|
+
'does',
|
|
97
|
+
'how',
|
|
98
|
+
'what',
|
|
99
|
+
'why',
|
|
100
|
+
'when',
|
|
101
|
+
'where',
|
|
102
|
+
'want',
|
|
103
|
+
'need',
|
|
104
|
+
'have',
|
|
105
|
+
'would',
|
|
106
|
+
'should',
|
|
107
|
+
'could',
|
|
108
|
+
]);
|
|
109
|
+
return request
|
|
110
|
+
.toLowerCase()
|
|
111
|
+
.replace(/[^\w\s]/g, ' ')
|
|
112
|
+
.split(/\s+/)
|
|
113
|
+
.filter((w) => w.length >= 3 && !stopWords.has(w))
|
|
114
|
+
.slice(0, 10);
|
|
115
|
+
}
|
|
116
|
+
function computeConfidence(request, type) {
|
|
117
|
+
// Higher confidence when multiple signals align
|
|
118
|
+
const signals = [
|
|
119
|
+
BUGFIX_RE.test(request) && type === 'bugfix',
|
|
120
|
+
EXPLORATION_RE.test(request) && type === 'exploration',
|
|
121
|
+
request.trim().endsWith('?') && type === 'question',
|
|
122
|
+
REFACTOR_RE.test(request) && type === 'refactor',
|
|
123
|
+
type === 'feature',
|
|
124
|
+
];
|
|
125
|
+
const matching = signals.filter(Boolean).length;
|
|
126
|
+
if (matching >= 2) {
|
|
127
|
+
return 0.95;
|
|
128
|
+
}
|
|
129
|
+
if (matching === 1) {
|
|
130
|
+
return 0.8;
|
|
131
|
+
}
|
|
132
|
+
return 0.6;
|
|
133
|
+
}
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Public API
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
/**
|
|
138
|
+
* Classify a natural-language request into type, complexity, and keywords.
|
|
139
|
+
*/
|
|
140
|
+
export function classifyIntent(request) {
|
|
141
|
+
const type = classifyType(request);
|
|
142
|
+
const complexity = classifyComplexity(request, type);
|
|
143
|
+
const keywords = extractKeywords(request);
|
|
144
|
+
const confidence = computeConfidence(request, type);
|
|
145
|
+
return {
|
|
146
|
+
type,
|
|
147
|
+
complexity,
|
|
148
|
+
estimatedMinutes: MINUTES[complexity],
|
|
149
|
+
keywords,
|
|
150
|
+
confidence,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=intent-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent-classifier.js","sourceRoot":"","sources":["../../../src/engine/facilitate/intent-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ParsedPlan } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extract structured spec data from Plan Mode markdown output.
|
|
4
|
+
* Returns null when the input is empty or not parseable as a plan.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parsePlanContent(planMarkdown: string): ParsedPlan | null;
|
|
7
|
+
//# sourceMappingURL=plan-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-parser.d.ts","sourceRoot":"","sources":["../../../src/engine/facilitate/plan-parser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,sBAAsB,CAAC;AAyGnE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAyBxE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// engine/facilitate/plan-parser.ts — SPEC-264 Plan Mode markdown parser
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Section extraction
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
const SECTION_HEADERS = /^#{1,3}\s+(.+)$/m;
|
|
6
|
+
const PLAN_SECTION_RE = /^#{1,3}\s+(?:plan|approach|steps|implementation|solution)\s*$/im;
|
|
7
|
+
const TITLE_RE = /^#\s+(.+)$/m;
|
|
8
|
+
const CHECKBOX_RE = /^[-*]\s+\[[ x]\]\s+(.+)$/gim;
|
|
9
|
+
const ARCHITECTURAL_TERMS = /\b(?:migrate|migration|replace|redesign|overhaul|rewrite|refactor architecture)\b/i;
|
|
10
|
+
const COMPLEXITY_TERMS = /\b(?:service|worker|queue|cache|database|api|integration)\b/gi;
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Helpers
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
function extractTitle(markdown) {
|
|
15
|
+
const match = TITLE_RE.exec(markdown);
|
|
16
|
+
if (match?.[1]) {
|
|
17
|
+
return match[1].trim();
|
|
18
|
+
}
|
|
19
|
+
// Fallback: use first non-empty line
|
|
20
|
+
const firstLine = markdown.split('\n').find((l) => l.trim().length > 0);
|
|
21
|
+
return firstLine?.replace(/^#+\s*/, '').trim() ?? 'Untitled Plan';
|
|
22
|
+
}
|
|
23
|
+
function extractCheckboxes(markdown) {
|
|
24
|
+
const results = [];
|
|
25
|
+
let m;
|
|
26
|
+
const re = new RegExp(CHECKBOX_RE.source, CHECKBOX_RE.flags);
|
|
27
|
+
while ((m = re.exec(markdown)) !== null) {
|
|
28
|
+
if (m[1]) {
|
|
29
|
+
results.push(m[1].trim());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return results;
|
|
33
|
+
}
|
|
34
|
+
function extractBullets(section) {
|
|
35
|
+
const lines = section.split('\n');
|
|
36
|
+
return lines
|
|
37
|
+
.filter((l) => /^[-*]\s+(?!\[)/.test(l.trim()))
|
|
38
|
+
.map((l) => l.replace(/^[-*]\s+/, '').trim())
|
|
39
|
+
.filter((l) => l.length > 0);
|
|
40
|
+
}
|
|
41
|
+
function extractTechnicalNotes(markdown) {
|
|
42
|
+
const notes = [];
|
|
43
|
+
// Extract content from code blocks (language tag as note)
|
|
44
|
+
const blockRe = /```(\w+)/g;
|
|
45
|
+
let m;
|
|
46
|
+
while ((m = blockRe.exec(markdown)) !== null) {
|
|
47
|
+
if (m[1]) {
|
|
48
|
+
notes.push(`Code block: ${m[1]}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Extract lines with technical hints (file paths, imports, type refs)
|
|
52
|
+
const techLineRe = /^[-*]\s+.{10,}(?:\.ts|\.js|import|export|interface|type |class )/gim;
|
|
53
|
+
let tm;
|
|
54
|
+
while ((tm = techLineRe.exec(markdown)) !== null) {
|
|
55
|
+
const note = tm[0].replace(/^[-*]\s+/, '').trim();
|
|
56
|
+
if (!notes.includes(note)) {
|
|
57
|
+
notes.push(note);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return notes.slice(0, 10);
|
|
61
|
+
}
|
|
62
|
+
function estimateComplexity(markdown, acCount) {
|
|
63
|
+
if (ARCHITECTURAL_TERMS.test(markdown)) {
|
|
64
|
+
return 'architectural';
|
|
65
|
+
}
|
|
66
|
+
// Create a fresh regex each call to avoid stateful `g` flag issues
|
|
67
|
+
const complexTerms = (markdown.match(new RegExp(COMPLEXITY_TERMS.source, 'gi')) ?? []).length;
|
|
68
|
+
if (acCount >= 5 || complexTerms >= 3) {
|
|
69
|
+
return 'feature';
|
|
70
|
+
}
|
|
71
|
+
if (acCount >= 2 || complexTerms >= 1) {
|
|
72
|
+
return 'simple';
|
|
73
|
+
}
|
|
74
|
+
return 'trivial';
|
|
75
|
+
}
|
|
76
|
+
function extractPlanSection(markdown) {
|
|
77
|
+
const match = PLAN_SECTION_RE.exec(markdown);
|
|
78
|
+
if (!match) {
|
|
79
|
+
return markdown;
|
|
80
|
+
}
|
|
81
|
+
const start = match.index + match[0].length;
|
|
82
|
+
// Find next section header at same or higher level
|
|
83
|
+
const remaining = markdown.slice(start);
|
|
84
|
+
const nextHeader = SECTION_HEADERS.exec(remaining);
|
|
85
|
+
return nextHeader ? remaining.slice(0, nextHeader.index) : remaining;
|
|
86
|
+
}
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Public API
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
/**
|
|
91
|
+
* Extract structured spec data from Plan Mode markdown output.
|
|
92
|
+
* Returns null when the input is empty or not parseable as a plan.
|
|
93
|
+
*/
|
|
94
|
+
export function parsePlanContent(planMarkdown) {
|
|
95
|
+
if (!planMarkdown || planMarkdown.trim().length < 10) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const title = extractTitle(planMarkdown);
|
|
99
|
+
// First try checkbox-style ACs
|
|
100
|
+
let acceptanceCriteria = extractCheckboxes(planMarkdown);
|
|
101
|
+
// Fallback: look for bullet lists inside plan/approach sections
|
|
102
|
+
if (acceptanceCriteria.length === 0) {
|
|
103
|
+
const section = extractPlanSection(planMarkdown);
|
|
104
|
+
acceptanceCriteria = extractBullets(section);
|
|
105
|
+
}
|
|
106
|
+
const technicalNotes = extractTechnicalNotes(planMarkdown);
|
|
107
|
+
const estimatedComplexity = estimateComplexity(planMarkdown, acceptanceCriteria.length);
|
|
108
|
+
return {
|
|
109
|
+
title,
|
|
110
|
+
acceptanceCriteria,
|
|
111
|
+
technicalNotes,
|
|
112
|
+
estimatedComplexity,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=plan-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-parser.js","sourceRoot":"","sources":["../../../src/engine/facilitate/plan-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ClassifiedIntent, LoadedFacilitateContext, RouteDecision } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Decide the best next action given classified intent and loaded context.
|
|
4
|
+
*/
|
|
5
|
+
export declare function route(intent: ClassifiedIntent, context: LoadedFacilitateContext, request: string): RouteDecision;
|
|
6
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/engine/facilitate/router.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,aAAa,EACd,MAAM,sBAAsB,CAAC;AAiC9B;;GAEG;AACH,wBAAgB,KAAK,CACnB,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,uBAAuB,EAChC,OAAO,EAAE,MAAM,GACd,aAAa,CA8Cf"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// engine/facilitate/router.ts — SPEC-264 Routing logic for facilitate orchestrator
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Helpers
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
function findRelatedActiveSpec(context, keywords) {
|
|
6
|
+
const lowerKeywords = keywords.map((k) => k.toLowerCase());
|
|
7
|
+
for (const spec of context.activeSpecs) {
|
|
8
|
+
const titleLower = spec.title.toLowerCase();
|
|
9
|
+
if (lowerKeywords.some((kw) => titleLower.includes(kw))) {
|
|
10
|
+
return spec.id;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
// No keyword match — return first active spec if only one
|
|
14
|
+
if (context.activeSpecs.length === 1 && context.activeSpecs[0]) {
|
|
15
|
+
return context.activeSpecs[0].id;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
function buildSpecDescription(request, intent) {
|
|
20
|
+
const typePrefix = intent.type === 'bugfix' ? 'Fix: ' : '';
|
|
21
|
+
return `${typePrefix}${request}`;
|
|
22
|
+
}
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Public API
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Decide the best next action given classified intent and loaded context.
|
|
28
|
+
*/
|
|
29
|
+
export function route(intent, context, request) {
|
|
30
|
+
// 1. Resume active work when there's a related spec in-progress
|
|
31
|
+
if (context.hasActiveWork) {
|
|
32
|
+
const relatedId = findRelatedActiveSpec(context, intent.keywords);
|
|
33
|
+
if (relatedId) {
|
|
34
|
+
const spec = context.activeSpecs.find((s) => s.id === relatedId);
|
|
35
|
+
return {
|
|
36
|
+
action: 'resume',
|
|
37
|
+
specId: relatedId,
|
|
38
|
+
reason: `Spec ${relatedId} "${spec?.title ?? ''}" is in progress and matches your request`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// 2. Trivial requests → answer directly without creating a spec
|
|
43
|
+
if (intent.complexity === 'trivial') {
|
|
44
|
+
return {
|
|
45
|
+
action: 'direct',
|
|
46
|
+
reason: 'Request is trivial — no spec needed, handle inline',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// 3. Exploration and questions → direct answer
|
|
50
|
+
if (intent.type === 'exploration' || intent.type === 'question') {
|
|
51
|
+
return {
|
|
52
|
+
action: 'direct',
|
|
53
|
+
reason: 'Informational request — answer directly',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// 4. Ambiguous architectural requests → ask for clarification
|
|
57
|
+
if (intent.complexity === 'architectural' && intent.confidence < 0.7) {
|
|
58
|
+
return {
|
|
59
|
+
action: 'clarify',
|
|
60
|
+
question: 'This looks like a significant architectural change. ' +
|
|
61
|
+
'Could you describe the current pain point and the desired end state?',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// 5. Default → create a spec
|
|
65
|
+
return {
|
|
66
|
+
action: 'create-spec',
|
|
67
|
+
description: buildSpecDescription(request, intent),
|
|
68
|
+
type: intent.type,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/engine/facilitate/router.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAQnF,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,qBAAqB,CAC5B,OAAgC,EAChC,QAAkB;IAElB,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC3D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IACD,0DAA0D;IAC1D,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAe,EAAE,MAAwB;IACrE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,OAAO,GAAG,UAAU,GAAG,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;GAEG;AACH,MAAM,UAAU,KAAK,CACnB,MAAwB,EACxB,OAAgC,EAChC,OAAe;IAEf,gEAAgE;IAChE,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClE,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;YACjE,OAAO;gBACL,MAAM,EAAE,QAAQ;gBAChB,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,QAAQ,SAAS,KAAK,IAAI,EAAE,KAAK,IAAI,EAAE,2CAA2C;aAC3F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,oDAAoD;SAC7D,CAAC;IACJ,CAAC;IAED,+CAA+C;IAC/C,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAChE,OAAO;YACL,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,yCAAyC;SAClD,CAAC;IACJ,CAAC;IAED,8DAA8D;IAC9D,IAAI,MAAM,CAAC,UAAU,KAAK,eAAe,IAAI,MAAM,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;QACrE,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,QAAQ,EACN,sDAAsD;gBACtD,sEAAsE;SACzE,CAAC;IACJ,CAAC;IAED,6BAA6B;IAC7B,OAAO;QACL,MAAM,EAAE,aAAa;QACrB,WAAW,EAAE,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC;QAClD,IAAI,EAAE,MAAM,CAAC,IAAI;KAClB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads project specs and decisions from data/ and writes
|
|
3
|
+
* .planu/plan-context.md in the project root.
|
|
4
|
+
*/
|
|
5
|
+
export declare function injectPlanContext(projectPath: string, taskDescription: string | null): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Builds the markdown content for .planu/plan-context.md.
|
|
8
|
+
* Pure function for testability — does not write to disk.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildContextMarkdown(projectPath: string, taskDescription: string | null): Promise<string>;
|
|
11
|
+
//# sourceMappingURL=context-injector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-injector.d.ts","sourceRoot":"","sources":["../../../src/engine/hooks/context-injector.ts"],"names":[],"mappings":"AAuFA;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GAAG,IAAI,GAC7B,OAAO,CAAC,IAAI,CAAC,CAKf;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GAAG,IAAI,GAC7B,OAAO,CAAC,MAAM,CAAC,CAyCjB"}
|