Compare commits
15 Commits
515bb1b1e6
...
6c6096e01b
| Author | SHA1 | Date |
|---|---|---|
|
|
6c6096e01b | |
|
|
f3f606a9ce | |
|
|
9636e86b75 | |
|
|
88aa53506a | |
|
|
653c3ae152 | |
|
|
39359ddbcd | |
|
|
f036c21d13 | |
|
|
cc300b3940 | |
|
|
6de6f45086 | |
|
|
5c0dfd85ad | |
|
|
7422d3a0a3 | |
|
|
d2e7158c72 | |
|
|
ac04378a1a | |
|
|
fe2cbe9a78 | |
|
|
1cdc7f4a48 |
|
|
@ -60,6 +60,13 @@ reviews:
|
|||
- "!**/validation-report-*.md"
|
||||
- "!CHANGELOG.md"
|
||||
path_instructions:
|
||||
- path: "src/**"
|
||||
instructions: |
|
||||
Source file changed. Check whether documentation under docs/ needs
|
||||
a corresponding update — new features, changed behavior, renamed
|
||||
concepts, altered CLI flags, or modified configuration options should
|
||||
all be reflected in the relevant doc pages. Flag missing or outdated
|
||||
docs as a review comment.
|
||||
- path: "src/**/skills/**"
|
||||
instructions: |
|
||||
Skill file. Apply the full rule catalog defined in tools/skill-validator.md.
|
||||
|
|
|
|||
|
|
@ -10,8 +10,57 @@
|
|||
|
||||
## INSTRUCTIONS
|
||||
|
||||
1. Change `{spec_file}` status to `done` in the frontmatter.
|
||||
2. If version control is available and the tree is dirty, create a local commit with a conventional message derived from the spec title.
|
||||
3. Display summary of your work to the user, including the commit hash if one was created. Advise on how to review the changes. Offer to push and/or create a pull request.
|
||||
### Generate Suggested Review Order
|
||||
|
||||
Determine what changed:
|
||||
|
||||
- **Plan-code-review:** Read `{baseline_commit}` from `{spec_file}` frontmatter and construct the diff of all changes since that commit.
|
||||
- **One-shot:** No baseline exists. Use the files you created or modified during implementation.
|
||||
|
||||
**Plan-code-review:** Append the review order as a `## Suggested Review Order` section to `{spec_file}` **after the last existing section**. Do not modify the Code Map.
|
||||
|
||||
**One-shot:** Display the review order directly in conversation output.
|
||||
|
||||
Build the trail as an ordered sequence of **stops** — clickable `path:line` references with brief framing — optimized for a human reviewer reading top-down to understand the change:
|
||||
|
||||
1. **Order by concern, not by file.** Group stops by the conceptual concern they address (e.g., "validation logic", "schema change", "UI binding"). A single file may appear under multiple concerns.
|
||||
2. **Lead with the entry point** — the single highest-leverage file:line a reviewer should look at first to grasp the design intent.
|
||||
3. **Inside each concern**, order stops from most important / architecturally interesting to supporting. Lightly bias toward higher-risk or boundary-crossing stops.
|
||||
4. **End with peripherals** — tests, config, types, and other supporting changes come last.
|
||||
5. **Every code reference is a clickable workspace-relative link.** Format each stop as a markdown link: `[short-name:line](/project-root-relative/path/to/file.ts#L42)`. The link target uses a leading `/` (workspace root) with a `#L` line anchor. Use the file's basename (or shortest unambiguous suffix) plus line number as the link text.
|
||||
6. **Each stop gets one ultra-concise line of framing** (≤15 words) — why this approach was chosen here and what it achieves in the context of the change. No paragraphs.
|
||||
|
||||
Format each stop as framing first, link on the next indented line:
|
||||
|
||||
```markdown
|
||||
## Suggested Review Order
|
||||
|
||||
**{Concern name}**
|
||||
|
||||
- {one-line framing}
|
||||
[`file.ts:42`](/src/path/to/file.ts#L42)
|
||||
|
||||
- {one-line framing}
|
||||
[`other.ts:17`](/src/path/to/other.ts#L17)
|
||||
|
||||
**{Next concern}**
|
||||
|
||||
- {one-line framing}
|
||||
[`file.ts:88`](/src/path/to/file.ts#L88)
|
||||
```
|
||||
|
||||
When there is only one concern, omit the bold label — just list the stops directly.
|
||||
|
||||
### Commit and Present
|
||||
|
||||
1. **Plan-code-review:** Change `{spec_file}` status to `done` in the frontmatter.
|
||||
2. If version control is available and the tree is dirty, create a local commit with a conventional message derived from the spec title (plan-code-review) or the intent (one-shot).
|
||||
3. **Plan-code-review only:** Open the spec in the user's editor so they can click through the Suggested Review Order:
|
||||
- Run `code -r "{spec_file}"` to open the spec in the current VS Code window (reuses the window where the project or worktree is open). Always double-quote the path to handle spaces and special characters.
|
||||
- If `code` is not available (command fails), skip gracefully and tell the user the spec file path instead.
|
||||
4. Display summary of your work to the user, including the commit hash if one was created. Include:
|
||||
- **Plan-code-review:** A note that the spec is open in their editor (or the file path if it couldn't be opened). Mention that `{spec_file}` now contains a Suggested Review Order.
|
||||
- **Navigation tip:** "Ctrl+click (Cmd+click on macOS) the links in the Suggested Review Order to jump to each stop."
|
||||
- Offer to push and/or create a pull request.
|
||||
|
||||
Workflow complete.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,15 @@ class UI {
|
|||
}
|
||||
confirmedDirectory = expandedDir;
|
||||
await prompts.log.info(`Using directory from command-line: ${confirmedDirectory}`);
|
||||
} else if (options.yes) {
|
||||
// Default to current directory when --yes flag is set
|
||||
const cwd = process.cwd();
|
||||
const validation = this.validateDirectorySync(cwd);
|
||||
if (validation) {
|
||||
throw new Error(`Invalid current directory: ${validation}`);
|
||||
}
|
||||
confirmedDirectory = cwd;
|
||||
await prompts.log.info(`Using current directory (--yes flag): ${confirmedDirectory}`);
|
||||
} else {
|
||||
confirmedDirectory = await this.getConfirmedDirectory();
|
||||
}
|
||||
|
|
@ -842,6 +851,45 @@ class UI {
|
|||
return { existingInstall, installedModuleIds, bmadDir };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default core config values by reading from src/core/module.yaml
|
||||
* @returns {Object} Default core config with user_name, communication_language, document_output_language, output_folder
|
||||
*/
|
||||
getDefaultCoreConfig() {
|
||||
const { getModulePath } = require('./project-root');
|
||||
const yaml = require('yaml');
|
||||
|
||||
let safeUsername;
|
||||
try {
|
||||
safeUsername = os.userInfo().username;
|
||||
} catch {
|
||||
safeUsername = process.env.USER || process.env.USERNAME || 'User';
|
||||
}
|
||||
const osUsername = safeUsername.charAt(0).toUpperCase() + safeUsername.slice(1);
|
||||
|
||||
const norm = (value, fallback) => (typeof value === 'string' && value.trim() !== '' ? value.trim() : fallback);
|
||||
|
||||
// Read defaults from core module.yaml (single source of truth)
|
||||
try {
|
||||
const moduleYamlPath = path.join(getModulePath('core'), 'module.yaml');
|
||||
const moduleConfig = yaml.parse(fs.readFileSync(moduleYamlPath, 'utf8'));
|
||||
return {
|
||||
user_name: norm(moduleConfig.user_name?.default, osUsername),
|
||||
communication_language: norm(moduleConfig.communication_language?.default, 'English'),
|
||||
document_output_language: norm(moduleConfig.document_output_language?.default, 'English'),
|
||||
output_folder: norm(moduleConfig.output_folder?.default, '_bmad-output'),
|
||||
};
|
||||
} catch (error) {
|
||||
console.warn(`Failed to load module.yaml, falling back to defaults: ${error.message}`);
|
||||
return {
|
||||
user_name: osUsername,
|
||||
communication_language: 'English',
|
||||
document_output_language: 'English',
|
||||
output_folder: '_bmad-output',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect core configuration
|
||||
* @param {string} directory - Installation directory
|
||||
|
|
@ -885,27 +933,33 @@ class UI {
|
|||
(!options.userName || !options.communicationLanguage || !options.documentOutputLanguage || !options.outputFolder)
|
||||
) {
|
||||
await configCollector.collectModuleConfig('core', directory, false, true);
|
||||
} else if (options.yes) {
|
||||
// Fill in defaults for any fields not provided via command-line or existing config
|
||||
const isMissingOrUnresolved = (v) => v == null || (typeof v === 'string' && (v.trim() === '' || /^\{[^}]+\}$/.test(v.trim())));
|
||||
|
||||
const defaults = this.getDefaultCoreConfig();
|
||||
for (const [key, value] of Object.entries(defaults)) {
|
||||
if (isMissingOrUnresolved(configCollector.collectedConfig.core[key])) {
|
||||
configCollector.collectedConfig.core[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (options.yes) {
|
||||
// Use all defaults when --yes flag is set
|
||||
// Use all defaults when --yes flag is set, merging with any existing config
|
||||
await configCollector.loadExistingConfig(directory);
|
||||
const existingConfig = configCollector.collectedConfig.core || {};
|
||||
const defaults = this.getDefaultCoreConfig();
|
||||
configCollector.collectedConfig.core = { ...defaults, ...existingConfig };
|
||||
|
||||
// If no existing config, use defaults
|
||||
if (Object.keys(existingConfig).length === 0) {
|
||||
let safeUsername;
|
||||
try {
|
||||
safeUsername = os.userInfo().username;
|
||||
} catch {
|
||||
safeUsername = process.env.USER || process.env.USERNAME || 'User';
|
||||
// Clean up any unresolved placeholder tokens from existing config
|
||||
const isMissingOrUnresolved = (v) => v == null || (typeof v === 'string' && (v.trim() === '' || /^\{[^}]+\}$/.test(v.trim())));
|
||||
for (const [key, value] of Object.entries(configCollector.collectedConfig.core)) {
|
||||
if (isMissingOrUnresolved(value)) {
|
||||
configCollector.collectedConfig.core[key] = defaults[key];
|
||||
}
|
||||
const defaultUsername = safeUsername.charAt(0).toUpperCase() + safeUsername.slice(1);
|
||||
configCollector.collectedConfig.core = {
|
||||
user_name: defaultUsername,
|
||||
communication_language: 'English',
|
||||
document_output_language: 'English',
|
||||
output_folder: '_bmad-output',
|
||||
};
|
||||
}
|
||||
|
||||
if (Object.keys(existingConfig).length === 0) {
|
||||
await prompts.log.info('Using default configuration (--yes flag)');
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue