Skip to content

Commit 92b4546

Browse files
authored
fix: use change-id as fallback title instead of "Untitled Change" (#236)
* fix: use change-id as fallback title instead of "Untitled Change" Fixes #225 by addressing mismatch between proposal template and title extraction: - Updated proposal template to include `# Change: [description]` header - Changed extractTitle fallback from "Untitled Change" to change-id - Updated all extractTitle call sites to pass changeName parameter This ensures both new and existing proposals display meaningful titles. * refactor: make title extraction case-insensitive for "Change:" Makes the extractTitle regex case-insensitive to handle variations like "# change:" or "# CHANGE:" in addition to "# Change:".
1 parent 5ab438f commit 92b4546

File tree

2 files changed

+13
-11
lines changed

2 files changed

+13
-11
lines changed

src/commands/change.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class ChangeCommand {
2828
*/
2929
async show(changeName?: string, options?: { json?: boolean; requirementsOnly?: boolean; deltasOnly?: boolean; noInteractive?: boolean }): Promise<void> {
3030
const changesPath = path.join(process.cwd(), 'openspec', 'changes');
31-
31+
3232
if (!changeName) {
3333
const canPrompt = isInteractive(options?.noInteractive);
3434
const changes = await this.getActiveChanges(changesPath);
@@ -49,25 +49,25 @@ export class ChangeCommand {
4949
return;
5050
}
5151
}
52-
52+
5353
const proposalPath = path.join(changesPath, changeName, 'proposal.md');
54-
54+
5555
try {
5656
await fs.access(proposalPath);
5757
} catch {
5858
throw new Error(`Change "${changeName}" not found at ${proposalPath}`);
5959
}
60-
60+
6161
if (options?.json) {
6262
const jsonOutput = await this.converter.convertChangeToJson(proposalPath);
63-
63+
6464
if (options.requirementsOnly) {
6565
console.error('Flag --requirements-only is deprecated; use --deltas-only instead.');
6666
}
6767

6868
const parsed: Change = JSON.parse(jsonOutput);
6969
const contentForTitle = await fs.readFile(proposalPath, 'utf-8');
70-
const title = this.extractTitle(contentForTitle);
70+
const title = this.extractTitle(contentForTitle, changeName);
7171
const id = parsed.name;
7272
const deltas = parsed.deltas || [];
7373

@@ -124,7 +124,7 @@ export class ChangeCommand {
124124

125125
return {
126126
id: changeName,
127-
title: this.extractTitle(content),
127+
title: this.extractTitle(content, changeName),
128128
deltaCount: change.deltas.length,
129129
taskStatus,
130130
};
@@ -159,7 +159,7 @@ export class ChangeCommand {
159159
const tasksPath = path.join(changesPath, changeName, 'tasks.md');
160160
try {
161161
const content = await fs.readFile(proposalPath, 'utf-8');
162-
const title = this.extractTitle(content);
162+
const title = this.extractTitle(content, changeName);
163163
let taskStatusText = '';
164164
try {
165165
const tasksContent = await fs.readFile(tasksPath, 'utf-8');
@@ -258,9 +258,9 @@ export class ChangeCommand {
258258
}
259259
}
260260

261-
private extractTitle(content: string): string {
262-
const match = content.match(/^#\s+(?:Change:\s+)?(.+)$/m);
263-
return match ? match[1].trim() : 'Untitled Change';
261+
private extractTitle(content: string, changeName: string): string {
262+
const match = content.match(/^#\s+(?:Change:\s+)?(.+)$/im);
263+
return match ? match[1].trim() : changeName;
264264
}
265265

266266
private countTasks(content: string): { total: number; completed: number } {

src/core/templates/agents-template.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ New request?
160160
161161
2. **Write proposal.md:**
162162
\`\`\`markdown
163+
# Change: [Brief description of change]
164+
163165
## Why
164166
[1-2 sentences on problem/opportunity]
165167

0 commit comments

Comments
 (0)