You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat: make apply instructions schema-aware
The `generateApplyInstructions` function was hardcoded to check for
`spec-driven` artifacts. This change makes it read artifact definitions
from the schema's new `apply` block, enabling support for different
workflows like TDD.
Changes:
- Add `ApplyPhaseSchema` Zod schema with `requires`, `tracks`, and
`instruction` fields to types.ts
- Update `SchemaYamlSchema` to include optional `apply` field
- Add `apply` block to spec-driven and tdd schemas
- Refactor `generateApplyInstructions` to:
- Load schema via `resolveSchema()`
- Read `apply.requires` for required artifacts
- Check artifact existence dynamically (supports glob patterns)
- Use `apply.tracks` for progress tracking (or skip if null)
- Use `apply.instruction` for custom guidance
- Build `contextFiles` from all existing artifacts in schema
- Handle fallback when schema has no `apply` block (require all artifacts)
- Add 8 new tests for schema-aware apply behavior
* fix: improve apply instructions robustness and consistency
- Fix artifactOutputExists to properly handle glob patterns cross-platform
by using path.sep and verifying actual file matches
- Remove redundant if/else in contextFiles loop
- Distinguish between missing tracks file vs empty tracks file
- Use consistent { error: } key in ApplyPhaseSchema validation
- Rename fallback test to accurately describe what it tests
* test: add fallback behavior tests for schemas without apply block
Add two tests that verify the fallback logic when a schema lacks an
apply block:
- Blocks when not all artifacts exist (requires ALL artifacts)
- Ready state with default instruction when all artifacts exist
Uses XDG_DATA_HOME to create temporary user schemas for testing.
instruction=`Cannot apply this change yet. Missing artifacts: ${missingArtifacts.join(', ')}.\nUse the openspec-continue-change skill to create the missing artifacts first.`;
491
-
}elseif(remaining===0&&total>0){
555
+
}elseif(tracksFile&&!tracksFileExists){
556
+
// Tracking file configured but doesn't exist yet
557
+
consttracksFilename=path.basename(tracksFile);
558
+
state='blocked';
559
+
instruction=`The ${tracksFilename} file is missing and must be created.\nUse openspec-continue-change to generate the tracking file.`;
560
+
}elseif(tracksFile&&tracksFileExists&&total===0){
561
+
// Tracking file exists but contains no tasks
562
+
consttracksFilename=path.basename(tracksFile);
563
+
state='blocked';
564
+
instruction=`The ${tracksFilename} file exists but contains no tasks.\nAdd tasks to ${tracksFilename} or regenerate it with openspec-continue-change.`;
565
+
}elseif(tracksFile&&remaining===0&&total>0){
492
566
state='all_done';
493
567
instruction='All tasks are complete! This change is ready to be archived.\nConsider running tests and reviewing the changes before archiving.';
494
-
}elseif(total===0){
495
-
state='blocked';
496
-
instruction='The tasks.md file exists but contains no tasks.\nAdd tasks to tasks.md or regenerate it with openspec-continue-change.';
568
+
}elseif(!tracksFile){
569
+
// No tracking file (e.g., TDD schema) - ready to apply
570
+
state='ready';
571
+
instruction=schemaInstruction?.trim()??'All required artifacts complete. Proceed with implementation.';
497
572
}else{
498
573
state='ready';
499
-
instruction='Read context files, work through pending tasks, mark complete as you go.\nPause if you hit blockers or need clarification.';
574
+
instruction=schemaInstruction?.trim()??'Read context files, work through pending tasks, mark complete as you go.\nPause if you hit blockers or need clarification.';
500
575
}
501
576
502
577
return{
503
578
changeName,
504
579
changeDir,
580
+
schemaName: context.schemaName,
505
581
contextFiles,
506
582
progress: { total, complete, remaining },
507
583
tasks,
@@ -541,9 +617,10 @@ async function applyInstructionsCommand(options: ApplyInstructionsOptions): Prom
0 commit comments