Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions src/commands/artifact-workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ function printInstructionsText(instructions: ArtifactInstructions, isBlocked: bo
outputPath,
description,
instruction,
context,
rules,
template,
dependencies,
unlocks,
Expand All @@ -339,9 +341,29 @@ function printInstructionsText(instructions: ArtifactInstructions, isBlocked: bo
console.log('</task>');
console.log();

// Context (dependencies)
// Project context (AI constraint - do not include in output)
if (context) {
console.log('<project_context>');
console.log('<!-- This is background information for you. Do NOT include this in your output. -->');
console.log(context);
console.log('</project_context>');
console.log();
}

// Rules (AI constraint - do not include in output)
if (rules && rules.length > 0) {
console.log('<rules>');
console.log('<!-- These are constraints for you to follow. Do NOT include this in your output. -->');
for (const rule of rules) {
console.log(`- ${rule}`);
}
console.log('</rules>');
console.log();
}

// Dependencies (files to read for context)
if (dependencies.length > 0) {
console.log('<context>');
console.log('<dependencies>');
console.log('Read these files for context before creating this artifact:');
console.log();
for (const dep of dependencies) {
Expand All @@ -352,7 +374,7 @@ function printInstructionsText(instructions: ArtifactInstructions, isBlocked: bo
console.log(` <description>${dep.description}</description>`);
console.log('</dependency>');
}
console.log('</context>');
console.log('</dependencies>');
console.log();
}

Expand All @@ -372,6 +394,7 @@ function printInstructionsText(instructions: ArtifactInstructions, isBlocked: bo

// Template
console.log('<template>');
console.log('<!-- Use this as the structure for your output file. Fill in the sections. -->');
console.log(template.trim());
console.log('</template>');
console.log();
Expand Down
36 changes: 13 additions & 23 deletions src/core/artifact-graph/instruction-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ export interface ArtifactInstructions {
description: string;
/** Guidance on how to create this artifact (from schema instruction field) */
instruction: string | undefined;
/** Template content (structure to follow) */
/** Project context from config (constraints/background for AI, not to be included in output) */
context: string | undefined;
/** Artifact-specific rules from config (constraints for AI, not to be included in output) */
rules: string[] | undefined;
/** Template content (structure to follow - this IS the output format) */
template: string;
/** Dependencies with completion status and paths */
dependencies: DependencyInfo[];
Expand Down Expand Up @@ -218,14 +222,11 @@ export function generateInstructions(
const dependencies = getDependencyInfo(artifact, context.graph, context.completed);
const unlocks = getUnlockedArtifacts(context.graph, artifactId);

// Build enriched template with project config injections
let enrichedTemplate = '';
let projectConfig = null;

// Use projectRoot from context if not explicitly provided
const effectiveProjectRoot = projectRoot ?? context.projectRoot;

// Try to read project config
// Try to read project config for context and rules
let projectConfig = null;
if (effectiveProjectRoot) {
try {
projectConfig = readProjectConfig(effectiveProjectRoot);
Expand All @@ -252,23 +253,10 @@ export function generateInstructions(
}
}

// 1. Add context (all artifacts)
if (projectConfig?.context) {
enrichedTemplate += `<context>\n${projectConfig.context}\n</context>\n\n`;
}

// 2. Add rules (only for matching artifact)
// Extract context and rules as separate fields (not prepended to template)
const configContext = projectConfig?.context?.trim() || undefined;
const rulesForArtifact = projectConfig?.rules?.[artifactId];
if (rulesForArtifact && rulesForArtifact.length > 0) {
enrichedTemplate += `<rules>\n`;
for (const rule of rulesForArtifact) {
enrichedTemplate += `- ${rule}\n`;
}
enrichedTemplate += `</rules>\n\n`;
}

// 3. Add original template (without wrapper - CLI handles XML structure)
enrichedTemplate += templateContent;
const configRules = rulesForArtifact && rulesForArtifact.length > 0 ? rulesForArtifact : undefined;

return {
changeName: context.changeName,
Expand All @@ -278,7 +266,9 @@ export function generateInstructions(
outputPath: artifact.generates,
description: artifact.description,
instruction: artifact.instruction,
template: enrichedTemplate,
context: configContext,
rules: configRules,
template: templateContent,
dependencies,
unlocks,
};
Expand Down
55 changes: 42 additions & 13 deletions src/core/templates/skill-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,10 +434,17 @@ export function getContinueChangeSkillTemplate(): SkillTemplate {
\`\`\`bash
openspec instructions <artifact-id> --change "<name>" --json
\`\`\`
- Parse the JSON to get template, dependencies, and what it unlocks
- **Create the artifact file** using the template as a starting point:
- Parse the JSON. The key fields are:
- \`context\`: Project background (constraints for you - do NOT include in output)
- \`rules\`: Artifact-specific rules (constraints for you - do NOT include in output)
- \`template\`: The structure to use for your output file
- \`instruction\`: Schema-specific guidance
- \`outputPath\`: Where to write the artifact
- \`dependencies\`: Completed artifacts to read for context
- **Create the artifact file**:
- Read any completed dependency files for context
- Fill in the template based on context and user's goals
- Use \`template\` as the structure - fill in its sections
- Apply \`context\` and \`rules\` as constraints when writing - but do NOT copy them into the file
- Write to the output path specified in instructions
- Show what was created and what's now unlocked
- STOP after creating ONE artifact
Expand Down Expand Up @@ -489,7 +496,10 @@ For other schemas, follow the \`instruction\` field from the CLI output.
- Never skip artifacts or create out of order
- If context is unclear, ask the user before creating
- Verify the artifact file exists after writing before marking progress
- Use the schema's artifact sequence, don't assume specific artifact names`
- Use the schema's artifact sequence, don't assume specific artifact names
- **IMPORTANT**: \`context\` and \`rules\` are constraints for YOU, not content for the file
- Do NOT copy \`<context>\`, \`<rules>\`, \`<project_context>\` blocks into the artifact
- These guide what you write, but should never appear in the output`
};
}

Expand Down Expand Up @@ -699,12 +709,15 @@ export function getFfChangeSkillTemplate(): SkillTemplate {
openspec instructions <artifact-id> --change "<name>" --json
\`\`\`
- The instructions JSON includes:
- \`template\`: The template content to use
- \`context\`: Project background (constraints for you - do NOT include in output)
- \`rules\`: Artifact-specific rules (constraints for you - do NOT include in output)
- \`template\`: The structure to use for your output file
- \`instruction\`: Schema-specific guidance for this artifact type
- \`outputPath\`: Where to write the artifact
- \`dependencies\`: Completed artifacts to read for context
- Read any completed dependency files for context
- Create the artifact file following the schema's \`instruction\`
- Create the artifact file using \`template\` as the structure
- Apply \`context\` and \`rules\` as constraints - but do NOT copy them into the file
- Show brief progress: "✓ Created <artifact-id>"

b. **Continue until all \`applyRequires\` artifacts are complete**
Expand Down Expand Up @@ -734,7 +747,10 @@ After completing all artifacts, summarize:
- Follow the \`instruction\` field from \`openspec instructions\` for each artifact type
- The schema defines what each artifact should contain - follow it
- Read dependency artifacts for context before creating new ones
- Use the \`template\` as a starting point, filling in based on context
- Use \`template\` as the structure for your output file - fill in its sections
- **IMPORTANT**: \`context\` and \`rules\` are constraints for YOU, not content for the file
- Do NOT copy \`<context>\`, \`<rules>\`, \`<project_context>\` blocks into the artifact
- These guide what you write, but should never appear in the output

**Guardrails**
- Create ALL artifacts needed for implementation (as defined by schema's \`apply.requires\`)
Expand Down Expand Up @@ -1206,10 +1222,17 @@ export function getOpsxContinueCommandTemplate(): CommandTemplate {
\`\`\`bash
openspec instructions <artifact-id> --change "<name>" --json
\`\`\`
- Parse the JSON to get template, dependencies, and what it unlocks
- **Create the artifact file** using the template as a starting point:
- Parse the JSON. The key fields are:
- \`context\`: Project background (constraints for you - do NOT include in output)
- \`rules\`: Artifact-specific rules (constraints for you - do NOT include in output)
- \`template\`: The structure to use for your output file
- \`instruction\`: Schema-specific guidance
- \`outputPath\`: Where to write the artifact
- \`dependencies\`: Completed artifacts to read for context
- **Create the artifact file**:
- Read any completed dependency files for context
- Fill in the template based on context and user's goals
- Use \`template\` as the structure - fill in its sections
- Apply \`context\` and \`rules\` as constraints when writing - but do NOT copy them into the file
- Write to the output path specified in instructions
- Show what was created and what's now unlocked
- STOP after creating ONE artifact
Expand Down Expand Up @@ -1261,7 +1284,10 @@ For other schemas, follow the \`instruction\` field from the CLI output.
- Never skip artifacts or create out of order
- If context is unclear, ask the user before creating
- Verify the artifact file exists after writing before marking progress
- Use the schema's artifact sequence, don't assume specific artifact names`
- Use the schema's artifact sequence, don't assume specific artifact names
- **IMPORTANT**: \`context\` and \`rules\` are constraints for YOU, not content for the file
- Do NOT copy \`<context>\`, \`<rules>\`, \`<project_context>\` blocks into the artifact
- These guide what you write, but should never appear in the output`
};
}

Expand Down Expand Up @@ -1474,12 +1500,15 @@ export function getOpsxFfCommandTemplate(): CommandTemplate {
openspec instructions <artifact-id> --change "<name>" --json
\`\`\`
- The instructions JSON includes:
- \`template\`: The template content to use
- \`context\`: Project background (constraints for you - do NOT include in output)
- \`rules\`: Artifact-specific rules (constraints for you - do NOT include in output)
- \`template\`: The structure to use for your output file
- \`instruction\`: Schema-specific guidance for this artifact type
- \`outputPath\`: Where to write the artifact
- \`dependencies\`: Completed artifacts to read for context
- Read any completed dependency files for context
- Create the artifact file following the schema's \`instruction\`
- Create the artifact file using \`template\` as the structure
- Apply \`context\` and \`rules\` as constraints - but do NOT copy them into the file
- Show brief progress: "✓ Created <artifact-id>"

b. **Continue until all \`applyRequires\` artifacts are complete**
Expand Down
Loading
Loading