maestro-flow 0.3.10 → 0.3.11
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/.claude/agents/workflow-collab-planner.md +1 -1
- package/.claude/agents/workflow-executor.md +1 -1
- package/.claude/agents/workflow-plan-checker.md +1 -1
- package/.claude/agents/workflow-planner.md +1 -1
- package/.claude/commands/learn-decompose.md +176 -176
- package/.claude/commands/learn-follow.md +167 -167
- package/.claude/commands/learn-retro.md +1 -1
- package/.claude/commands/maestro-coordinate.md +1 -3
- package/.claude/commands/manage-harvest.md +131 -131
- package/.claude/commands/manage-issue.md +2 -2
- package/.claude/commands/spec-add.md +67 -56
- package/.claude/commands/spec-load.md +66 -64
- package/.claude/commands/spec-setup.md +5 -9
- package/.codex/skills/learn-decompose/SKILL.md +119 -0
- package/.codex/skills/learn-follow/SKILL.md +83 -0
- package/.codex/skills/learn-investigate/SKILL.md +83 -0
- package/.codex/skills/learn-retro/SKILL.md +83 -0
- package/.codex/skills/learn-second-opinion/SKILL.md +86 -0
- package/.codex/skills/maestro/SKILL.md +151 -279
- package/.codex/skills/maestro-analyze/SKILL.md +59 -71
- package/.codex/skills/maestro-brainstorm/SKILL.md +452 -463
- package/.codex/skills/maestro-chain/SKILL.md +95 -110
- package/.codex/skills/maestro-coordinate/SKILL.md +68 -234
- package/.codex/skills/maestro-execute/SKILL.md +435 -446
- package/.codex/skills/maestro-fork/SKILL.md +68 -0
- package/.codex/skills/maestro-init/SKILL.md +171 -167
- package/.codex/skills/maestro-learn/SKILL.md +80 -0
- package/.codex/skills/maestro-link-coordinate/SKILL.md +224 -220
- package/.codex/skills/maestro-merge/SKILL.md +62 -0
- package/.codex/skills/maestro-milestone-audit/SKILL.md +108 -103
- package/.codex/skills/maestro-milestone-complete/SKILL.md +155 -149
- package/.codex/skills/maestro-milestone-release/SKILL.md +70 -0
- package/.codex/skills/maestro-overlay/SKILL.md +188 -185
- package/.codex/skills/maestro-plan/SKILL.md +58 -69
- package/.codex/skills/maestro-quick/SKILL.md +26 -23
- package/.codex/skills/maestro-roadmap/SKILL.md +65 -73
- package/.codex/skills/maestro-spec-generate/SKILL.md +66 -74
- package/.codex/skills/maestro-ui-design/SKILL.md +34 -31
- package/.codex/skills/maestro-verify/SKILL.md +556 -566
- package/.codex/skills/manage-codebase-rebuild/SKILL.md +397 -405
- package/.codex/skills/manage-codebase-refresh/SKILL.md +93 -82
- package/.codex/skills/manage-harvest/SKILL.md +82 -0
- package/.codex/skills/manage-issue/SKILL.md +80 -65
- package/.codex/skills/manage-issue-discover/SKILL.md +491 -503
- package/.codex/skills/manage-learn/SKILL.md +190 -186
- package/.codex/skills/manage-memory/SKILL.md +95 -72
- package/.codex/skills/manage-memory-capture/SKILL.md +99 -86
- package/.codex/skills/manage-status/SKILL.md +102 -89
- package/.codex/skills/quality-business-test/SKILL.md +228 -223
- package/.codex/skills/quality-debug/SKILL.md +54 -66
- package/.codex/skills/quality-integration-test/SKILL.md +532 -544
- package/.codex/skills/quality-refactor/SKILL.md +197 -191
- package/.codex/skills/quality-retrospective/SKILL.md +512 -505
- package/.codex/skills/quality-review/SKILL.md +93 -105
- package/.codex/skills/quality-sync/SKILL.md +101 -89
- package/.codex/skills/quality-test/SKILL.md +202 -198
- package/.codex/skills/quality-test-gen/SKILL.md +93 -104
- package/.codex/skills/spec-add/SKILL.md +58 -39
- package/.codex/skills/spec-load/SKILL.md +45 -40
- package/.codex/skills/spec-map/SKILL.md +180 -182
- package/.codex/skills/spec-setup/SKILL.md +94 -76
- package/.codex/skills/team-coordinate/SKILL.md +346 -357
- package/.codex/skills/team-executor/SKILL.md +70 -112
- package/.codex/skills/team-lifecycle-v4/SKILL.md +311 -299
- package/.codex/skills/team-quality-assurance/SKILL.md +234 -227
- package/.codex/skills/team-review/SKILL.md +232 -225
- package/.codex/skills/team-tech-debt/SKILL.md +78 -100
- package/.codex/skills/team-testing/SKILL.md +242 -235
- package/.codex/skills/wiki-connect/SKILL.md +75 -0
- package/.codex/skills/wiki-digest/SKILL.md +87 -0
- package/README.md +7 -4
- package/README.zh-CN.md +7 -4
- package/dashboard/dist-server/dashboard/src/server/routes/specs.d.ts +1 -1
- package/dashboard/dist-server/dashboard/src/server/routes/specs.js +75 -30
- package/dashboard/dist-server/dashboard/src/server/routes/specs.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/state/event-bus.d.ts +5 -0
- package/dashboard/dist-server/dashboard/src/server/state/event-bus.js +5 -0
- package/dashboard/dist-server/dashboard/src/server/state/event-bus.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/shared/constants.js +5 -0
- package/dashboard/dist-server/dashboard/src/shared/constants.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/shared/team-types.d.ts +21 -0
- package/dashboard/dist-server/dashboard/src/shared/team-types.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/shared/types.d.ts +3 -2
- package/dashboard/dist-server/dashboard/src/shared/ws-protocol.d.ts +1 -1
- package/dashboard/dist-server/dashboard/src/shared/ws-protocol.js.map +1 -1
- package/dashboard/dist-server/src/hooks/constants.d.ts +2 -0
- package/dashboard/dist-server/src/hooks/constants.js +2 -0
- package/dashboard/dist-server/src/hooks/constants.js.map +1 -1
- package/dist/src/commands/collab.js +4 -4
- package/dist/src/commands/collab.js.map +1 -1
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +66 -1
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/spec.d.ts.map +1 -1
- package/dist/src/commands/spec.js +7 -2
- package/dist/src/commands/spec.js.map +1 -1
- package/dist/src/hooks/constants.d.ts +2 -0
- package/dist/src/hooks/constants.d.ts.map +1 -1
- package/dist/src/hooks/constants.js +2 -0
- package/dist/src/hooks/constants.js.map +1 -1
- package/dist/src/hooks/guards/index.d.ts +1 -0
- package/dist/src/hooks/guards/index.d.ts.map +1 -1
- package/dist/src/hooks/guards/index.js +1 -0
- package/dist/src/hooks/guards/index.js.map +1 -1
- package/dist/src/hooks/guards/spec-validator.d.ts +25 -0
- package/dist/src/hooks/guards/spec-validator.d.ts.map +1 -0
- package/dist/src/hooks/guards/spec-validator.js +66 -0
- package/dist/src/hooks/guards/spec-validator.js.map +1 -0
- package/dist/src/hooks/keyword-spec-injector.d.ts +21 -0
- package/dist/src/hooks/keyword-spec-injector.d.ts.map +1 -0
- package/dist/src/hooks/keyword-spec-injector.js +96 -0
- package/dist/src/hooks/keyword-spec-injector.js.map +1 -0
- package/dist/src/hooks/plugins/spec-injection-plugin.d.ts +2 -1
- package/dist/src/hooks/plugins/spec-injection-plugin.d.ts.map +1 -1
- package/dist/src/hooks/plugins/spec-injection-plugin.js +21 -12
- package/dist/src/hooks/plugins/spec-injection-plugin.js.map +1 -1
- package/dist/src/hooks/spec-bridge.d.ts +40 -0
- package/dist/src/hooks/spec-bridge.d.ts.map +1 -0
- package/dist/src/hooks/spec-bridge.js +97 -0
- package/dist/src/hooks/spec-bridge.js.map +1 -0
- package/dist/src/hooks/spec-injector.d.ts.map +1 -1
- package/dist/src/hooks/spec-injector.js +18 -12
- package/dist/src/hooks/spec-injector.js.map +1 -1
- package/dist/src/team/phase-orchestrator.d.ts +52 -0
- package/dist/src/team/phase-orchestrator.d.ts.map +1 -0
- package/dist/src/team/phase-orchestrator.js +165 -0
- package/dist/src/team/phase-orchestrator.js.map +1 -0
- package/dist/src/team/phase-types.d.ts +51 -0
- package/dist/src/team/phase-types.d.ts.map +1 -0
- package/dist/src/team/phase-types.js +41 -0
- package/dist/src/team/phase-types.js.map +1 -0
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +6 -0
- package/dist/src/tools/index.js.map +1 -1
- package/dist/src/tools/spec-entry-parser.d.ts +56 -0
- package/dist/src/tools/spec-entry-parser.d.ts.map +1 -0
- package/dist/src/tools/spec-entry-parser.js +196 -0
- package/dist/src/tools/spec-entry-parser.js.map +1 -0
- package/dist/src/tools/spec-init.d.ts.map +1 -1
- package/dist/src/tools/spec-init.js +66 -92
- package/dist/src/tools/spec-init.js.map +1 -1
- package/dist/src/tools/spec-keyword-index.d.ts +30 -0
- package/dist/src/tools/spec-keyword-index.d.ts.map +1 -0
- package/dist/src/tools/spec-keyword-index.js +101 -0
- package/dist/src/tools/spec-keyword-index.js.map +1 -0
- package/dist/src/tools/spec-loader.d.ts +3 -3
- package/dist/src/tools/spec-loader.d.ts.map +1 -1
- package/dist/src/tools/spec-loader.js +49 -23
- package/dist/src/tools/spec-loader.js.map +1 -1
- package/dist/src/tools/team-agents.d.ts +27 -0
- package/dist/src/tools/team-agents.d.ts.map +1 -0
- package/dist/src/tools/team-agents.js +362 -0
- package/dist/src/tools/team-agents.js.map +1 -0
- package/dist/src/tools/team-mailbox.d.ts +40 -0
- package/dist/src/tools/team-mailbox.d.ts.map +1 -0
- package/dist/src/tools/team-mailbox.js +384 -0
- package/dist/src/tools/team-mailbox.js.map +1 -0
- package/dist/src/tools/team-msg.d.ts +17 -8
- package/dist/src/tools/team-msg.d.ts.map +1 -1
- package/dist/src/tools/team-msg.js +110 -13
- package/dist/src/tools/team-msg.js.map +1 -1
- package/dist/src/tools/team-tasks-mcp.d.ts +27 -0
- package/dist/src/tools/team-tasks-mcp.d.ts.map +1 -0
- package/dist/src/tools/team-tasks-mcp.js +408 -0
- package/dist/src/tools/team-tasks-mcp.js.map +1 -0
- package/package.json +2 -1
- package/workflows/analyze.md +816 -816
- package/workflows/brainstorm.md +471 -471
- package/workflows/codebase-rebuild.md +332 -332
- package/workflows/codebase-refresh.md +240 -240
- package/workflows/execute.md +1 -1
- package/workflows/harvest.md +420 -420
- package/workflows/integration-test.md +343 -343
- package/workflows/issue-discover.md +414 -414
- package/workflows/map.md +111 -111
- package/workflows/milestone-complete.md +176 -176
- package/workflows/plan.md +1 -1
- package/workflows/quick.md +497 -497
- package/workflows/refactor.md +300 -300
- package/workflows/roadmap.md +335 -335
- package/workflows/spec-generate.md +640 -640
- package/workflows/specs-add.md +46 -81
- package/workflows/specs-load.md +15 -17
- package/workflows/specs-setup.md +40 -161
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Validator Guard — PreToolUse: Write|Edit
|
|
3
|
+
*
|
|
4
|
+
* Validates that spec file entries use the <spec-entry> closed-tag format.
|
|
5
|
+
* Pure evaluation function — no I/O, follows workflow-guard.ts pattern.
|
|
6
|
+
*
|
|
7
|
+
* Only activates when the file path targets .workflow/specs/.
|
|
8
|
+
*/
|
|
9
|
+
import { parseSpecEntries, validateCategoryMatch } from '../../tools/spec-entry-parser.js';
|
|
10
|
+
import { CATEGORY_MAP } from '../../tools/spec-loader.js';
|
|
11
|
+
import { basename } from 'node:path';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Public API
|
|
14
|
+
// ============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Evaluate spec file content for format compliance.
|
|
17
|
+
*
|
|
18
|
+
* @param filePath Absolute or relative file path being written
|
|
19
|
+
* @param content The full file content after the write/edit
|
|
20
|
+
* @param mode 'warn' (advisory) or 'block' (reject write)
|
|
21
|
+
*/
|
|
22
|
+
export function evaluateSpecValidator(filePath, content, mode = 'warn') {
|
|
23
|
+
// Only validate files in .workflow/specs/
|
|
24
|
+
if (!isSpecFile(filePath)) {
|
|
25
|
+
return { valid: true, mode, errors: [] };
|
|
26
|
+
}
|
|
27
|
+
const errors = [];
|
|
28
|
+
// Determine expected category from filename
|
|
29
|
+
const fileName = basename(filePath);
|
|
30
|
+
const expectedCategory = CATEGORY_MAP[fileName];
|
|
31
|
+
// Parse entries
|
|
32
|
+
const result = parseSpecEntries(content);
|
|
33
|
+
// Collect parser-level errors
|
|
34
|
+
errors.push(...result.errors);
|
|
35
|
+
// Validate category match per entry
|
|
36
|
+
if (expectedCategory) {
|
|
37
|
+
for (const entry of result.entries) {
|
|
38
|
+
const mismatch = validateCategoryMatch(entry, expectedCategory);
|
|
39
|
+
if (mismatch) {
|
|
40
|
+
errors.push({ line: entry.lineStart, message: mismatch });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Check for unclosed tags
|
|
45
|
+
const openCount = (content.match(/<spec-entry\b/g) || []).length;
|
|
46
|
+
const closeCount = (content.match(/<\/spec-entry>/g) || []).length;
|
|
47
|
+
if (openCount !== closeCount) {
|
|
48
|
+
errors.push({
|
|
49
|
+
line: 1,
|
|
50
|
+
message: `Unbalanced tags: ${openCount} opening <spec-entry> vs ${closeCount} closing </spec-entry>`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
valid: errors.length === 0,
|
|
55
|
+
mode,
|
|
56
|
+
errors,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Internal
|
|
61
|
+
// ============================================================================
|
|
62
|
+
function isSpecFile(filePath) {
|
|
63
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
64
|
+
return normalized.includes('.workflow/specs/') && normalized.endsWith('.md');
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=spec-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-validator.js","sourceRoot":"","sources":["../../../../src/hooks/guards/spec-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAqB,qBAAqB,EAAoB,MAAM,kCAAkC,CAAC;AAChI,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAYrC,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAgB,EAChB,OAAe,EACf,OAAyB,MAAM;IAE/B,0CAA0C;IAC1C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAA6C,EAAE,CAAC;IAE5D,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,gBAAgB,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEhD,gBAAgB;IAChB,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAEzC,8BAA8B;IAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAE9B,oCAAoC;IACpC,IAAI,gBAAgB,EAAE,CAAC;QACrB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;YAChE,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IACjE,MAAM,UAAU,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IACnE,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,oBAAoB,SAAS,4BAA4B,UAAU,wBAAwB;SACrG,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,IAAI;QACJ,MAAM;KACP,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,WAAW;AACX,+EAA+E;AAE/E,SAAS,UAAU,CAAC,QAAgB;IAClC,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyword Spec Injector — UserPromptSubmit hook
|
|
3
|
+
*
|
|
4
|
+
* Scans user prompt for keywords, matches against <spec-entry> keyword attributes,
|
|
5
|
+
* injects matching entries as additionalContext. Session dedup prevents re-injection.
|
|
6
|
+
*/
|
|
7
|
+
export interface KeywordInjectionResult {
|
|
8
|
+
inject: boolean;
|
|
9
|
+
content?: string;
|
|
10
|
+
matchedKeywords?: string[];
|
|
11
|
+
matchedEntries?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Evaluate whether to inject keyword-matched spec entries for a user prompt.
|
|
15
|
+
*
|
|
16
|
+
* @param prompt The user's prompt text
|
|
17
|
+
* @param projectPath Working directory for spec file resolution
|
|
18
|
+
* @param sessionId Session ID for dedup bridge
|
|
19
|
+
*/
|
|
20
|
+
export declare function evaluateKeywordInjection(prompt: string, projectPath: string, sessionId: string): KeywordInjectionResult;
|
|
21
|
+
//# sourceMappingURL=keyword-spec-injector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyword-spec-injector.d.ts","sourceRoot":"","sources":["../../../src/hooks/keyword-spec-injector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA+BD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,sBAAsB,CAqCxB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyword Spec Injector — UserPromptSubmit hook
|
|
3
|
+
*
|
|
4
|
+
* Scans user prompt for keywords, matches against <spec-entry> keyword attributes,
|
|
5
|
+
* injects matching entries as additionalContext. Session dedup prevents re-injection.
|
|
6
|
+
*/
|
|
7
|
+
import { buildKeywordIndex, lookupKeywords } from '../tools/spec-keyword-index.js';
|
|
8
|
+
import { markInjected, filterUnjected } from './spec-bridge.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Config
|
|
11
|
+
// ============================================================================
|
|
12
|
+
const MIN_KEYWORD_LENGTH = 3;
|
|
13
|
+
/** Common words to skip when tokenizing prompt */
|
|
14
|
+
const STOP_WORDS = new Set([
|
|
15
|
+
'the', 'and', 'for', 'are', 'but', 'not', 'you', 'all', 'can', 'had',
|
|
16
|
+
'her', 'was', 'one', 'our', 'out', 'has', 'his', 'how', 'its', 'may',
|
|
17
|
+
'new', 'now', 'old', 'see', 'way', 'who', 'did', 'get', 'let', 'say',
|
|
18
|
+
'she', 'too', 'use', 'this', 'that', 'with', 'have', 'from', 'they',
|
|
19
|
+
'been', 'said', 'each', 'make', 'like', 'just', 'over', 'such', 'take',
|
|
20
|
+
'than', 'them', 'very', 'when', 'what', 'some', 'time', 'will', 'into',
|
|
21
|
+
'look', 'only', 'come', 'also', 'back', 'after', 'work', 'first', 'well',
|
|
22
|
+
'then', 'year', 'your', 'them', 'would', 'there', 'their', 'which',
|
|
23
|
+
'about', 'could', 'other', 'these', 'think', 'should', 'please',
|
|
24
|
+
// code-related common words to skip
|
|
25
|
+
'file', 'code', 'function', 'class', 'import', 'export', 'const', 'return',
|
|
26
|
+
'true', 'false', 'null', 'undefined', 'string', 'number', 'type', 'interface',
|
|
27
|
+
]);
|
|
28
|
+
/** Max entries to inject per prompt to avoid context bloat */
|
|
29
|
+
const MAX_ENTRIES_PER_INJECTION = 5;
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Public API
|
|
32
|
+
// ============================================================================
|
|
33
|
+
/**
|
|
34
|
+
* Evaluate whether to inject keyword-matched spec entries for a user prompt.
|
|
35
|
+
*
|
|
36
|
+
* @param prompt The user's prompt text
|
|
37
|
+
* @param projectPath Working directory for spec file resolution
|
|
38
|
+
* @param sessionId Session ID for dedup bridge
|
|
39
|
+
*/
|
|
40
|
+
export function evaluateKeywordInjection(prompt, projectPath, sessionId) {
|
|
41
|
+
// 1. Tokenize prompt into candidate keywords
|
|
42
|
+
const promptKeywords = tokenizePrompt(prompt);
|
|
43
|
+
if (promptKeywords.length === 0)
|
|
44
|
+
return { inject: false };
|
|
45
|
+
// 2. Build keyword index from spec files
|
|
46
|
+
const index = buildKeywordIndex(projectPath);
|
|
47
|
+
if (index.size === 0)
|
|
48
|
+
return { inject: false };
|
|
49
|
+
// 3. Look up matching entries
|
|
50
|
+
const matchedAll = lookupKeywords(index, promptKeywords);
|
|
51
|
+
if (matchedAll.length === 0)
|
|
52
|
+
return { inject: false };
|
|
53
|
+
// 4. Filter out already-injected entries (session dedup)
|
|
54
|
+
const unjected = filterUnjected(sessionId, matchedAll);
|
|
55
|
+
if (unjected.length === 0)
|
|
56
|
+
return { inject: false };
|
|
57
|
+
// 5. Limit to avoid context bloat
|
|
58
|
+
const toInject = unjected.slice(0, MAX_ENTRIES_PER_INJECTION);
|
|
59
|
+
// 6. Build injection content
|
|
60
|
+
const content = formatInjectionContent(toInject);
|
|
61
|
+
// 7. Mark as injected
|
|
62
|
+
const injectedKeywords = [...new Set(toInject.flatMap(e => e.keywords))];
|
|
63
|
+
const injectedIds = toInject.map(e => e.id);
|
|
64
|
+
markInjected(sessionId, injectedKeywords, injectedIds);
|
|
65
|
+
// 8. Determine which prompt keywords actually matched
|
|
66
|
+
const matchedKws = promptKeywords.filter(kw => index.has(kw));
|
|
67
|
+
return {
|
|
68
|
+
inject: true,
|
|
69
|
+
content,
|
|
70
|
+
matchedKeywords: matchedKws,
|
|
71
|
+
matchedEntries: toInject.length,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Internal
|
|
76
|
+
// ============================================================================
|
|
77
|
+
/**
|
|
78
|
+
* Tokenize prompt into candidate keywords for index lookup.
|
|
79
|
+
* Lowercase, deduplicate, filter by length and stop words.
|
|
80
|
+
*/
|
|
81
|
+
function tokenizePrompt(prompt) {
|
|
82
|
+
const words = prompt
|
|
83
|
+
.toLowerCase()
|
|
84
|
+
.replace(/[^a-z0-9\u4e00-\u9fff_-]/g, ' ')
|
|
85
|
+
.split(/\s+/)
|
|
86
|
+
.filter(w => w.length >= MIN_KEYWORD_LENGTH && !STOP_WORDS.has(w));
|
|
87
|
+
return [...new Set(words)];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Format matched entries for injection as context.
|
|
91
|
+
*/
|
|
92
|
+
function formatInjectionContent(entries) {
|
|
93
|
+
const sections = entries.map(e => `--- ${e.file} (${e.category}) [${e.keywords.join(', ')}] ---\n\n${e.content}`);
|
|
94
|
+
return `<spec-keyword-match count="${entries.length}">\n\n${sections.join('\n\n---\n\n')}\n\n</spec-keyword-match>`;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=keyword-spec-injector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyword-spec-injector.js","sourceRoot":"","sources":["../../../src/hooks/keyword-spec-injector.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,8 +9,9 @@ import type { WorkflowHookRegistry } from '../workflow-hooks.js';
|
|
|
9
9
|
*/
|
|
10
10
|
export declare class SpecInjectionPlugin implements MaestroPlugin {
|
|
11
11
|
private readonly projectPath;
|
|
12
|
+
private readonly sessionId;
|
|
12
13
|
readonly name = "specInjection";
|
|
13
|
-
constructor(projectPath?: string);
|
|
14
|
+
constructor(projectPath?: string, sessionId?: string);
|
|
14
15
|
apply(registry: WorkflowHookRegistry): void;
|
|
15
16
|
}
|
|
16
17
|
//# sourceMappingURL=spec-injection-plugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-injection-plugin.d.ts","sourceRoot":"","sources":["../../../../src/hooks/plugins/spec-injection-plugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"spec-injection-plugin.d.ts","sourceRoot":"","sources":["../../../../src/hooks/plugins/spec-injection-plugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAKjE;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IAIrD,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAJ5B,QAAQ,CAAC,IAAI,mBAAmB;gBAGb,WAAW,GAAE,MAAsB,EACnC,SAAS,GAAE,MAAW;IAGzC,KAAK,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI;CAuB5C"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
import { loadSpecs } from '../../tools/spec-loader.js';
|
|
5
5
|
import { resolveSelf } from '../../tools/team-members.js';
|
|
6
|
+
import { evaluateKeywordInjection } from '../keyword-spec-injector.js';
|
|
6
7
|
/**
|
|
7
8
|
* In-process plugin for `maestro coordinate` — injects relevant specs
|
|
8
9
|
* into the prompt via the `transformPrompt` waterfall hook.
|
|
@@ -12,20 +13,30 @@ import { resolveSelf } from '../../tools/team-members.js';
|
|
|
12
13
|
*/
|
|
13
14
|
export class SpecInjectionPlugin {
|
|
14
15
|
projectPath;
|
|
16
|
+
sessionId;
|
|
15
17
|
name = 'specInjection';
|
|
16
|
-
constructor(projectPath = process.cwd()) {
|
|
18
|
+
constructor(projectPath = process.cwd(), sessionId = '') {
|
|
17
19
|
this.projectPath = projectPath;
|
|
20
|
+
this.sessionId = sessionId;
|
|
18
21
|
}
|
|
19
22
|
apply(registry) {
|
|
20
23
|
registry.transformPrompt.tap(this.name, (prompt) => {
|
|
21
|
-
|
|
24
|
+
const parts = [prompt];
|
|
25
|
+
// Category-based injection
|
|
22
26
|
const category = inferCategory(prompt);
|
|
23
|
-
// Best-effort uid resolution for personal spec layer
|
|
24
27
|
const uid = resolveUidSafe();
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const catResult = loadSpecs(this.projectPath, category, uid);
|
|
29
|
+
if (catResult.content) {
|
|
30
|
+
parts.push(catResult.content);
|
|
31
|
+
}
|
|
32
|
+
// Keyword-based injection (with session dedup)
|
|
33
|
+
if (this.sessionId) {
|
|
34
|
+
const kwResult = evaluateKeywordInjection(prompt, this.projectPath, this.sessionId);
|
|
35
|
+
if (kwResult.inject && kwResult.content) {
|
|
36
|
+
parts.push(kwResult.content);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return parts.length > 1 ? parts.join('\n\n---\n\n') : prompt;
|
|
29
40
|
});
|
|
30
41
|
}
|
|
31
42
|
}
|
|
@@ -55,10 +66,8 @@ function inferCategory(prompt) {
|
|
|
55
66
|
return 'test';
|
|
56
67
|
if (/\b(debug|diagnose|fix|error|bug)\b/.test(lower))
|
|
57
68
|
return 'debug';
|
|
58
|
-
if (/\b(plan|design|architect|decompose)\b/.test(lower))
|
|
59
|
-
return '
|
|
60
|
-
|
|
61
|
-
return 'exploration';
|
|
62
|
-
return 'execution'; // Default for implementation work
|
|
69
|
+
if (/\b(plan|design|architect|decompose|explore|discover|search|analyze)\b/.test(lower))
|
|
70
|
+
return 'arch';
|
|
71
|
+
return 'coding'; // Default for implementation work
|
|
63
72
|
}
|
|
64
73
|
//# sourceMappingURL=spec-injection-plugin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-injection-plugin.js","sourceRoot":"","sources":["../../../../src/hooks/plugins/spec-injection-plugin.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,uEAAuE;AACvE,8EAA8E;AAI9E,OAAO,EAAE,SAAS,EAAqB,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"spec-injection-plugin.js","sourceRoot":"","sources":["../../../../src/hooks/plugins/spec-injection-plugin.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,uEAAuE;AACvE,8EAA8E;AAI9E,OAAO,EAAE,SAAS,EAAqB,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,OAAO,mBAAmB;IAIX;IACA;IAJV,IAAI,GAAG,eAAe,CAAC;IAEhC,YACmB,cAAsB,OAAO,CAAC,GAAG,EAAE,EACnC,YAAoB,EAAE;QADtB,gBAAW,GAAX,WAAW,CAAwB;QACnC,cAAS,GAAT,SAAS,CAAa;IACtC,CAAC;IAEJ,KAAK,CAAC,QAA8B;QAClC,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAc,EAAE,EAAE;YACzD,MAAM,KAAK,GAAa,CAAC,MAAM,CAAC,CAAC;YAEjC,2BAA2B;YAC3B,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;YAC7D,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;YAED,+CAA+C;YAC/C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBACpF,IAAI,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;oBACxC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;YAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;QAC3B,OAAO,IAAI,EAAE,GAAG,IAAI,SAAS,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,MAAc;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,kCAAkC,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IACpE,IAAI,iCAAiC,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACjE,IAAI,oCAAoC,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACrE,IAAI,uEAAuE,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IACvG,OAAO,QAAQ,CAAC,CAAC,kCAAkC;AACrD,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Keyword Bridge — Session-based dedup for keyword-triggered spec injection.
|
|
3
|
+
*
|
|
4
|
+
* Tracks which keywords and entries have already been injected in the current session
|
|
5
|
+
* to prevent duplicate injection when the same keyword appears in multiple prompts.
|
|
6
|
+
*
|
|
7
|
+
* Bridge file: {tmpdir}/maestro-spec-kw-{sessionId}.json
|
|
8
|
+
*/
|
|
9
|
+
export interface SpecKeywordBridge {
|
|
10
|
+
session_id: string;
|
|
11
|
+
injected_keywords: string[];
|
|
12
|
+
injected_entries: string[];
|
|
13
|
+
updated_at: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Read the spec keyword bridge file for a session.
|
|
17
|
+
* Returns null if the file does not exist or is unreadable.
|
|
18
|
+
*/
|
|
19
|
+
export declare function readSpecBridge(sessionId: string): SpecKeywordBridge | null;
|
|
20
|
+
/**
|
|
21
|
+
* Mark keywords and entry IDs as injected for this session.
|
|
22
|
+
* Merges with existing bridge data (additive, never removes).
|
|
23
|
+
*/
|
|
24
|
+
export declare function markInjected(sessionId: string, keywords: string[], entryIds: string[]): void;
|
|
25
|
+
/**
|
|
26
|
+
* Check if a keyword has already been injected this session.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isKeywordInjected(sessionId: string, keyword: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Check if an entry has already been injected this session.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isEntryInjected(sessionId: string, entryId: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Filter entries to only those not yet injected in this session.
|
|
35
|
+
* An entry is considered "already injected" if its ID is in the bridge.
|
|
36
|
+
*/
|
|
37
|
+
export declare function filterUnjected<T extends {
|
|
38
|
+
id: string;
|
|
39
|
+
}>(sessionId: string, entries: T[]): T[];
|
|
40
|
+
//# sourceMappingURL=spec-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-bridge.d.ts","sourceRoot":"","sources":["../../../src/hooks/spec-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAU1E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,EAAE,GACjB,IAAI,CA0BN;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAI7E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAI3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACrD,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,EAAE,GACX,CAAC,EAAE,CAML"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Keyword Bridge — Session-based dedup for keyword-triggered spec injection.
|
|
3
|
+
*
|
|
4
|
+
* Tracks which keywords and entries have already been injected in the current session
|
|
5
|
+
* to prevent duplicate injection when the same keyword appears in multiple prompts.
|
|
6
|
+
*
|
|
7
|
+
* Bridge file: {tmpdir}/maestro-spec-kw-{sessionId}.json
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { tmpdir } from 'node:os';
|
|
12
|
+
import { SPEC_KW_BRIDGE_PREFIX } from './constants.js';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Public API
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Read the spec keyword bridge file for a session.
|
|
18
|
+
* Returns null if the file does not exist or is unreadable.
|
|
19
|
+
*/
|
|
20
|
+
export function readSpecBridge(sessionId) {
|
|
21
|
+
const path = bridgePath(sessionId);
|
|
22
|
+
if (!existsSync(path))
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
const raw = readFileSync(path, 'utf-8');
|
|
26
|
+
return JSON.parse(raw);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Mark keywords and entry IDs as injected for this session.
|
|
34
|
+
* Merges with existing bridge data (additive, never removes).
|
|
35
|
+
*/
|
|
36
|
+
export function markInjected(sessionId, keywords, entryIds) {
|
|
37
|
+
const existing = readSpecBridge(sessionId) ?? {
|
|
38
|
+
session_id: sessionId,
|
|
39
|
+
injected_keywords: [],
|
|
40
|
+
injected_entries: [],
|
|
41
|
+
updated_at: 0,
|
|
42
|
+
};
|
|
43
|
+
const kwSet = new Set(existing.injected_keywords);
|
|
44
|
+
for (const kw of keywords)
|
|
45
|
+
kwSet.add(kw.toLowerCase());
|
|
46
|
+
const entrySet = new Set(existing.injected_entries);
|
|
47
|
+
for (const id of entryIds)
|
|
48
|
+
entrySet.add(id);
|
|
49
|
+
const updated = {
|
|
50
|
+
session_id: sessionId,
|
|
51
|
+
injected_keywords: [...kwSet],
|
|
52
|
+
injected_entries: [...entrySet],
|
|
53
|
+
updated_at: Math.floor(Date.now() / 1000),
|
|
54
|
+
};
|
|
55
|
+
try {
|
|
56
|
+
writeFileSync(bridgePath(sessionId), JSON.stringify(updated), 'utf-8');
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// Best-effort — don't fail the hook if bridge write fails
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check if a keyword has already been injected this session.
|
|
64
|
+
*/
|
|
65
|
+
export function isKeywordInjected(sessionId, keyword) {
|
|
66
|
+
const bridge = readSpecBridge(sessionId);
|
|
67
|
+
if (!bridge)
|
|
68
|
+
return false;
|
|
69
|
+
return bridge.injected_keywords.includes(keyword.toLowerCase());
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if an entry has already been injected this session.
|
|
73
|
+
*/
|
|
74
|
+
export function isEntryInjected(sessionId, entryId) {
|
|
75
|
+
const bridge = readSpecBridge(sessionId);
|
|
76
|
+
if (!bridge)
|
|
77
|
+
return false;
|
|
78
|
+
return bridge.injected_entries.includes(entryId);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Filter entries to only those not yet injected in this session.
|
|
82
|
+
* An entry is considered "already injected" if its ID is in the bridge.
|
|
83
|
+
*/
|
|
84
|
+
export function filterUnjected(sessionId, entries) {
|
|
85
|
+
const bridge = readSpecBridge(sessionId);
|
|
86
|
+
if (!bridge)
|
|
87
|
+
return entries;
|
|
88
|
+
const injectedSet = new Set(bridge.injected_entries);
|
|
89
|
+
return entries.filter(e => !injectedSet.has(e.id));
|
|
90
|
+
}
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// Internal
|
|
93
|
+
// ============================================================================
|
|
94
|
+
function bridgePath(sessionId) {
|
|
95
|
+
return join(tmpdir(), `${SPEC_KW_BRIDGE_PREFIX}${sessionId}.json`);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=spec-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-bridge.js","sourceRoot":"","sources":["../../../src/hooks/spec-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-injector.d.ts","sourceRoot":"","sources":["../../../src/hooks/spec-injector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"spec-injector.d.ts","sourceRoot":"","sources":["../../../src/hooks/spec-injector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAM7D,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,qDAAqD;IACrD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA+BD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,mBAAmB,EAC5B,GAAG,CAAC,EAAE,MAAM,GACX,mBAAmB,CAmDrB"}
|
|
@@ -15,23 +15,21 @@ import { resolveSelf } from '../tools/team-members.js';
|
|
|
15
15
|
// Default agent-type → spec-category mapping
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
17
|
const DEFAULT_AGENT_SPEC_MAP = {
|
|
18
|
-
// Execution agents →
|
|
19
|
-
'code-developer': { categories: ['
|
|
20
|
-
'tdd-developer': { categories: ['
|
|
21
|
-
'workflow-executor': { categories: ['
|
|
22
|
-
'universal-executor': { categories: ['
|
|
23
|
-
'test-fix-agent': { categories: ['
|
|
24
|
-
// Planning agents →
|
|
25
|
-
'cli-lite-planning-agent': { categories: ['
|
|
26
|
-
'action-planning-agent': { categories: ['
|
|
27
|
-
'workflow-planner': { categories: ['
|
|
18
|
+
// Execution agents → coding specs
|
|
19
|
+
'code-developer': { categories: ['coding'], extras: [] },
|
|
20
|
+
'tdd-developer': { categories: ['coding', 'test'], extras: [] },
|
|
21
|
+
'workflow-executor': { categories: ['coding'], extras: [] },
|
|
22
|
+
'universal-executor': { categories: ['coding'], extras: [] },
|
|
23
|
+
'test-fix-agent': { categories: ['coding', 'test'], extras: [] },
|
|
24
|
+
// Planning agents → arch specs
|
|
25
|
+
'cli-lite-planning-agent': { categories: ['arch'], extras: [] },
|
|
26
|
+
'action-planning-agent': { categories: ['arch'], extras: [] },
|
|
27
|
+
'workflow-planner': { categories: ['arch'], extras: [] },
|
|
28
28
|
// Review agents → review specs
|
|
29
29
|
'workflow-reviewer': { categories: ['review'], extras: [] },
|
|
30
30
|
// Debug agents → debug specs
|
|
31
31
|
'debug-explore-agent': { categories: ['debug'], extras: [] },
|
|
32
32
|
'workflow-debugger': { categories: ['debug'], extras: [] },
|
|
33
|
-
// Explore agents → exploration (lightweight)
|
|
34
|
-
'Explore': { categories: ['exploration'], extras: [] },
|
|
35
33
|
};
|
|
36
34
|
// ---------------------------------------------------------------------------
|
|
37
35
|
// Public API
|
|
@@ -65,6 +63,14 @@ export function evaluateSpecInjection(agentType, projectPath, sessionId, config,
|
|
|
65
63
|
totalCount += result.totalLoaded;
|
|
66
64
|
}
|
|
67
65
|
}
|
|
66
|
+
if (sections.length === 0 && !sessionId)
|
|
67
|
+
return { inject: false };
|
|
68
|
+
// Keyword-based injection from agent prompt (if sessionId available)
|
|
69
|
+
if (sessionId && projectPath) {
|
|
70
|
+
// Extract prompt from the original function context — the caller should pass it
|
|
71
|
+
// For now, keyword injection from agent prompts is handled at the hook runner level
|
|
72
|
+
// via evaluateKeywordInjection(), not here. This keeps the two concerns separate.
|
|
73
|
+
}
|
|
68
74
|
if (sections.length === 0)
|
|
69
75
|
return { inject: false };
|
|
70
76
|
const rawContent = sections.join('\n\n---\n\n');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-injector.js","sourceRoot":"","sources":["../../../src/hooks/spec-injector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAqB,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"spec-injector.js","sourceRoot":"","sources":["../../../src/hooks/spec-injector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase Orchestrator - Structured team phase management.
|
|
3
|
+
*
|
|
4
|
+
* Manages phase transitions with guard evaluation, fix retry counting,
|
|
5
|
+
* state broadcast via team-msg, and transition persistence.
|
|
6
|
+
*/
|
|
7
|
+
import { TeamPhase, type PhaseGateConfig, type PhaseStatus } from './phase-types.js';
|
|
8
|
+
export interface TransitionResult {
|
|
9
|
+
success: boolean;
|
|
10
|
+
from: TeamPhase;
|
|
11
|
+
to: TeamPhase;
|
|
12
|
+
/** Non-empty when success=false, explains why the transition was rejected */
|
|
13
|
+
reason?: string;
|
|
14
|
+
/** Gate evaluation reasons (populated even on success if gates were soft-blocked and forced) */
|
|
15
|
+
gateReasons: string[];
|
|
16
|
+
}
|
|
17
|
+
export declare class PhaseOrchestrator {
|
|
18
|
+
private readonly sessionId;
|
|
19
|
+
private _currentPhase;
|
|
20
|
+
private _fixAttempts;
|
|
21
|
+
private readonly _history;
|
|
22
|
+
constructor(sessionId: string);
|
|
23
|
+
/** Current phase of the team workflow */
|
|
24
|
+
get currentPhase(): TeamPhase;
|
|
25
|
+
/** Number of fix attempts in the current fix loop */
|
|
26
|
+
get fixAttempts(): number;
|
|
27
|
+
/**
|
|
28
|
+
* Attempt to transition to `targetPhase`.
|
|
29
|
+
*
|
|
30
|
+
* Steps:
|
|
31
|
+
* 1. Validate the transition exists in TRANSITIONS map
|
|
32
|
+
* 2. Check fix retry limit for fix->review transitions
|
|
33
|
+
* 3. Evaluate phase-gate guard (if gateConfig provided)
|
|
34
|
+
* 4. Apply the transition, update counters, record history
|
|
35
|
+
* 5. Broadcast state_update via team-msg opLog
|
|
36
|
+
* 6. Persist transition to transitions.jsonl
|
|
37
|
+
*/
|
|
38
|
+
transitionTo(targetPhase: TeamPhase, options?: {
|
|
39
|
+
trigger?: string;
|
|
40
|
+
force?: boolean;
|
|
41
|
+
gateConfig?: PhaseGateConfig;
|
|
42
|
+
/** Callback to broadcast via team-msg (decoupled from direct import) */
|
|
43
|
+
broadcast?: (sessionId: string, phase: TeamPhase, fixAttempts: number) => void;
|
|
44
|
+
}): TransitionResult;
|
|
45
|
+
getPhaseStatus(): PhaseStatus;
|
|
46
|
+
private applyTransition;
|
|
47
|
+
/**
|
|
48
|
+
* Append transition record to .workflow/.team/{session}/transitions.jsonl
|
|
49
|
+
*/
|
|
50
|
+
private persistTransition;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=phase-orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-orchestrator.d.ts","sourceRoot":"","sources":["../../../src/team/phase-orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EACL,SAAS,EAET,KAAK,eAAe,EACpB,KAAK,WAAW,EAEjB,MAAM,kBAAkB,CAAC;AAa1B,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,SAAS,CAAC;IACd,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAMD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0B;gBAEvC,SAAS,EAAE,MAAM;IAO7B,yCAAyC;IACzC,IAAI,YAAY,IAAI,SAAS,CAE5B;IAED,qDAAqD;IACrD,IAAI,WAAW,IAAI,MAAM,CAExB;IAMD;;;;;;;;;;OAUG;IACH,YAAY,CACV,WAAW,EAAE,SAAS,EACtB,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,UAAU,CAAC,EAAE,eAAe,CAAC;QAC7B,wEAAwE;QACxE,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;KAChF,GACA,gBAAgB;IA8DnB,cAAc,IAAI,WAAW;IAc7B,OAAO,CAAC,eAAe;IAwCvB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAa1B"}
|