azclaude-copilot 0.7.6 → 0.7.8
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/README.md +2 -2
- package/bin/cli.js +63 -6
- package/bin/copilot.js +6 -11
- package/package.json +1 -1
- package/templates/agents/orchestrator.md +15 -1
- package/templates/capabilities/manifest.md +1 -0
- package/templates/capabilities/shared/plan-tracker.md +6 -0
- package/templates/capabilities/shared/strategies.md +90 -0
- package/templates/commands/blueprint.md +2 -0
- package/templates/commands/tasks.md +40 -6
package/README.md
CHANGED
|
@@ -637,11 +637,11 @@ AZCLAUDE is a lazy-loaded environment of 48 capability modules. It only loads wh
|
|
|
637
637
|
|
|
638
638
|
## Verified
|
|
639
639
|
|
|
640
|
-
|
|
640
|
+
1998 tests. Every template, command, capability, agent, hook, and CLI feature verified.
|
|
641
641
|
|
|
642
642
|
```bash
|
|
643
643
|
bash tests/test-features.sh
|
|
644
|
-
# Results:
|
|
644
|
+
# Results: 1998 passed, 0 failed, 1998 total
|
|
645
645
|
```
|
|
646
646
|
|
|
647
647
|
---
|
package/bin/cli.js
CHANGED
|
@@ -6,6 +6,14 @@ const os = require('os');
|
|
|
6
6
|
const crypto = require('crypto');
|
|
7
7
|
const { execSync } = require('child_process');
|
|
8
8
|
|
|
9
|
+
// Strip --cli <value> from argv early so it doesn't interfere with positional args
|
|
10
|
+
const cliArgIdx = process.argv.indexOf('--cli');
|
|
11
|
+
let CLI_OVERRIDE = null;
|
|
12
|
+
if (cliArgIdx !== -1 && process.argv[cliArgIdx + 1]) {
|
|
13
|
+
CLI_OVERRIDE = process.argv[cliArgIdx + 1];
|
|
14
|
+
process.argv.splice(cliArgIdx, 2); // remove --cli and its value from argv
|
|
15
|
+
}
|
|
16
|
+
|
|
9
17
|
const TEMPLATE_DIR = path.join(__dirname, '..', 'templates');
|
|
10
18
|
const CORE_COMMANDS = ['setup', 'fix', 'add', 'audit', 'test', 'blueprint', 'ship', 'pulse', 'explain', 'snapshot', 'persist'];
|
|
11
19
|
const EXTENDED_COMMANDS = ['dream', 'refactor', 'doc', 'loop', 'migrate', 'deps', 'find', 'create', 'reflect', 'hookify', 'sentinel', 'clarify', 'spec', 'analyze', 'constitute', 'tasks', 'issues', 'driven', 'mcp', 'verify', 'inoculate', 'ghost-test', 'visualize'];
|
|
@@ -73,7 +81,19 @@ const CLI_TABLE = [
|
|
|
73
81
|
];
|
|
74
82
|
|
|
75
83
|
function detectCLI() {
|
|
76
|
-
// 0.
|
|
84
|
+
// 0. --cli flag override (stripped from argv at top of file)
|
|
85
|
+
if (CLI_OVERRIDE) {
|
|
86
|
+
const v = CLI_OVERRIDE.toLowerCase();
|
|
87
|
+
const forced = CLI_TABLE.find(c =>
|
|
88
|
+
c.name.toLowerCase().replace(/\s/g,'') === v
|
|
89
|
+
|| c.exe === v
|
|
90
|
+
|| c.cfg === `.${v}`
|
|
91
|
+
);
|
|
92
|
+
if (forced) return forced;
|
|
93
|
+
console.log(` ⚠ Unknown CLI "${CLI_OVERRIDE}". Valid: ${CLI_TABLE.map(c => c.exe).join(', ')}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 0a. Env override (for testing / explicit selection)
|
|
77
97
|
if (process.env.AZCLAUDE_CLI) {
|
|
78
98
|
const forced = CLI_TABLE.find(c => c.name.toLowerCase().replace(/\s/g,'') === process.env.AZCLAUDE_CLI.toLowerCase());
|
|
79
99
|
if (forced) return forced;
|
|
@@ -116,6 +136,36 @@ function substitutePaths(content, cfg) {
|
|
|
116
136
|
return content.replace(/\.claude\//g, `${cfg}/`);
|
|
117
137
|
}
|
|
118
138
|
|
|
139
|
+
// Adapt command frontmatter for non-Claude CLIs.
|
|
140
|
+
// Claude Code: keeps all fields as-is.
|
|
141
|
+
// OpenCode: keeps description, strips Claude-specific fields (allowed-tools, disable-model-invocation, argument-hint).
|
|
142
|
+
// Codex CLI: keeps description, strips Claude-specific fields.
|
|
143
|
+
// Gemini CLI: converts to TOML format (handled separately in installCommandsGemini).
|
|
144
|
+
function adaptCommandContent(content, cliName) {
|
|
145
|
+
if (cliName === 'Claude Code') return content;
|
|
146
|
+
|
|
147
|
+
// Parse frontmatter
|
|
148
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
149
|
+
if (!fmMatch) return content; // no frontmatter, return as-is
|
|
150
|
+
|
|
151
|
+
const fmBlock = fmMatch[1];
|
|
152
|
+
const body = fmMatch[2];
|
|
153
|
+
|
|
154
|
+
// Extract description (may be multi-line with >)
|
|
155
|
+
const descMatch = fmBlock.match(/description:\s*>?\s*\n?([\s\S]*?)(?=\n\w|\n---|\s*$)/);
|
|
156
|
+
const descSimple = fmBlock.match(/description:\s*"?([^"\n]+)"?\s*$/m);
|
|
157
|
+
let description = '';
|
|
158
|
+
if (descMatch) {
|
|
159
|
+
description = descMatch[1].split('\n').map(l => l.trim()).filter(Boolean).join(' ');
|
|
160
|
+
} else if (descSimple) {
|
|
161
|
+
description = descSimple[1].trim();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// For OpenCode / Codex: rebuild frontmatter with only supported fields
|
|
165
|
+
const newFm = description ? `---\ndescription: ${description}\n---` : '---\n---';
|
|
166
|
+
return `${newFm}\n${body}`;
|
|
167
|
+
}
|
|
168
|
+
|
|
119
169
|
// ─── Hook Scripts ─────────────────────────────────────────────────────────────
|
|
120
170
|
|
|
121
171
|
const HOOK_SCRIPTS = ['user-prompt.js', 'stop.js', 'post-tool-use.js', 'pre-tool-use.js', 'visualizer-hook.js'];
|
|
@@ -365,7 +415,7 @@ function installCapabilities(projectDir, cfg, full) {
|
|
|
365
415
|
|
|
366
416
|
// ─── Commands (Skills) ────────────────────────────────────────────────────────
|
|
367
417
|
|
|
368
|
-
function installCommands(projectDir, cfg) {
|
|
418
|
+
function installCommands(projectDir, cfg, cliName) {
|
|
369
419
|
const commandsDir = path.join(projectDir, cfg, 'commands');
|
|
370
420
|
fs.mkdirSync(commandsDir, { recursive: true });
|
|
371
421
|
|
|
@@ -374,14 +424,19 @@ function installCommands(projectDir, cfg) {
|
|
|
374
424
|
const dst = path.join(commandsDir, `${cmd}.md`);
|
|
375
425
|
if (!fs.existsSync(src)) continue;
|
|
376
426
|
if (!fs.existsSync(dst)) {
|
|
377
|
-
fs.
|
|
427
|
+
let content = fs.readFileSync(src, 'utf8');
|
|
428
|
+
content = substitutePaths(content, cfg);
|
|
429
|
+
content = adaptCommandContent(content, cliName || 'Claude Code');
|
|
430
|
+
fs.writeFileSync(dst, content);
|
|
378
431
|
ok(`/${cmd} installed`);
|
|
379
432
|
} else if (forceUpdate) {
|
|
380
433
|
// --update: overwrite with latest template
|
|
381
|
-
|
|
434
|
+
let srcContent = fs.readFileSync(src, 'utf8');
|
|
435
|
+
srcContent = substitutePaths(srcContent, cfg);
|
|
436
|
+
srcContent = adaptCommandContent(srcContent, cliName || 'Claude Code');
|
|
382
437
|
const dstContent = fs.readFileSync(dst, 'utf8');
|
|
383
438
|
if (srcContent !== dstContent) {
|
|
384
|
-
fs.
|
|
439
|
+
fs.writeFileSync(dst, srcContent);
|
|
385
440
|
ok(`/${cmd} updated (--update)`);
|
|
386
441
|
}
|
|
387
442
|
} else {
|
|
@@ -1273,7 +1328,7 @@ if (cli.cfg === '.claude') {
|
|
|
1273
1328
|
installGlobalHooks(cli);
|
|
1274
1329
|
}
|
|
1275
1330
|
installCapabilities(projectDir, cli.cfg, fullInstall);
|
|
1276
|
-
installCommands(projectDir, cli.cfg);
|
|
1331
|
+
installCommands(projectDir, cli.cfg, cli.name);
|
|
1277
1332
|
installSkills(projectDir, cli.cfg);
|
|
1278
1333
|
installScripts(projectDir, cli.cfg);
|
|
1279
1334
|
installVisualizer(projectDir, cli.cfg);
|
|
@@ -1401,4 +1456,6 @@ console.log('');
|
|
|
1401
1456
|
console.log(' ─────────────────────────────────────────────');
|
|
1402
1457
|
console.log(' all commands: /help · docs: github.com/haytamAroui/AZ-CLAUDE-COPILOT');
|
|
1403
1458
|
console.log(' upgrade: npx azclaude-copilot@latest');
|
|
1459
|
+
console.log(' other CLI: npx azclaude-copilot --cli opencode');
|
|
1460
|
+
console.log(' (claude, opencode, gemini, codex, cursor)');
|
|
1404
1461
|
console.log('════════════════════════════════════════════════\n');
|
package/bin/copilot.js
CHANGED
|
@@ -27,19 +27,14 @@ const args = process.argv.slice(2);
|
|
|
27
27
|
// Catch `npx azclaude-copilot setup` and similar — run the installer instead
|
|
28
28
|
// Also: no arguments at all → run installer (auto-detect install vs upgrade)
|
|
29
29
|
const SUBCOMMANDS = ['setup', 'init', 'install', 'doctor', 'upgrade'];
|
|
30
|
-
const CLI_FLAGS = ['--update', '--full', '--audit'];
|
|
30
|
+
const CLI_FLAGS = ['--update', '--full', '--audit', '--cli'];
|
|
31
31
|
const noArgs = args.length === 0 || (args.length === 1 && CLI_FLAGS.includes(args[0]));
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const subDir = path.resolve(subPositional[0] || '.');
|
|
36
|
-
if (!noArgs) console.log(`\n Running AZCLAUDE installer on ${subDir}...${subFlags.length ? ' (' + subFlags.join(' ') + ')' : ''}\n`);
|
|
32
|
+
// --cli <value> means "install for this CLI" — route to installer
|
|
33
|
+
const hasCliFlag = args.includes('--cli');
|
|
34
|
+
if (noArgs || hasCliFlag || (args[0] && SUBCOMMANDS.includes(args[0].toLowerCase()))) {
|
|
37
35
|
const cliPath = path.join(__dirname, 'cli.js');
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
? [cliPath, subDir, '--doctor', ...subFlags]
|
|
41
|
-
: [cliPath, subDir, ...subFlags];
|
|
42
|
-
const r = spawnSync('node', subArgs, { cwd: subDir, stdio: 'inherit' });
|
|
36
|
+
// Pass all args through to cli.js — it handles --cli stripping internally
|
|
37
|
+
const r = spawnSync('node', [cliPath, ...args], { cwd: process.cwd(), stdio: 'inherit' });
|
|
43
38
|
process.exit(r.status || 0);
|
|
44
39
|
}
|
|
45
40
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azclaude-copilot",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "AI coding environment — 40 commands, 10 skills, 15 agents, real-time visualizer, memory, reflexes, evolution. Install: npx azclaude-copilot@latest, then open Claude Code.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"azclaude": "bin/cli.js",
|
|
@@ -30,6 +30,7 @@ Read these files (skip if absent):
|
|
|
30
30
|
- `.claude/memory/decisions.md` — prior architecture choices
|
|
31
31
|
- `.claude/memory/patterns.md` — established conventions
|
|
32
32
|
- `.claude/constitution.md` — non-negotiables and required patterns (if present)
|
|
33
|
+
- `capabilities/shared/strategies.md` — load if plan.md has `strategy:` field (dispatch ordering)
|
|
33
34
|
|
|
34
35
|
If no plan.md → run `/blueprint` first.
|
|
35
36
|
If CLAUDE.md unfilled → run `/setup` with intent from copilot-intent.md first.
|
|
@@ -130,7 +131,20 @@ If any two candidates share a written file → dispatch the conflicting one sequ
|
|
|
130
131
|
| Standard | Writes to unique files | Parallel with worktree isolation |
|
|
131
132
|
|
|
132
133
|
**Max parallel agents:** 6 (default). Override with `max_parallel` in plan.md frontmatter.
|
|
133
|
-
|
|
134
|
+
|
|
135
|
+
**Strategy-based dispatch ordering:**
|
|
136
|
+
Check plan.md frontmatter for `strategy:` field (risk_first, value_first, simple_first, complex_first).
|
|
137
|
+
If present → load `capabilities/shared/strategies.md`, score each ready milestone, sort descending.
|
|
138
|
+
If absent → dispatch by milestone ID order (M2 before M3).
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
grep -m1 "^strategy:" .claude/plan.md 2>/dev/null || echo "no strategy"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Scoring uses each milestone's `Risk:`, `Value:`, and `Complexity:` fields from plan.md.
|
|
145
|
+
If a milestone is missing an attribute, default: Risk=3, Value=3, Complexity=MEDIUM.
|
|
146
|
+
|
|
147
|
+
If ready milestones exceed max_parallel → dispatch highest-scored first, queue the rest.
|
|
134
148
|
|
|
135
149
|
- All done → SHIP
|
|
136
150
|
- All remaining blocked → BLOCKER RECOVERY
|
|
@@ -31,6 +31,7 @@ Load only the files that match the current task. Never load the full list.
|
|
|
31
31
|
| shared/ultrathink.md | $ARGUMENTS contains --deep, or command needs extended thinking for complex analysis | ~80 |
|
|
32
32
|
| shared/context-relay.md | About to spawn a subagent — pass pre-read files to eliminate redundant reads across agent boundaries | ~300 |
|
|
33
33
|
| shared/toolchain-gate.md | /copilot dispatch, /parallel, agent verify, env-scan — stack detection, verify commands, toolchain bootstrap, 3-tier verification, log protocol | ~500 |
|
|
34
|
+
| shared/strategies.md | /tasks --strategy flag, or orchestrator reading plan.md with strategy: field — milestone dispatch ordering within waves | ~120 |
|
|
34
35
|
|
|
35
36
|
## Level Builders — load ONE at a time
|
|
36
37
|
| File | When to load | Tokens |
|
|
@@ -23,6 +23,8 @@ Every plan.md must follow this structure exactly. The copilot runner parses it.
|
|
|
23
23
|
- Dirs: {top-level directories this milestone owns — e.g. src/auth/, tests/auth/}
|
|
24
24
|
- Depends: {M-numbers this depends on, or "none"}
|
|
25
25
|
- Parallel: {yes|no} — yes = safe to run alongside other same-wave milestones
|
|
26
|
+
- Risk: {1-5} — failure cost (5 = highest risk, run first in risk_first strategy)
|
|
27
|
+
- Value: {1-5} — business impact (5 = core feature, run first in value_first strategy)
|
|
26
28
|
- Commit: {expected commit message}
|
|
27
29
|
|
|
28
30
|
### M2: {title}
|
|
@@ -32,6 +34,8 @@ Every plan.md must follow this structure exactly. The copilot runner parses it.
|
|
|
32
34
|
- Dirs: src/users/, tests/users/
|
|
33
35
|
- Depends: M1
|
|
34
36
|
- Parallel: yes
|
|
37
|
+
- Risk: {1-5}
|
|
38
|
+
- Value: {1-5}
|
|
35
39
|
- Commit: ...
|
|
36
40
|
|
|
37
41
|
## Summary
|
|
@@ -51,6 +55,8 @@ Waves: {N} (max parallel in one wave: {N})
|
|
|
51
55
|
| `Files:` | Expected file paths to create/modify. Blueprint's estimate — problem-architect refines to `Files Written:`. |
|
|
52
56
|
| `Parallel: yes` | Orchestrator may dispatch with worktree isolation alongside other Wave N milestones. |
|
|
53
57
|
| `Parallel: no` | Reasons: touches shared config, schema change, or has runtime dep on sibling milestone. |
|
|
58
|
+
| `Risk: 1-5` | Dispatch priority score. 5 = highest risk (fail fast in `risk_first` strategy). Default: 3. |
|
|
59
|
+
| `Value: 1-5` | Business value score. 5 = highest value (ship first in `value_first` strategy). Default: 3. |
|
|
54
60
|
|
|
55
61
|
## Status Values
|
|
56
62
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dispatch-strategies
|
|
3
|
+
description: >
|
|
4
|
+
Pluggable scoring strategies for milestone dispatch ordering within the same wave.
|
|
5
|
+
Load when: orchestrator reads plan.md with strategy: field set, or /tasks called with --strategy flag.
|
|
6
|
+
NOT loaded by default — only when strategy-based ranking is active.
|
|
7
|
+
tokens: ~120
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Dispatch Strategies
|
|
11
|
+
|
|
12
|
+
Milestones in the same wave have no dependency between them — they CAN run in any order.
|
|
13
|
+
Strategies decide which order is BEST by scoring each milestone on its attributes.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Milestone Attributes (scored by problem-architect or /blueprint)
|
|
18
|
+
|
|
19
|
+
| Attribute | Scale | Meaning |
|
|
20
|
+
|-----------|-------|---------|
|
|
21
|
+
| `Risk: 1-5` | 1 = safe, 5 = likely to fail or cascade | Failure cost. Higher = more dangerous. |
|
|
22
|
+
| `Value: 1-5` | 1 = nice-to-have, 5 = core feature | Business impact. Higher = more important. |
|
|
23
|
+
| `Complexity:` | SIMPLE / MEDIUM / COMPLEX | Effort estimate. Maps to 1 / 2 / 3 for scoring. |
|
|
24
|
+
|
|
25
|
+
If a milestone is missing an attribute, default: Risk=3, Value=3, Complexity=MEDIUM.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Strategies
|
|
30
|
+
|
|
31
|
+
### risk_first (default for /copilot)
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
score = Risk × 2 + Complexity_int
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Dispatch highest score first. Surfaces dangerous milestones early — fail fast while there's still room to pivot. If M3 has Risk:5 and M4 has Risk:2, run M3 first.
|
|
38
|
+
|
|
39
|
+
### value_first
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
score = Value × 2 + (6 - Risk)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Dispatch highest score first. Delivers the most impactful features early. Low-risk, high-value milestones rank highest — ship what matters.
|
|
46
|
+
|
|
47
|
+
### simple_first
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
score = (4 - Complexity_int) × 2 + (6 - Risk)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Dispatch highest score first. Clears easy wins, builds momentum, unblocks dependents cheaply. Best for greenfield projects where early confidence matters.
|
|
54
|
+
|
|
55
|
+
### complex_first
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
score = Complexity_int × 2 + Risk
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Dispatch highest score first. Front-loads the hardest work while energy and context are fresh. Best for late-stage projects where derisking matters most.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## How to Set a Strategy
|
|
66
|
+
|
|
67
|
+
**In plan.md frontmatter:**
|
|
68
|
+
```markdown
|
|
69
|
+
---
|
|
70
|
+
strategy: risk_first
|
|
71
|
+
---
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Via /tasks flag:**
|
|
75
|
+
```
|
|
76
|
+
/tasks --strategy value_first
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Orchestrator behavior:**
|
|
80
|
+
- If plan.md has `strategy:` → use it for all wave dispatch ordering
|
|
81
|
+
- If no `strategy:` field → no scoring, dispatch by milestone ID order (current default)
|
|
82
|
+
- Strategy applies ONLY within a wave — cross-wave ordering is always dependency-driven
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Tie-Breaking
|
|
87
|
+
|
|
88
|
+
When two milestones have the same score:
|
|
89
|
+
1. Higher Risk breaks the tie (surface problems early)
|
|
90
|
+
2. If still tied, lower milestone ID first (M2 before M3)
|
|
@@ -414,6 +414,8 @@ When running inside `/copilot` (detected by: `.claude/copilot-intent.md` exists)
|
|
|
414
414
|
- Each milestone = one logical unit of work (1-3 files, one commit)
|
|
415
415
|
- Include `Depends:` for milestones that require prior work
|
|
416
416
|
- Include `Files:` with expected paths
|
|
417
|
+
- Include `Risk: 1-5` — failure cost (1=safe, 5=likely to fail or cascade). Score based on: touches shared state? new pattern? external dependency?
|
|
418
|
+
- Include `Value: 1-5` — business impact (1=nice-to-have, 5=core feature). Score based on: user-facing? blocks other features? revenue impact?
|
|
417
419
|
- Include `Commit:` with conventional commit format
|
|
418
420
|
- Write `## Summary` with counts at the bottom
|
|
419
421
|
|
|
@@ -24,6 +24,19 @@ $ARGUMENTS
|
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
+
## Strategy Detection
|
|
28
|
+
|
|
29
|
+
If `$ARGUMENTS` contains `--strategy`:
|
|
30
|
+
1. Strip `--strategy {name}` from arguments before processing
|
|
31
|
+
2. Valid strategies: `risk_first`, `value_first`, `simple_first`, `complex_first`
|
|
32
|
+
3. Load `capabilities/shared/strategies.md` for scoring formulas
|
|
33
|
+
4. Apply strategy scoring in Step 4b (after wave grouping, before output)
|
|
34
|
+
|
|
35
|
+
If no `--strategy` flag → check plan.md frontmatter for `strategy:` field.
|
|
36
|
+
If neither → no scoring, display milestones in ID order within each wave (current default).
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
27
40
|
## Step 1: Find the Source
|
|
28
41
|
|
|
29
42
|
```bash
|
|
@@ -87,6 +100,24 @@ Algorithm:
|
|
|
87
100
|
|
|
88
101
|
---
|
|
89
102
|
|
|
103
|
+
## Step 4b: Strategy Scoring (if active)
|
|
104
|
+
|
|
105
|
+
If a strategy was detected (from `--strategy` flag or plan.md `strategy:` field):
|
|
106
|
+
|
|
107
|
+
For each pending milestone, read its `Risk:`, `Value:`, and `Complexity:` fields.
|
|
108
|
+
Map Complexity to integer: SIMPLE=1, MEDIUM=2, COMPLEX=3. Default missing values: Risk=3, Value=3, Complexity=MEDIUM.
|
|
109
|
+
|
|
110
|
+
Apply the scoring formula from `capabilities/shared/strategies.md`:
|
|
111
|
+
- `risk_first`: score = Risk × 2 + Complexity_int
|
|
112
|
+
- `value_first`: score = Value × 2 + (6 - Risk)
|
|
113
|
+
- `simple_first`: score = (4 - Complexity_int) × 2 + (6 - Risk)
|
|
114
|
+
- `complex_first`: score = Complexity_int × 2 + Risk
|
|
115
|
+
|
|
116
|
+
Sort milestones within each wave by score (descending). Ties broken by higher Risk, then lower ID.
|
|
117
|
+
Add a `Score: {N}` column to the output in Step 5.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
90
121
|
## Step 5: Output the Task Graph
|
|
91
122
|
|
|
92
123
|
```
|
|
@@ -96,13 +127,13 @@ Source: {file}
|
|
|
96
127
|
Total tasks: {N} | Done: {N} | Pending: {N} | Blocked: {N}
|
|
97
128
|
|
|
98
129
|
── Wave 1 (can start now) ──────────────────────────────────────
|
|
99
|
-
▶ M1 {title} [Files: src/auth/login.ts]
|
|
100
|
-
▶ M2 {title} [Files: src/models/user.ts]
|
|
101
|
-
▶ M3 {title} [Files: tests/auth/]
|
|
130
|
+
▶ M1 {title} [Files: src/auth/login.ts] {Score: N — if strategy active}
|
|
131
|
+
▶ M2 {title} [Files: src/models/user.ts] {Score: N — if strategy active}
|
|
132
|
+
▶ M3 {title} [Files: tests/auth/] {Score: N — if strategy active}
|
|
102
133
|
|
|
103
134
|
── Wave 2 (after Wave 1) ───────────────────────────────────────
|
|
104
|
-
▶ M4 {title} ←depends M1 [Files: src/api/routes.ts]
|
|
105
|
-
▶ M5 {title} ←depends M2 [Files: src/services/]
|
|
135
|
+
▶ M4 {title} ←depends M1 [Files: src/api/routes.ts] {Score: N}
|
|
136
|
+
▶ M5 {title} ←depends M2 [Files: src/services/] {Score: N}
|
|
106
137
|
|
|
107
138
|
── Wave 3 (after Wave 2) ───────────────────────────────────────
|
|
108
139
|
▶ M6 {title} ←depends M4,M5 [Files: src/app.ts]
|
|
@@ -126,10 +157,13 @@ Critical path length: {N waves minimum to complete}
|
|
|
126
157
|
File collision pairs: {N pairs that cannot run simultaneously}
|
|
127
158
|
DAG dispatch mode: merge-on-complete (agents unblock dependents immediately)
|
|
128
159
|
|
|
160
|
+
Dispatch strategy: {strategy name or "none (ID order)"}
|
|
161
|
+
|
|
129
162
|
Suggested dispatch order for /copilot:
|
|
130
163
|
1. Foundation first (shared files: models, schemas) — sequential
|
|
131
164
|
2. Launch all ready tasks simultaneously (DAG readiness, not wave number)
|
|
132
|
-
3.
|
|
165
|
+
3. Within each wave, dispatch by strategy score (highest first)
|
|
166
|
+
4. As each task completes → merge → check for newly-unblocked → dispatch immediately
|
|
133
167
|
```
|
|
134
168
|
|
|
135
169
|
---
|