maxsimcli 4.15.2 → 4.15.4
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/assets/CHANGELOG.md +14 -0
- package/dist/assets/hooks/maxsim-statusline.cjs +46 -7
- package/dist/assets/hooks/maxsim-statusline.cjs.map +1 -1
- package/dist/assets/templates/references/git-planning-commit.md +1 -1
- package/dist/assets/templates/references/questioning.md +1 -1
- package/dist/assets/templates/templates/codebase/structure.md +1 -1
- package/dist/assets/templates/templates/milestone-archive.md +3 -3
- package/dist/assets/templates/workflows/batch.md +2 -3
- package/dist/assets/templates/workflows/diagnose-issues.md +6 -6
- package/dist/assets/templates/workflows/discovery-phase.md +6 -7
- package/dist/assets/templates/workflows/discuss-phase.md +8 -11
- package/dist/assets/templates/workflows/execute-phase.md +5 -49
- package/dist/assets/templates/workflows/execute-plan.md +0 -6
- package/dist/assets/templates/workflows/go.md +2 -2
- package/dist/assets/templates/workflows/help.md +1 -1
- package/dist/assets/templates/workflows/init-existing.md +4 -5
- package/dist/assets/templates/workflows/init.md +20 -2
- package/dist/assets/templates/workflows/new-milestone.md +2 -7
- package/dist/assets/templates/workflows/new-project.md +4 -5
- package/dist/assets/templates/workflows/quick.md +0 -1
- package/dist/assets/templates/workflows/sdd.md +0 -2
- package/dist/assets/templates/workflows/settings.md +2 -7
- package/dist/assets/templates/workflows/verify-work.md +2 -16
- package/dist/cli.cjs +11 -56
- package/dist/cli.cjs.map +1 -1
- package/dist/core-D5zUr9cb.cjs.map +1 -1
- package/dist/install.cjs +10 -26
- package/dist/install.cjs.map +1 -1
- package/dist/mcp-server.cjs +2 -38
- package/dist/mcp-server.cjs.map +1 -1
- package/dist/skills-CjFWZIGM.cjs.map +1 -1
- package/package.json +1 -1
- package/dist/assets/templates/references/dashboard-bridge.md +0 -59
- package/dist/assets/templates/workflows/plan-phase.md +0 -501
package/dist/assets/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [4.15.3](https://github.com/maystudios/maxsimcli/compare/v4.15.2...v4.15.3) (2026-03-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **workflows:** move init CLI call into router to prevent workflow freelancing ([242e943](https://github.com/maystudios/maxsimcli/commit/242e9438968e90012c7ccc5b3180380a628c7154))
|
|
7
|
+
|
|
8
|
+
## [4.15.2](https://github.com/maystudios/maxsimcli/compare/v4.15.1...v4.15.2) (2026-03-11)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **workflows:** add missing GitHub fields to init workflow Parse JSON instructions ([539487b](https://github.com/maystudios/maxsimcli/commit/539487bb0bc59e818cab72e1e0969f9c2e69760a))
|
|
14
|
+
|
|
1
15
|
## [4.15.1](https://github.com/maystudios/maxsimcli/compare/v4.15.0...v4.15.1) (2026-03-11)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -60,7 +60,7 @@ const CLAUDE_DIR = ".claude";
|
|
|
60
60
|
//#region src/hooks/maxsim-statusline.ts
|
|
61
61
|
/**
|
|
62
62
|
* Claude Code Statusline - MAXSIM Edition
|
|
63
|
-
* Shows: [update] model | P{N} |
|
|
63
|
+
* Shows: [update] model | P{N} {BoardColumn} | {milestone}: {pct}% | dirname
|
|
64
64
|
*/
|
|
65
65
|
const CACHE_TTL_SECONDS = 60;
|
|
66
66
|
/**
|
|
@@ -112,25 +112,49 @@ try {
|
|
|
112
112
|
// gh api failed for milestones, continue with defaults
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
// Get current phase from
|
|
115
|
+
// Get current phase from open issues with 'phase' label, parse number from title
|
|
116
116
|
let phaseNumber = null;
|
|
117
|
+
let issueNumber = null;
|
|
117
118
|
try {
|
|
118
119
|
const phaseRaw = execSync(
|
|
119
|
-
'gh api "repos/' + owner + '/' + repo + '/issues?state=open&labels=phase
|
|
120
|
+
'gh api "repos/' + owner + '/' + repo + '/issues?state=open&labels=phase&per_page=1&sort=updated&direction=desc" --jq ".[0] | {number: .number, title: .title}"',
|
|
120
121
|
{ encoding: 'utf8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] }
|
|
121
122
|
).trim();
|
|
122
|
-
|
|
123
|
-
|
|
123
|
+
const phaseData = JSON.parse(phaseRaw || '{}');
|
|
124
|
+
const titleMatch = (phaseData.title || '').match(/^\\[Phase\\s+(\\S+)\\]/);
|
|
125
|
+
if (titleMatch) {
|
|
126
|
+
phaseNumber = titleMatch[1];
|
|
124
127
|
}
|
|
128
|
+
issueNumber = phaseData.number || null;
|
|
125
129
|
} catch (e) {
|
|
126
130
|
// gh api failed for phase, continue with null
|
|
127
131
|
}
|
|
128
132
|
|
|
133
|
+
// Get board column via GraphQL
|
|
134
|
+
let boardColumn = null;
|
|
135
|
+
if (issueNumber) {
|
|
136
|
+
try {
|
|
137
|
+
const gqlQuery = '{ repository(owner: "' + owner + '", name: "' + repo + '") { issue(number: ' + issueNumber + ') { projectItems(first: 5, includeArchived: false) { nodes { fieldValueByName(name: "Status") { ... on ProjectV2ItemFieldSingleSelectValue { name } } } } } } }';
|
|
138
|
+
const boardRaw = execSync(
|
|
139
|
+
'gh api graphql -f query=@-',
|
|
140
|
+
{ input: gqlQuery, encoding: 'utf8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] }
|
|
141
|
+
).trim();
|
|
142
|
+
const boardData = JSON.parse(boardRaw);
|
|
143
|
+
const nodes = boardData?.data?.repository?.issue?.projectItems?.nodes || [];
|
|
144
|
+
if (nodes.length > 0 && nodes[0]?.fieldValueByName?.name) {
|
|
145
|
+
boardColumn = nodes[0].fieldValueByName.name;
|
|
146
|
+
}
|
|
147
|
+
} catch (e) {
|
|
148
|
+
boardColumn = null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
129
152
|
// Write cache
|
|
130
153
|
const cacheData = JSON.stringify({
|
|
131
154
|
phase_number: phaseNumber,
|
|
132
155
|
milestone_title: milestoneTitle,
|
|
133
156
|
milestone_pct: milestonePct,
|
|
157
|
+
board_column: boardColumn,
|
|
134
158
|
updated: Math.floor(Date.now() / 1000),
|
|
135
159
|
});
|
|
136
160
|
|
|
@@ -138,7 +162,18 @@ try {
|
|
|
138
162
|
fs.mkdirSync(dir, { recursive: true });
|
|
139
163
|
fs.writeFileSync(${JSON.stringify(cacheFile)}, cacheData);
|
|
140
164
|
} catch (e) {
|
|
141
|
-
|
|
165
|
+
try {
|
|
166
|
+
const dir = ${JSON.stringify(cacheDir)};
|
|
167
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
168
|
+
fs.writeFileSync(${JSON.stringify(cacheFile)}, JSON.stringify({
|
|
169
|
+
phase_number: null,
|
|
170
|
+
milestone_title: null,
|
|
171
|
+
milestone_pct: 0,
|
|
172
|
+
board_column: null,
|
|
173
|
+
offline: true,
|
|
174
|
+
updated: Math.floor(Date.now() / 1000),
|
|
175
|
+
}));
|
|
176
|
+
} catch (_) {}
|
|
142
177
|
process.exit(0);
|
|
143
178
|
}
|
|
144
179
|
`;
|
|
@@ -174,8 +209,12 @@ function formatStatusline(data) {
|
|
|
174
209
|
cache = null;
|
|
175
210
|
}
|
|
176
211
|
if (cacheAge > CACHE_TTL_SECONDS) spawnBackgroundRefresh(cacheDir, cacheFile);
|
|
212
|
+
if (cache?.offline) return `${updateIndicator}${DIM}${model}${RESET}${SEP}${DIM}P? offline${RESET}${SEP}${DIM}${dirname}${RESET}`;
|
|
177
213
|
let phaseSegment = "";
|
|
178
|
-
if (cache?.phase_number)
|
|
214
|
+
if (cache?.phase_number) {
|
|
215
|
+
const column = cache.board_column ? ` ${cache.board_column}` : "";
|
|
216
|
+
phaseSegment = `${SEP}${DIM}P${cache.phase_number}${column}${RESET}`;
|
|
217
|
+
}
|
|
179
218
|
let milestoneSegment = "";
|
|
180
219
|
if (cache?.milestone_title) milestoneSegment = `${SEP}${DIM}${cache.milestone_title}: ${cache.milestone_pct}%${RESET}`;
|
|
181
220
|
return `${updateIndicator}${DIM}${model}${RESET}${phaseSegment}${milestoneSegment}${SEP}${DIM}${dirname}${RESET}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maxsim-statusline.cjs","names":["path","fs"],"sources":["../../../src/hooks/shared.ts","../../../src/hooks/maxsim-statusline.ts"],"sourcesContent":["/**\n * Shared utilities for MAXSIM hooks.\n */\n\n/**\n * Read all stdin as a string, then invoke callback with parsed JSON.\n * Used by statusline and sync-reminder hooks.\n */\nexport function readStdinJson<T>(callback: (data: T) => void): void {\n let input = '';\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (chunk: string) => (input += chunk));\n process.stdin.on('end', () => {\n try {\n const data = JSON.parse(input) as T;\n callback(data);\n } catch {\n // Silent fail -- never block hook execution\n process.exit(0);\n }\n });\n}\n\n/** The '.claude' path segment -- template marker replaced during install. */\nexport const CLAUDE_DIR = '.claude';\n","#!/usr/bin/env node\n/**\n * Claude Code Statusline - MAXSIM Edition\n * Shows: [update] model | P{N} | v{M}: {pct}% | dirname\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport { readStdinJson, CLAUDE_DIR } from './shared';\n\nexport interface StatuslineInput {\n model?: { display_name?: string };\n workspace?: { current_dir?: string; project_dir?: string };\n session_id?: string;\n}\n\nexport interface ProgressCache {\n phase_number: string | null;\n milestone_title: string | null;\n milestone_pct: number;\n updated: number;\n}\n\nconst CACHE_TTL_SECONDS = 60;\n\n/**\n * Spawn a detached Node child process to refresh the progress cache in the background.\n * The child runs gh CLI commands to detect owner/repo, find the first open milestone,\n * compute progress, and find the current phase label.\n */\nfunction spawnBackgroundRefresh(cacheDir: string, cacheFile: string): void {\n try {\n const script = `\nconst { execSync } = require('child_process');\nconst fs = require('fs');\nconst path = require('path');\n\ntry {\n // Detect owner/repo\n const nameWithOwner = execSync('gh repo view --json nameWithOwner -q .nameWithOwner', {\n encoding: 'utf8',\n timeout: 10000,\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n if (!nameWithOwner || !nameWithOwner.includes('/')) {\n process.exit(0);\n }\n\n const [owner, repo] = nameWithOwner.split('/');\n\n // Get milestones\n let milestoneTitle = null;\n let milestonePct = 0;\n try {\n const milestonesRaw = execSync(\n 'gh api repos/' + owner + '/' + repo + '/milestones --jq \".\"',\n { encoding: 'utf8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] }\n ).trim();\n if (milestonesRaw) {\n const milestones = JSON.parse(milestonesRaw);\n const openMilestone = milestones.find(function(m) { return m.state === 'open'; });\n if (openMilestone) {\n milestoneTitle = openMilestone.title || null;\n const total = (openMilestone.open_issues || 0) + (openMilestone.closed_issues || 0);\n if (total > 0) {\n milestonePct = Math.round(((openMilestone.closed_issues || 0) / total) * 100);\n }\n }\n }\n } catch (e) {\n // gh api failed for milestones, continue with defaults\n }\n\n // Get current phase from labels on open issues\n let phaseNumber = null;\n try {\n const phaseRaw = execSync(\n 'gh api \"repos/' + owner + '/' + repo + '/issues?state=open&labels=phase:&per_page=1&sort=created&direction=desc\" --jq \".[0].labels[] | select(.name | startswith(\\\\\"phase:\\\\\")) | .name\"',\n { encoding: 'utf8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] }\n ).trim();\n if (phaseRaw && phaseRaw.startsWith('phase:')) {\n phaseNumber = phaseRaw.replace('phase:', '').trim();\n }\n } catch (e) {\n // gh api failed for phase, continue with null\n }\n\n // Write cache\n const cacheData = JSON.stringify({\n phase_number: phaseNumber,\n milestone_title: milestoneTitle,\n milestone_pct: milestonePct,\n updated: Math.floor(Date.now() / 1000),\n });\n\n const dir = ${JSON.stringify(cacheDir)};\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(${JSON.stringify(cacheFile)}, cacheData);\n} catch (e) {\n // Silently degrade if gh not available\n process.exit(0);\n}\n`;\n\n const child = spawn(process.execPath, ['-e', script], {\n stdio: 'ignore',\n windowsHide: true,\n detached: true,\n });\n child.unref();\n } catch {\n // Silent fail -- never break statusline\n }\n}\n\nexport function formatStatusline(data: StatuslineInput): string {\n const model = data.model?.display_name || 'Claude';\n const dir = data.workspace?.project_dir || data.workspace?.current_dir || process.cwd();\n const dirname = path.basename(dir);\n\n const SEP = ' \\u2502 ';\n const DIM = '\\x1b[2m';\n const RESET = '\\x1b[0m';\n\n // MAXSIM update available?\n let updateIndicator = '';\n const updateCacheFile = path.join(dir, CLAUDE_DIR, 'cache', 'maxsim-update-check.json');\n if (fs.existsSync(updateCacheFile)) {\n try {\n const cache = JSON.parse(fs.readFileSync(updateCacheFile, 'utf8'));\n if (cache.update_available) {\n updateIndicator = '\\x1b[33m\\u2B06\\x1b[0m ';\n }\n } catch {\n // ignore\n }\n }\n\n // Check if this is a MAXSIM project\n const planningDir = path.join(dir, '.planning');\n const isMaxsimProject = fs.existsSync(planningDir);\n\n if (!isMaxsimProject) {\n return `${updateIndicator}${DIM}${model}${RESET}${SEP}${DIM}${dirname}${RESET}`;\n }\n\n // Read progress cache\n const cacheDir = path.join(dir, CLAUDE_DIR, 'cache');\n const cacheFile = path.join(cacheDir, 'maxsim-progress.json');\n let cache: ProgressCache | null = null;\n let cacheAge = Infinity;\n\n if (fs.existsSync(cacheFile)) {\n try {\n cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8')) as ProgressCache;\n cacheAge = Math.floor(Date.now() / 1000) - (cache.updated || 0);\n } catch {\n cache = null;\n }\n }\n\n // Spawn background refresh if cache is stale or missing\n if (cacheAge > CACHE_TTL_SECONDS) {\n spawnBackgroundRefresh(cacheDir, cacheFile);\n }\n\n // Build phase segment\n let phaseSegment = '';\n if (cache?.phase_number) {\n phaseSegment = `${SEP}${DIM}P${cache.phase_number}${RESET}`;\n }\n\n // Build milestone segment\n let milestoneSegment = '';\n if (cache?.milestone_title) {\n milestoneSegment = `${SEP}${DIM}${cache.milestone_title}: ${cache.milestone_pct}%${RESET}`;\n }\n\n return `${updateIndicator}${DIM}${model}${RESET}${phaseSegment}${milestoneSegment}${SEP}${DIM}${dirname}${RESET}`;\n}\n\n// Standalone entry\nif (require.main === module) {\n readStdinJson<StatuslineInput>((data) => {\n process.stdout.write(formatStatusline(data));\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,SAAgB,cAAiB,UAAmC;CAClE,IAAI,QAAQ;AACZ,SAAQ,MAAM,YAAY,OAAO;AACjC,SAAQ,MAAM,GAAG,SAAS,UAAmB,SAAS,MAAO;AAC7D,SAAQ,MAAM,GAAG,aAAa;AAC5B,MAAI;AAEF,YADa,KAAK,MAAM,MAAM,CAChB;UACR;AAEN,WAAQ,KAAK,EAAE;;GAEjB;;;AAIJ,MAAa,aAAa;;;;;;;;ACA1B,MAAM,oBAAoB;;;;;;AAO1B,SAAS,uBAAuB,UAAkB,WAAyB;AACzE,KAAI;EACF,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAgEH,KAAK,UAAU,SAAS,CAAC;;qBAEpB,KAAK,UAAU,UAAU,CAAC;;;;;;AAY3C,gCALoB,QAAQ,UAAU,CAAC,MAAM,OAAO,EAAE;GACpD,OAAO;GACP,aAAa;GACb,UAAU;GACX,CAAC,CACI,OAAO;SACP;;AAKV,SAAgB,iBAAiB,MAA+B;CAC9D,MAAM,QAAQ,KAAK,OAAO,gBAAgB;CAC1C,MAAM,MAAM,KAAK,WAAW,eAAe,KAAK,WAAW,eAAe,QAAQ,KAAK;CACvF,MAAM,UAAUA,UAAK,SAAS,IAAI;CAElC,MAAM,MAAM;CACZ,MAAM,MAAM;CACZ,MAAM,QAAQ;CAGd,IAAI,kBAAkB;CACtB,MAAM,kBAAkBA,UAAK,KAAK,KAAK,YAAY,SAAS,2BAA2B;AACvF,KAAIC,QAAG,WAAW,gBAAgB,CAChC,KAAI;AAEF,MADc,KAAK,MAAMA,QAAG,aAAa,iBAAiB,OAAO,CAAC,CACxD,iBACR,mBAAkB;SAEd;CAMV,MAAM,cAAcD,UAAK,KAAK,KAAK,YAAY;AAG/C,KAAI,CAFoBC,QAAG,WAAW,YAAY,CAGhD,QAAO,GAAG,kBAAkB,MAAM,QAAQ,QAAQ,MAAM,MAAM,UAAU;CAI1E,MAAM,WAAWD,UAAK,KAAK,KAAK,YAAY,QAAQ;CACpD,MAAM,YAAYA,UAAK,KAAK,UAAU,uBAAuB;CAC7D,IAAI,QAA8B;CAClC,IAAI,WAAW;AAEf,KAAIC,QAAG,WAAW,UAAU,CAC1B,KAAI;AACF,UAAQ,KAAK,MAAMA,QAAG,aAAa,WAAW,OAAO,CAAC;AACtD,aAAW,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,IAAI,MAAM,WAAW;SACvD;AACN,UAAQ;;AAKZ,KAAI,WAAW,kBACb,wBAAuB,UAAU,UAAU;CAI7C,IAAI,eAAe;AACnB,KAAI,OAAO,aACT,gBAAe,GAAG,MAAM,IAAI,GAAG,MAAM,eAAe;CAItD,IAAI,mBAAmB;AACvB,KAAI,OAAO,gBACT,oBAAmB,GAAG,MAAM,MAAM,MAAM,gBAAgB,IAAI,MAAM,cAAc,GAAG;AAGrF,QAAO,GAAG,kBAAkB,MAAM,QAAQ,QAAQ,eAAe,mBAAmB,MAAM,MAAM,UAAU;;AAI5G,IAAI,QAAQ,SAAS,OACnB,gBAAgC,SAAS;AACvC,SAAQ,OAAO,MAAM,iBAAiB,KAAK,CAAC;EAC5C"}
|
|
1
|
+
{"version":3,"file":"maxsim-statusline.cjs","names":["path","fs"],"sources":["../../../src/hooks/shared.ts","../../../src/hooks/maxsim-statusline.ts"],"sourcesContent":["/**\n * Shared utilities for MAXSIM hooks.\n */\n\n/**\n * Read all stdin as a string, then invoke callback with parsed JSON.\n * Used by statusline and sync-reminder hooks.\n */\nexport function readStdinJson<T>(callback: (data: T) => void): void {\n let input = '';\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (chunk: string) => (input += chunk));\n process.stdin.on('end', () => {\n try {\n const data = JSON.parse(input) as T;\n callback(data);\n } catch {\n // Silent fail -- never block hook execution\n process.exit(0);\n }\n });\n}\n\n/** The '.claude' path segment -- template marker replaced during install. */\nexport const CLAUDE_DIR = '.claude';\n","#!/usr/bin/env node\n/**\n * Claude Code Statusline - MAXSIM Edition\n * Shows: [update] model | P{N} {BoardColumn} | {milestone}: {pct}% | dirname\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport { readStdinJson, CLAUDE_DIR } from './shared';\n\nexport interface StatuslineInput {\n model?: { display_name?: string };\n workspace?: { current_dir?: string; project_dir?: string };\n session_id?: string;\n}\n\nexport interface ProgressCache {\n phase_number: string | null;\n milestone_title: string | null;\n milestone_pct: number;\n board_column: string | null;\n offline?: boolean;\n updated: number;\n}\n\nconst CACHE_TTL_SECONDS = 60;\n\n/**\n * Spawn a detached Node child process to refresh the progress cache in the background.\n * The child runs gh CLI commands to detect owner/repo, find the first open milestone,\n * compute progress, and find the current phase label.\n */\nfunction spawnBackgroundRefresh(cacheDir: string, cacheFile: string): void {\n try {\n const script = `\nconst { execSync } = require('child_process');\nconst fs = require('fs');\nconst path = require('path');\n\ntry {\n // Detect owner/repo\n const nameWithOwner = execSync('gh repo view --json nameWithOwner -q .nameWithOwner', {\n encoding: 'utf8',\n timeout: 10000,\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n\n if (!nameWithOwner || !nameWithOwner.includes('/')) {\n process.exit(0);\n }\n\n const [owner, repo] = nameWithOwner.split('/');\n\n // Get milestones\n let milestoneTitle = null;\n let milestonePct = 0;\n try {\n const milestonesRaw = execSync(\n 'gh api repos/' + owner + '/' + repo + '/milestones --jq \".\"',\n { encoding: 'utf8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] }\n ).trim();\n if (milestonesRaw) {\n const milestones = JSON.parse(milestonesRaw);\n const openMilestone = milestones.find(function(m) { return m.state === 'open'; });\n if (openMilestone) {\n milestoneTitle = openMilestone.title || null;\n const total = (openMilestone.open_issues || 0) + (openMilestone.closed_issues || 0);\n if (total > 0) {\n milestonePct = Math.round(((openMilestone.closed_issues || 0) / total) * 100);\n }\n }\n }\n } catch (e) {\n // gh api failed for milestones, continue with defaults\n }\n\n // Get current phase from open issues with 'phase' label, parse number from title\n let phaseNumber = null;\n let issueNumber = null;\n try {\n const phaseRaw = execSync(\n 'gh api \"repos/' + owner + '/' + repo + '/issues?state=open&labels=phase&per_page=1&sort=updated&direction=desc\" --jq \".[0] | {number: .number, title: .title}\"',\n { encoding: 'utf8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] }\n ).trim();\n const phaseData = JSON.parse(phaseRaw || '{}');\n const titleMatch = (phaseData.title || '').match(/^\\\\[Phase\\\\s+(\\\\S+)\\\\]/);\n if (titleMatch) {\n phaseNumber = titleMatch[1];\n }\n issueNumber = phaseData.number || null;\n } catch (e) {\n // gh api failed for phase, continue with null\n }\n\n // Get board column via GraphQL\n let boardColumn = null;\n if (issueNumber) {\n try {\n const gqlQuery = '{ repository(owner: \"' + owner + '\", name: \"' + repo + '\") { issue(number: ' + issueNumber + ') { projectItems(first: 5, includeArchived: false) { nodes { fieldValueByName(name: \"Status\") { ... on ProjectV2ItemFieldSingleSelectValue { name } } } } } } }';\n const boardRaw = execSync(\n 'gh api graphql -f query=@-',\n { input: gqlQuery, encoding: 'utf8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'] }\n ).trim();\n const boardData = JSON.parse(boardRaw);\n const nodes = boardData?.data?.repository?.issue?.projectItems?.nodes || [];\n if (nodes.length > 0 && nodes[0]?.fieldValueByName?.name) {\n boardColumn = nodes[0].fieldValueByName.name;\n }\n } catch (e) {\n boardColumn = null;\n }\n }\n\n // Write cache\n const cacheData = JSON.stringify({\n phase_number: phaseNumber,\n milestone_title: milestoneTitle,\n milestone_pct: milestonePct,\n board_column: boardColumn,\n updated: Math.floor(Date.now() / 1000),\n });\n\n const dir = ${JSON.stringify(cacheDir)};\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(${JSON.stringify(cacheFile)}, cacheData);\n} catch (e) {\n try {\n const dir = ${JSON.stringify(cacheDir)};\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(${JSON.stringify(cacheFile)}, JSON.stringify({\n phase_number: null,\n milestone_title: null,\n milestone_pct: 0,\n board_column: null,\n offline: true,\n updated: Math.floor(Date.now() / 1000),\n }));\n } catch (_) {}\n process.exit(0);\n}\n`;\n\n const child = spawn(process.execPath, ['-e', script], {\n stdio: 'ignore',\n windowsHide: true,\n detached: true,\n });\n child.unref();\n } catch {\n // Silent fail -- never break statusline\n }\n}\n\nexport function formatStatusline(data: StatuslineInput): string {\n const model = data.model?.display_name || 'Claude';\n const dir = data.workspace?.project_dir || data.workspace?.current_dir || process.cwd();\n const dirname = path.basename(dir);\n\n const SEP = ' \\u2502 ';\n const DIM = '\\x1b[2m';\n const RESET = '\\x1b[0m';\n\n // MAXSIM update available?\n let updateIndicator = '';\n const updateCacheFile = path.join(dir, CLAUDE_DIR, 'cache', 'maxsim-update-check.json');\n if (fs.existsSync(updateCacheFile)) {\n try {\n const cache = JSON.parse(fs.readFileSync(updateCacheFile, 'utf8'));\n if (cache.update_available) {\n updateIndicator = '\\x1b[33m\\u2B06\\x1b[0m ';\n }\n } catch {\n // ignore\n }\n }\n\n // Check if this is a MAXSIM project\n const planningDir = path.join(dir, '.planning');\n const isMaxsimProject = fs.existsSync(planningDir);\n\n if (!isMaxsimProject) {\n return `${updateIndicator}${DIM}${model}${RESET}${SEP}${DIM}${dirname}${RESET}`;\n }\n\n // Read progress cache\n const cacheDir = path.join(dir, CLAUDE_DIR, 'cache');\n const cacheFile = path.join(cacheDir, 'maxsim-progress.json');\n let cache: ProgressCache | null = null;\n let cacheAge = Infinity;\n\n if (fs.existsSync(cacheFile)) {\n try {\n cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8')) as ProgressCache;\n cacheAge = Math.floor(Date.now() / 1000) - (cache.updated || 0);\n } catch {\n cache = null;\n }\n }\n\n // Spawn background refresh if cache is stale or missing\n if (cacheAge > CACHE_TTL_SECONDS) {\n spawnBackgroundRefresh(cacheDir, cacheFile);\n }\n\n // Offline fallback\n if (cache?.offline) {\n return `${updateIndicator}${DIM}${model}${RESET}${SEP}${DIM}P? offline${RESET}${SEP}${DIM}${dirname}${RESET}`;\n }\n\n // Build phase segment: P{N} {BoardColumn}\n let phaseSegment = '';\n if (cache?.phase_number) {\n const column = cache.board_column ? ` ${cache.board_column}` : '';\n phaseSegment = `${SEP}${DIM}P${cache.phase_number}${column}${RESET}`;\n }\n\n // Build milestone segment\n let milestoneSegment = '';\n if (cache?.milestone_title) {\n milestoneSegment = `${SEP}${DIM}${cache.milestone_title}: ${cache.milestone_pct}%${RESET}`;\n }\n\n return `${updateIndicator}${DIM}${model}${RESET}${phaseSegment}${milestoneSegment}${SEP}${DIM}${dirname}${RESET}`;\n}\n\n// Standalone entry\nif (require.main === module) {\n readStdinJson<StatuslineInput>((data) => {\n process.stdout.write(formatStatusline(data));\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,SAAgB,cAAiB,UAAmC;CAClE,IAAI,QAAQ;AACZ,SAAQ,MAAM,YAAY,OAAO;AACjC,SAAQ,MAAM,GAAG,SAAS,UAAmB,SAAS,MAAO;AAC7D,SAAQ,MAAM,GAAG,aAAa;AAC5B,MAAI;AAEF,YADa,KAAK,MAAM,MAAM,CAChB;UACR;AAEN,WAAQ,KAAK,EAAE;;GAEjB;;;AAIJ,MAAa,aAAa;;;;;;;;ACE1B,MAAM,oBAAoB;;;;;;AAO1B,SAAS,uBAAuB,UAAkB,WAAyB;AACzE,KAAI;EACF,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBAwFH,KAAK,UAAU,SAAS,CAAC;;qBAEpB,KAAK,UAAU,UAAU,CAAC;;;kBAG7B,KAAK,UAAU,SAAS,CAAC;;uBAEpB,KAAK,UAAU,UAAU,CAAC;;;;;;;;;;;;AAkB7C,gCALoB,QAAQ,UAAU,CAAC,MAAM,OAAO,EAAE;GACpD,OAAO;GACP,aAAa;GACb,UAAU;GACX,CAAC,CACI,OAAO;SACP;;AAKV,SAAgB,iBAAiB,MAA+B;CAC9D,MAAM,QAAQ,KAAK,OAAO,gBAAgB;CAC1C,MAAM,MAAM,KAAK,WAAW,eAAe,KAAK,WAAW,eAAe,QAAQ,KAAK;CACvF,MAAM,UAAUA,UAAK,SAAS,IAAI;CAElC,MAAM,MAAM;CACZ,MAAM,MAAM;CACZ,MAAM,QAAQ;CAGd,IAAI,kBAAkB;CACtB,MAAM,kBAAkBA,UAAK,KAAK,KAAK,YAAY,SAAS,2BAA2B;AACvF,KAAIC,QAAG,WAAW,gBAAgB,CAChC,KAAI;AAEF,MADc,KAAK,MAAMA,QAAG,aAAa,iBAAiB,OAAO,CAAC,CACxD,iBACR,mBAAkB;SAEd;CAMV,MAAM,cAAcD,UAAK,KAAK,KAAK,YAAY;AAG/C,KAAI,CAFoBC,QAAG,WAAW,YAAY,CAGhD,QAAO,GAAG,kBAAkB,MAAM,QAAQ,QAAQ,MAAM,MAAM,UAAU;CAI1E,MAAM,WAAWD,UAAK,KAAK,KAAK,YAAY,QAAQ;CACpD,MAAM,YAAYA,UAAK,KAAK,UAAU,uBAAuB;CAC7D,IAAI,QAA8B;CAClC,IAAI,WAAW;AAEf,KAAIC,QAAG,WAAW,UAAU,CAC1B,KAAI;AACF,UAAQ,KAAK,MAAMA,QAAG,aAAa,WAAW,OAAO,CAAC;AACtD,aAAW,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,IAAI,MAAM,WAAW;SACvD;AACN,UAAQ;;AAKZ,KAAI,WAAW,kBACb,wBAAuB,UAAU,UAAU;AAI7C,KAAI,OAAO,QACT,QAAO,GAAG,kBAAkB,MAAM,QAAQ,QAAQ,MAAM,IAAI,YAAY,QAAQ,MAAM,MAAM,UAAU;CAIxG,IAAI,eAAe;AACnB,KAAI,OAAO,cAAc;EACvB,MAAM,SAAS,MAAM,eAAe,IAAI,MAAM,iBAAiB;AAC/D,iBAAe,GAAG,MAAM,IAAI,GAAG,MAAM,eAAe,SAAS;;CAI/D,IAAI,mBAAmB;AACvB,KAAI,OAAO,gBACT,oBAAmB,GAAG,MAAM,MAAM,MAAM,gBAAgB,IAAI,MAAM,cAAc,GAAG;AAGrF,QAAO,GAAG,kBAAkB,MAAM,QAAQ,QAAQ,eAAe,mBAAmB,MAAM,MAAM,UAAU;;AAI5G,IAAI,QAAQ,SAAS,OACnB,gBAAgC,SAAS;AACvC,SAAQ,OAAO,MAAM,iBAAiB,KAAK,CAAC;EAC5C"}
|
|
@@ -24,7 +24,7 @@ node ~/.claude/maxsim/bin/maxsim-tools.cjs commit "" --files .planning/codebase/
|
|
|
24
24
|
|
|
25
25
|
| Command | Scope | Example |
|
|
26
26
|
|---------|-------|---------|
|
|
27
|
-
| plan
|
|
27
|
+
| plan | phase | `docs(phase-03): create authentication plans` |
|
|
28
28
|
| execute-phase | phase | `docs(phase-03): complete authentication phase` |
|
|
29
29
|
| new-milestone | milestone | `docs: start milestone v1.1` |
|
|
30
30
|
| remove-phase | chore | `chore: remove phase 17 (dashboard)` |
|
|
@@ -19,7 +19,7 @@ By the end of questioning, you need enough clarity to write a PROJECT.md that do
|
|
|
19
19
|
- **Research** needs: what domain to research, what the user already knows, what unknowns exist
|
|
20
20
|
- **Requirements** needs: clear enough vision to scope v1 features
|
|
21
21
|
- **Roadmap** needs: clear enough vision to decompose into phases, what "done" looks like
|
|
22
|
-
- **plan
|
|
22
|
+
- **plan** needs: specific requirements to break into tasks, context for implementation choices
|
|
23
23
|
- **execute-phase** needs: success criteria to verify against, the "why" behind requirements
|
|
24
24
|
|
|
25
25
|
A vague PROJECT.md forces every downstream phase to guess. The cost compounds.
|
|
@@ -148,7 +148,7 @@ maxsim/
|
|
|
148
148
|
**commands/maxsim/**
|
|
149
149
|
- Purpose: Slash command definitions for Claude Code
|
|
150
150
|
- Contains: *.md files (one per command)
|
|
151
|
-
- Key files: new-project.md, plan
|
|
151
|
+
- Key files: new-project.md, plan.md, execute-plan.md
|
|
152
152
|
- Subdirectories: None (flat structure)
|
|
153
153
|
|
|
154
154
|
**maxsim/references/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Milestone Archive Template
|
|
2
2
|
|
|
3
|
-
This template is used by the complete-milestone workflow to create archive files in `.planning/
|
|
3
|
+
This template is used by the complete-milestone workflow to create archive files in `.planning/archive/`.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -112,8 +112,8 @@ _For current project status, see .planning/ROADMAP.md_
|
|
|
112
112
|
|
|
113
113
|
**Archive location:**
|
|
114
114
|
|
|
115
|
-
- Save to `.planning/
|
|
116
|
-
- Example: `.planning/
|
|
115
|
+
- Save to `.planning/archive/v{VERSION}-{NAME}.md`
|
|
116
|
+
- Example: `.planning/archive/v1.0-mvp.md`
|
|
117
117
|
|
|
118
118
|
**After archiving:**
|
|
119
119
|
|
|
@@ -13,7 +13,6 @@ Follows the batch-worktree skill process: Research (decompose) -> Plan (validate
|
|
|
13
13
|
|
|
14
14
|
<required_reading>
|
|
15
15
|
Read all files referenced by the invoking prompt's execution_context before starting.
|
|
16
|
-
@./references/dashboard-bridge.md
|
|
17
16
|
</required_reading>
|
|
18
17
|
|
|
19
18
|
<process>
|
|
@@ -225,7 +224,7 @@ For each unit (spawn all with `run_in_background: true` for parallel execution):
|
|
|
225
224
|
|
|
226
225
|
```
|
|
227
226
|
Task(
|
|
228
|
-
subagent_type="
|
|
227
|
+
subagent_type="executor",
|
|
229
228
|
model="{executor_model}",
|
|
230
229
|
isolation="worktree",
|
|
231
230
|
run_in_background=true,
|
|
@@ -299,7 +298,7 @@ For each failed unit:
|
|
|
299
298
|
**Attempt 1 — spawn fix agent:**
|
|
300
299
|
```
|
|
301
300
|
Task(
|
|
302
|
-
subagent_type="
|
|
301
|
+
subagent_type="executor",
|
|
303
302
|
model="{executor_model}",
|
|
304
303
|
isolation="worktree",
|
|
305
304
|
prompt="
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<purpose>
|
|
2
2
|
Orchestrate parallel debug agents to investigate UAT gaps and find root causes.
|
|
3
3
|
|
|
4
|
-
After UAT finds gaps, spawn one debug agent per gap. Each agent investigates autonomously with symptoms pre-filled from UAT. Collect root causes, update UAT.md gaps with diagnosis, then hand off to plan
|
|
4
|
+
After UAT finds gaps, spawn one debug agent per gap. Each agent investigates autonomously with symptoms pre-filled from UAT. Collect root causes, update UAT.md gaps with diagnosis, then hand off to plan --gaps with actual diagnoses.
|
|
5
5
|
|
|
6
6
|
Orchestrator stays lean: parse gaps, spawn agents, collect results, update UAT.
|
|
7
7
|
</purpose>
|
|
@@ -15,7 +15,7 @@ Debug files use the `.planning/debug/` path (hidden directory with leading dot).
|
|
|
15
15
|
<core_principle>
|
|
16
16
|
**Diagnose before planning fixes.**
|
|
17
17
|
|
|
18
|
-
UAT tells us WHAT is broken (symptoms). Debug agents find WHY (root cause). plan
|
|
18
|
+
UAT tells us WHAT is broken (symptoms). Debug agents find WHY (root cause). plan --gaps then creates targeted fixes based on actual causes, not guesses.
|
|
19
19
|
|
|
20
20
|
Without diagnosis: "Comment doesn't refresh" → guess at fix → maybe wrong
|
|
21
21
|
With diagnosis: "Comment doesn't refresh" → "useEffect missing dependency" → precise fix
|
|
@@ -94,7 +94,7 @@ Template placeholders:
|
|
|
94
94
|
- `{errors}`: Any error messages from UAT (or "None reported")
|
|
95
95
|
- `{reproduction}`: "Test {test_num} in UAT"
|
|
96
96
|
- `{timeline}`: "Discovered during UAT"
|
|
97
|
-
- `{goal}`: `find_root_cause_only` (UAT flow - plan
|
|
97
|
+
- `{goal}`: `find_root_cause_only` (UAT flow - plan --gaps handles fixes)
|
|
98
98
|
- `{slug}`: Generated from truth
|
|
99
99
|
</step>
|
|
100
100
|
|
|
@@ -118,7 +118,7 @@ Each agent returns with:
|
|
|
118
118
|
- {file1}: {what's wrong}
|
|
119
119
|
- {file2}: {related issue}
|
|
120
120
|
|
|
121
|
-
**Suggested Fix Direction:** {brief hint for plan
|
|
121
|
+
**Suggested Fix Direction:** {brief hint for plan --gaps}
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
Parse each return to extract:
|
|
@@ -190,7 +190,7 @@ Do NOT offer manual next steps - verify-work handles the rest.
|
|
|
190
190
|
|
|
191
191
|
<context_efficiency>
|
|
192
192
|
Agents start with symptoms pre-filled from UAT (no symptom gathering).
|
|
193
|
-
Agents only diagnose—plan
|
|
193
|
+
Agents only diagnose—plan --gaps handles fixes (no fix application).
|
|
194
194
|
</context_efficiency>
|
|
195
195
|
|
|
196
196
|
<failure_handling>
|
|
@@ -206,7 +206,7 @@ Agents only diagnose—plan-phase --gaps handles fixes (no fix application).
|
|
|
206
206
|
**All agents fail:**
|
|
207
207
|
- Something systemic (permissions, git, etc.)
|
|
208
208
|
- Report for manual investigation
|
|
209
|
-
- Fall back to plan
|
|
209
|
+
- Fall back to plan --gaps without root causes (less precise)
|
|
210
210
|
</failure_handling>
|
|
211
211
|
|
|
212
212
|
<success_criteria>
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
Execute discovery at the appropriate depth level.
|
|
3
3
|
Produces DISCOVERY.md (for Level 2-3) that informs PLAN.md creation.
|
|
4
4
|
|
|
5
|
-
Called from plan-
|
|
5
|
+
Called from plan-create.md's mandatory_discovery step with a depth parameter.
|
|
6
6
|
|
|
7
7
|
NOTE: For comprehensive ecosystem research ("how do experts build this"), use /maxsim:plan --research instead, which produces RESEARCH.md.
|
|
8
8
|
</purpose>
|
|
9
9
|
|
|
10
10
|
<required_reading>
|
|
11
|
-
@./references/dashboard-bridge.md
|
|
12
11
|
</required_reading>
|
|
13
12
|
|
|
14
13
|
<depth_levels>
|
|
@@ -20,7 +19,7 @@ NOTE: For comprehensive ecosystem research ("how do experts build this"), use /m
|
|
|
20
19
|
| 2 | Standard | 15-30 min | DISCOVERY.md | Choosing between options, new integration |
|
|
21
20
|
| 3 | Deep Dive | 1+ hour | Detailed DISCOVERY.md with validation gates | Architectural decisions, novel problems |
|
|
22
21
|
|
|
23
|
-
**Depth is determined by plan-
|
|
22
|
+
**Depth is determined by plan-create.md before routing here.**
|
|
24
23
|
</depth_levels>
|
|
25
24
|
|
|
26
25
|
<source_hierarchy>
|
|
@@ -38,7 +37,7 @@ See ~/.claude/maxsim/templates/discovery.md `<discovery_protocol>` for full prot
|
|
|
38
37
|
<process>
|
|
39
38
|
|
|
40
39
|
<step name="determine_depth">
|
|
41
|
-
Check the depth parameter passed from plan-
|
|
40
|
+
Check the depth parameter passed from plan-create.md:
|
|
42
41
|
- `depth=verify` → Level 1 (Quick Verification)
|
|
43
42
|
- `depth=standard` → Level 2 (Standard Discovery)
|
|
44
43
|
- `depth=deep` → Level 3 (Deep Dive)
|
|
@@ -73,7 +72,7 @@ For: Single known library, confirming syntax/version still correct.
|
|
|
73
72
|
- API syntax unchanged
|
|
74
73
|
- No breaking changes in recent versions
|
|
75
74
|
|
|
76
|
-
4. **If verified:** Return to plan-
|
|
75
|
+
4. **If verified:** Return to plan-create.md with confirmation. No DISCOVERY.md needed.
|
|
77
76
|
|
|
78
77
|
5. **If concerns found:** Escalate to Level 2.
|
|
79
78
|
|
|
@@ -118,7 +117,7 @@ For: Choosing between options, new external integration.
|
|
|
118
117
|
- Code examples from Context7
|
|
119
118
|
- Confidence level (should be MEDIUM-HIGH for Level 2)
|
|
120
119
|
|
|
121
|
-
7. Return to plan-
|
|
120
|
+
7. Return to plan-create.md.
|
|
122
121
|
|
|
123
122
|
**Output:** `.planning/phases/XX-name/DISCOVERY.md`
|
|
124
123
|
</step>
|
|
@@ -171,7 +170,7 @@ For: Architectural decisions, novel problems, high-risk choices.
|
|
|
171
170
|
|
|
172
171
|
7. **Confidence gate:** If overall confidence is LOW, present options before proceeding.
|
|
173
172
|
|
|
174
|
-
8. Return to plan-
|
|
173
|
+
8. Return to plan-create.md.
|
|
175
174
|
|
|
176
175
|
**Output:** `.planning/phases/XX-name/DISCOVERY.md` (comprehensive)
|
|
177
176
|
</step>
|
|
@@ -11,7 +11,6 @@ You are a thinking partner, not an interviewer. The user is the visionary — yo
|
|
|
11
11
|
</purpose>
|
|
12
12
|
|
|
13
13
|
<required_reading>
|
|
14
|
-
@./references/dashboard-bridge.md
|
|
15
14
|
@./references/thinking-partner.md
|
|
16
15
|
</required_reading>
|
|
17
16
|
|
|
@@ -27,13 +26,11 @@ Every question directed at the user MUST use a structured tool. NEVER write a qu
|
|
|
27
26
|
- Any clarification or follow-up question
|
|
28
27
|
- Existing context handling (update/view/skip)
|
|
29
28
|
|
|
30
|
-
**Tool selection:**
|
|
31
|
-
- **DASHBOARD_ACTIVE = true** → use `mcp__maxsim-dashboard__ask_question` (questions appear in browser). Follow the schema translation rules from @dashboard-bridge.
|
|
32
|
-
- **DASHBOARD_ACTIVE = false** → use `AskUserQuestion` (questions appear in terminal).
|
|
29
|
+
**Tool selection:** Use `AskUserQuestion` (questions appear in terminal).
|
|
33
30
|
|
|
34
31
|
**Why:** Plain-text questions create a worse UX — the user has to type free-form answers instead of selecting from well-designed options. Structured choices are the entire point of the discuss workflow.
|
|
35
32
|
|
|
36
|
-
**The rule is simple:** If you need input from the user → use
|
|
33
|
+
**The rule is simple:** If you need input from the user → use `AskUserQuestion`. Zero exceptions.
|
|
37
34
|
</tool_mandate>
|
|
38
35
|
|
|
39
36
|
<downstream_awareness>
|
|
@@ -603,19 +600,19 @@ Display banner:
|
|
|
603
600
|
MAXSIM ► AUTO-ADVANCING TO PLAN
|
|
604
601
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
605
602
|
|
|
606
|
-
Context captured. Spawning plan
|
|
603
|
+
Context captured. Spawning plan...
|
|
607
604
|
```
|
|
608
605
|
|
|
609
|
-
Spawn plan
|
|
606
|
+
Spawn plan as Task with direct workflow file reference (do NOT use Skill tool — Skills don't resolve inside Task subagents):
|
|
610
607
|
```
|
|
611
608
|
Task(
|
|
612
609
|
prompt="
|
|
613
610
|
<objective>
|
|
614
|
-
You are the plan
|
|
611
|
+
You are the plan orchestrator. Create executable plans for Phase ${PHASE}: ${PHASE_NAME}, then auto-advance to execution.
|
|
615
612
|
</objective>
|
|
616
613
|
|
|
617
614
|
<execution_context>
|
|
618
|
-
@./workflows/plan
|
|
615
|
+
@./workflows/plan.md
|
|
619
616
|
@./references/ui-brand.md
|
|
620
617
|
@./references/model-profile-resolution.md
|
|
621
618
|
</execution_context>
|
|
@@ -626,7 +623,7 @@ Task(
|
|
|
626
623
|
</arguments>
|
|
627
624
|
|
|
628
625
|
<instructions>
|
|
629
|
-
1. Read plan
|
|
626
|
+
1. Read plan.md from execution_context for your complete workflow
|
|
630
627
|
2. Follow ALL steps: initialize, validate, load context, research, plan, verify, auto-advance
|
|
631
628
|
3. When spawning agents (researcher, planner), use Task with specified subagent_type and model
|
|
632
629
|
4. For step 14 (auto-advance to execute): spawn execute-phase as a Task with DIRECT file reference — tell it to read execute-phase.md. Include @file refs to execute-phase.md, checkpoints.md, tdd.md, model-profile-resolution.md. Pass --no-transition flag so execute-phase returns results instead of chaining further.
|
|
@@ -639,7 +636,7 @@ Task(
|
|
|
639
636
|
)
|
|
640
637
|
```
|
|
641
638
|
|
|
642
|
-
**Handle plan
|
|
639
|
+
**Handle plan return:**
|
|
643
640
|
- **PHASE COMPLETE** → Full chain succeeded. Display:
|
|
644
641
|
```
|
|
645
642
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -24,8 +24,6 @@ Orchestrator coordinates, not executes. Each subagent loads the full execute-pla
|
|
|
24
24
|
|
|
25
25
|
<required_reading>
|
|
26
26
|
Read STATE.md before any operation to load project context.
|
|
27
|
-
|
|
28
|
-
@./references/dashboard-bridge.md
|
|
29
27
|
</required_reading>
|
|
30
28
|
|
|
31
29
|
<process>
|
|
@@ -53,19 +51,6 @@ REVIEW_CONFIG (from init JSON review_config — spec_review, code_review, simpli
|
|
|
53
51
|
When `parallelization` is false, plans within a wave execute sequentially.
|
|
54
52
|
</step>
|
|
55
53
|
|
|
56
|
-
<step name="probe_dashboard">
|
|
57
|
-
Probe for MCP dashboard availability (see @dashboard-bridge). If `DASHBOARD_ACTIVE`, emit:
|
|
58
|
-
```
|
|
59
|
-
mcp__maxsim-dashboard__submit_lifecycle_event(
|
|
60
|
-
event_type: "phase-started",
|
|
61
|
-
phase_name: PHASE_NAME,
|
|
62
|
-
phase_number: PHASE_NUMBER
|
|
63
|
-
)
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
**Note:** The dashboard is NOT auto-launched. Users start it explicitly via `maxsim dashboard`. This step only checks if a running dashboard is reachable via MCP.
|
|
67
|
-
</step>
|
|
68
|
-
|
|
69
54
|
<step name="handle_branching">
|
|
70
55
|
Check `branching_strategy` from init:
|
|
71
56
|
|
|
@@ -338,16 +323,7 @@ For each wave:
|
|
|
338
323
|
- Bad: "Executing terrain generation plan"
|
|
339
324
|
- Good: "Procedural terrain generator using Perlin noise — creates height maps, biome zones, and collision meshes. Required before vehicle physics can interact with ground."
|
|
340
325
|
|
|
341
|
-
2. **
|
|
342
|
-
```
|
|
343
|
-
mcp__maxsim-dashboard__submit_lifecycle_event(
|
|
344
|
-
event_type: "plan-started",
|
|
345
|
-
phase_name: PHASE_NAME, phase_number: PHASE_NUMBER,
|
|
346
|
-
step: plan_index, total_steps: total_plans
|
|
347
|
-
)
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
3. **Spawn executor agents:**
|
|
326
|
+
2. **Spawn executor agents:**
|
|
351
327
|
|
|
352
328
|
Pass plan content from GitHub and GitHub context — executors do NOT need to read local PLAN.md files.
|
|
353
329
|
This keeps orchestrator context lean (~10-15%).
|
|
@@ -421,16 +397,7 @@ For each wave:
|
|
|
421
397
|
|
|
422
398
|
Review stages to check: `Spec:` and `Code:` lines in `## Review Cycle`. Both must be PASS or SKIPPED for the plan to be considered review-complete.
|
|
423
399
|
|
|
424
|
-
If pass —
|
|
425
|
-
```
|
|
426
|
-
mcp__maxsim-dashboard__submit_lifecycle_event(
|
|
427
|
-
event_type: "plan-complete",
|
|
428
|
-
phase_name: PHASE_NAME, phase_number: PHASE_NUMBER,
|
|
429
|
-
step: plan_index, total_steps: total_plans
|
|
430
|
-
)
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
Then report:
|
|
400
|
+
If pass — report:
|
|
434
401
|
```
|
|
435
402
|
---
|
|
436
403
|
## Wave {N} Complete
|
|
@@ -725,14 +692,6 @@ mcp_post_comment(
|
|
|
725
692
|
)
|
|
726
693
|
```
|
|
727
694
|
|
|
728
|
-
**Emit phase-complete lifecycle event** (if `DASHBOARD_ACTIVE`):
|
|
729
|
-
```
|
|
730
|
-
mcp__maxsim-dashboard__submit_lifecycle_event(
|
|
731
|
-
event_type: "phase-complete",
|
|
732
|
-
phase_name: PHASE_NAME,
|
|
733
|
-
phase_number: PHASE_NUMBER
|
|
734
|
-
)
|
|
735
|
-
```
|
|
736
695
|
</step>
|
|
737
696
|
|
|
738
697
|
<step name="offer_next">
|
|
@@ -745,8 +704,7 @@ Parse `--no-transition` flag from $ARGUMENTS.
|
|
|
745
704
|
|
|
746
705
|
**If `--no-transition` flag present:**
|
|
747
706
|
|
|
748
|
-
Execute-phase was spawned by plan
|
|
749
|
-
After verification passes and roadmap is updated, return completion status to parent:
|
|
707
|
+
Execute-phase was spawned by plan's auto-advance. After verification passes and roadmap is updated, return completion status to parent:
|
|
750
708
|
|
|
751
709
|
```
|
|
752
710
|
## PHASE COMPLETE
|
|
@@ -780,13 +738,11 @@ STOP. Do not proceed to auto-advance or transition.
|
|
|
780
738
|
╚══════════════════════════════════════════╝
|
|
781
739
|
```
|
|
782
740
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
Read and follow `~/.claude/maxsim/workflows/transition.md`, passing through the `--auto` flag so it propagates to the next phase invocation.
|
|
741
|
+
Phase advancement is complete. The user may run `/maxsim:go` or `/maxsim:execute` to continue to the next phase.
|
|
786
742
|
|
|
787
743
|
**If neither `--auto` nor `AUTO_CFG` is true:**
|
|
788
744
|
|
|
789
|
-
The workflow ends. The user runs `/maxsim:
|
|
745
|
+
The workflow ends. The user runs `/maxsim:go` or `/maxsim:execute` to advance to the next phase.
|
|
790
746
|
</step>
|
|
791
747
|
|
|
792
748
|
</process>
|
|
@@ -7,7 +7,6 @@ Read STATE.md before any operation to load project context.
|
|
|
7
7
|
Read config.json for planning behavior settings.
|
|
8
8
|
|
|
9
9
|
@./references/git-integration.md
|
|
10
|
-
@./references/dashboard-bridge.md
|
|
11
10
|
</required_reading>
|
|
12
11
|
|
|
13
12
|
## MCP Server Fallback
|
|
@@ -363,11 +362,6 @@ Display: `CHECKPOINT: [Type]` box → Progress {X}/{Y} → Task name → type-sp
|
|
|
363
362
|
| decision (9%) | Decision needed + context + options with pros/cons | "Select: option-id" |
|
|
364
363
|
| human-action (1%) | What was automated + ONE manual step + verification plan | "done" |
|
|
365
364
|
|
|
366
|
-
**Dashboard mode:** If `DASHBOARD_ACTIVE` (see @dashboard-bridge), present checkpoint content via `mcp__maxsim-dashboard__ask_question` instead of plain text:
|
|
367
|
-
- human-verify: `options: [{value: "approved", label: "Approved"}, {value: "issues", label: "Report issues"}]`, `allow_free_text: true`
|
|
368
|
-
- decision: one option per decision choice
|
|
369
|
-
- human-action: `options: [{value: "done", label: "Done"}]`, `allow_free_text: true`
|
|
370
|
-
|
|
371
365
|
After response: verify if specified. Pass → continue. Fail → inform, wait. WAIT for user — do NOT hallucinate completion.
|
|
372
366
|
|
|
373
367
|
See ~/.claude/maxsim/references/checkpoints.md for details.
|
|
@@ -166,7 +166,7 @@ Rule 5: Phase "To Do" on GitHub board (not yet started)?
|
|
|
166
166
|
|
|
167
167
|
Rule 6: Current phase "In Review" on GitHub board?
|
|
168
168
|
-> Check: mcp_get_all_progress returns a phase with status="In Review"
|
|
169
|
-
-> Action: /maxsim:
|
|
169
|
+
-> Action: /maxsim:execute {N}
|
|
170
170
|
-> Reasoning: "Phase {N} ({name}) is awaiting verification."
|
|
171
171
|
|
|
172
172
|
Rule 7: All phases "Done" on GitHub board?
|
|
@@ -245,7 +245,7 @@ Wait for user selection, then dispatch the chosen command.
|
|
|
245
245
|
- Always surface problems BEFORE suggesting actions
|
|
246
246
|
- All problems block — no severity tiers, no "warnings"
|
|
247
247
|
- No arguments accepted — this is pure auto-detection
|
|
248
|
-
- No mention of old commands (plan
|
|
248
|
+
- No mention of old commands (plan, execute-phase, etc.)
|
|
249
249
|
- Keep initial feedback fast — show "Analyzing..." before heavy operations
|
|
250
250
|
- Primary source for phase state: live GitHub (mcp_get_all_progress, mcp_detect_interrupted)
|
|
251
251
|
- Local reads: STATE.md for blockers/decisions, ROADMAP.md for phase ordering only
|
|
@@ -106,7 +106,7 @@ Systematic debugging with persistent state across context resets.
|
|
|
106
106
|
|
|
107
107
|
- Scientific method: gather symptoms, hypothesize, test, verify
|
|
108
108
|
- Persistent debug sessions in `.planning/debug/` -- survives `/clear`
|
|
109
|
-
- Spawns isolated
|
|
109
|
+
- Spawns isolated verifier agent (fresh 200K context per investigation)
|
|
110
110
|
- Run with no args to resume an active session
|
|
111
111
|
|
|
112
112
|
Usage: `/maxsim:debug login form returns 500` or `/maxsim:debug` (resume)
|
|
@@ -6,15 +6,10 @@ Output: `.planning/` directory with config.json, PROJECT.md, REQUIREMENTS.md, RO
|
|
|
6
6
|
|
|
7
7
|
<required_reading>
|
|
8
8
|
Read all files referenced by the invoking prompt's execution_context before starting.
|
|
9
|
-
@./references/dashboard-bridge.md
|
|
10
9
|
@./references/thinking-partner.md
|
|
11
10
|
@./references/questioning.md
|
|
12
11
|
</required_reading>
|
|
13
12
|
|
|
14
|
-
<tool_mandate>
|
|
15
|
-
**Question routing:** At workflow start, probe for the dashboard (see @dashboard-bridge). If `DASHBOARD_ACTIVE = true`, route ALL `AskUserQuestion` calls through `mcp__maxsim-dashboard__ask_question` using the schema translation rules from @dashboard-bridge. If `DASHBOARD_ACTIVE = false`, use `AskUserQuestion` as normal.
|
|
16
|
-
</tool_mandate>
|
|
17
|
-
|
|
18
13
|
<auto_mode>
|
|
19
14
|
## Auto Mode Detection
|
|
20
15
|
|
|
@@ -39,6 +34,10 @@ Check if `--auto` flag is present in $ARGUMENTS.
|
|
|
39
34
|
|
|
40
35
|
**MANDATORY FIRST STEP — Execute these checks before ANY user interaction:**
|
|
41
36
|
|
|
37
|
+
**If `INIT_CONTEXT` was already loaded by the router** (the init.md workflow runs this before delegating), use that JSON directly — do NOT re-run the CLI command.
|
|
38
|
+
|
|
39
|
+
**Otherwise**, run:
|
|
40
|
+
|
|
42
41
|
```bash
|
|
43
42
|
INIT=$(node ~/.claude/maxsim/bin/maxsim-tools.cjs init init-existing)
|
|
44
43
|
```
|
|
@@ -72,7 +72,16 @@ Display:
|
|
|
72
72
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
**CRITICAL — Run init context BEFORE delegating:**
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
INIT_CONTEXT=$(node ~/.claude/maxsim/bin/maxsim-tools.cjs init new-project)
|
|
79
|
+
echo "$INIT_CONTEXT"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Save this JSON output — the sub-workflow will use it as `INIT_CONTEXT` and skip its own init call.
|
|
83
|
+
|
|
84
|
+
Now delegate to @./workflows/new-project.md — execute the full new-project workflow end-to-end. The `INIT_CONTEXT` JSON is already loaded; the sub-workflow will detect this and skip Step 1's CLI call.
|
|
76
85
|
|
|
77
86
|
Pass through:
|
|
78
87
|
- `--auto` flag if set
|
|
@@ -96,7 +105,16 @@ Display:
|
|
|
96
105
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
97
106
|
```
|
|
98
107
|
|
|
99
|
-
|
|
108
|
+
**CRITICAL — Run init context BEFORE delegating:**
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
INIT_CONTEXT=$(node ~/.claude/maxsim/bin/maxsim-tools.cjs init init-existing)
|
|
112
|
+
echo "$INIT_CONTEXT"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Save this JSON output — the sub-workflow will use it as `INIT_CONTEXT` and skip its own init call.
|
|
116
|
+
|
|
117
|
+
Now delegate to @./workflows/init-existing.md — execute the full init-existing workflow end-to-end. The `INIT_CONTEXT` JSON is already loaded; the sub-workflow will detect this and skip Step 1's CLI call.
|
|
100
118
|
|
|
101
119
|
Pass through:
|
|
102
120
|
- `--auto` flag if set
|