* feat(handoffs): include project identity in all Next Up blocks Adds project_code and project_title to withProjectRoot() and updates all 30 Next Up headings across 18 workflow files to include [PROJECT_CODE] PROJECT_TITLE suffix for multi-project clarity. Closes #1948 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(review): add withProjectRoot tests and fix placeholder syntax (#1951) Address code review feedback: - Add 4 tests for project_code/project_title injection in withProjectRoot() - Fix inconsistent placeholder syntax in continuation-format.md canonical template (bare-brace → shell-dollar to match variant examples) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(phase): preserve zero-padded prefix in renameDecimalPhases Captures the zero-padded prefix (e.g. "06" from "06.3-slug") with (0*${baseInt}) so renamed directories keep their original format (06.2-slug) instead of stripping padding (6.2-slug). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Brandon Higgins <brandonscotthiggins@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1426,6 +1426,87 @@ describe('#2192: init plan-phase includes auto-advance config to prevent separat
|
||||
});
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// withProjectRoot: project identity injection (#1948)
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('withProjectRoot project identity', () => {
|
||||
let tmpDir;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = createTempProject();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup(tmpDir);
|
||||
});
|
||||
|
||||
test('injects project_code when config.project_code is set', () => {
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'config.json'),
|
||||
JSON.stringify({ project_code: 'CK' })
|
||||
);
|
||||
|
||||
const result = runGsdTools(['init', 'quick', 'test task'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(output.project_code, 'CK');
|
||||
});
|
||||
|
||||
test('injects project_title extracted from PROJECT.md H1', () => {
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'config.json'),
|
||||
JSON.stringify({ project_code: 'CK' })
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'PROJECT.md'),
|
||||
'# CareKit\n\nA care management platform.\n'
|
||||
);
|
||||
|
||||
const result = runGsdTools(['init', 'quick', 'test task'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(output.project_title, 'CareKit');
|
||||
});
|
||||
|
||||
test('omits project_code and project_title when project_code is not set', () => {
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'config.json'),
|
||||
JSON.stringify({})
|
||||
);
|
||||
|
||||
const result = runGsdTools(['init', 'quick', 'test task'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(output.project_code, undefined,
|
||||
'project_code should not be present when not configured');
|
||||
// project_title may or may not be present depending on PROJECT.md existence,
|
||||
// but without project_code the workflow omits the identity suffix entirely
|
||||
});
|
||||
|
||||
test('omits project_title when PROJECT.md does not exist', () => {
|
||||
fs.writeFileSync(
|
||||
path.join(tmpDir, '.planning', 'config.json'),
|
||||
JSON.stringify({ project_code: 'CK' })
|
||||
);
|
||||
// Ensure no PROJECT.md exists (createTempProject doesn't create one)
|
||||
const projectMdPath = path.join(tmpDir, '.planning', 'PROJECT.md');
|
||||
if (fs.existsSync(projectMdPath)) fs.unlinkSync(projectMdPath);
|
||||
|
||||
const result = runGsdTools(['init', 'quick', 'test task'], tmpDir, { HOME: tmpDir });
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(output.project_code, 'CK',
|
||||
'project_code should still be present');
|
||||
assert.strictEqual(output.project_title, undefined,
|
||||
'project_title should not be present when PROJECT.md is missing');
|
||||
});
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// roadmap analyze command
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user