Skip to content
Open
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
64 changes: 51 additions & 13 deletions openspec/changes/unify-template-generation-pipeline/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,21 @@ The design goal is to preserve current behavior while making extension points ex
- Define one canonical source for workflow content and metadata
- Make tool/agent-specific behavior explicit and centrally discoverable
- Keep command adapters as the formatting boundary for tool syntax differences
- Represent tool-specific command surfaces and terminology explicitly (not as scattered string rewrites)
- Consolidate artifact generation/write orchestration into one reusable engine
- Improve correctness with enforceable validation and parity tests

**Non-Goals:**
- Redesigning command semantics or workflow instruction content
- Changing user-facing CLI command names/flags in this proposal
- Guaranteeing fully accurate literal slash-command strings for every supported tool on day one
- Merging unrelated legacy cleanup behavior beyond artifact generation reuse

## Decisions

### 1. Canonical `WorkflowManifest`

**Decision**: Represent each workflow once in a manifest entry containing canonical skill and command definitions plus metadata defaults.
**Decision**: Represent each workflow once in a manifest entry containing canonical skill and command definitions plus metadata defaults. Canonical text uses semantic tokens for tool-specific references.

Suggested shape:

Expand All @@ -41,6 +43,12 @@ interface WorkflowManifestEntry {
tags: string[];
compatibility: string;
}

// Examples in canonical workflow text:
// - {{cmd.apply}}
// - {{cmd.continue.withArg}}
// - {{term.change}}
// - {{term.workflow}}
Comment on lines +47 to +51
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

{{cmd.continue.withArg}} token format is undefined — implementation ambiguity.

The two-level tokens {{cmd.apply}} and {{term.change}} are self-explanatory, but {{cmd.continue.withArg}} introduces a three-level path (namespace · command name · modifier) without defining:

  • What .withArg means (a variant that includes an argument placeholder? a conditional rendering flag?)
  • Whether additional modifiers are valid (e.g., {{cmd.apply.withArg}})
  • How the token renderer resolves the third level

This will create inconsistent implementations across tasks 3.3 and 5.3. Recommend either defining the modifier contract inline here, or simplifying the example to a form that matches what the resolver will actually support (e.g., {{cmd.continue}}).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openspec/changes/unify-template-generation-pipeline/design.md` around lines
47 - 51, The example token {{cmd.continue.withArg}} is ambiguous; either define
the third-level modifier contract here or replace the example with a supported
two-level token like {{cmd.continue}}. Update the "Examples in canonical
workflow text" block to (a) explicitly document what a modifier such as .withArg
means (e.g., produces a placeholder argument, toggles inclusion, or is invalid),
(b) enumerate allowed modifier names and whether multiple modifiers are
permitted, and (c) describe how the renderer resolves a three-part path (lookup
order and fallback behavior). Make these edits so the example tokens
({{cmd.apply}}, {{term.change}}, and the revised {{cmd.continue}} or the newly
specified {{cmd.continue.withArg}} semantics) match the resolver behavior
expected by tasks 3.3 and 5.3.

```

**Rationale**:
Expand All @@ -50,7 +58,7 @@ interface WorkflowManifestEntry {

### 2. `ToolProfileRegistry` for capability wiring

**Decision**: Add a tool profile layer that maps tool IDs to generation capabilities and behavior.
**Decision**: Add a tool profile layer that maps tool IDs to generation capabilities, command-surface rendering, and terminology.

Suggested shape:

Expand All @@ -59,6 +67,16 @@ interface ToolProfile {
toolId: string;
skillsDir?: string;
commandAdapterId?: string;
commandSurface: {
pattern: 'opsx-colon' | 'opsx-hyphen' | 'opsx-slash' | 'openspec-hyphen' | 'custom';
verified: boolean;
aliases?: string[];
};
terminology: {
change: string;
workflow: string;
command: string;
};
transforms: string[];
}
```
Expand All @@ -67,10 +85,12 @@ interface ToolProfile {
- Prevents capability drift between `AI_TOOLS`, adapter registry, and detection logic
- Allows intentional "skills-only" tools without implicit special casing
- Provides one place to answer "what does this tool support?"
- Makes command rendering decisions explicit and testable
- Supports future terminology tailoring without copy/paste template forks

### 3. First-class transform pipeline

**Decision**: Model transforms as ordered plugins with scope + phase + applicability.
**Decision**: Model transforms as ordered plugins with scope + phase + applicability. Include token rendering in the transform pipeline instead of hardcoding literal command strings in templates.

Suggested shape:

Expand All @@ -87,17 +107,32 @@ interface ArtifactTransform {

Execution order:
1. Render canonical content from manifest
2. Apply matching `preAdapter` transforms
3. For commands, run adapter formatting
4. Apply matching `postAdapter` transforms
5. Validate and write
2. Apply token-render transform (`{{cmd.*}}`, `{{term.*}}`) using tool profile
3. Apply matching `preAdapter` transforms
4. For commands, run adapter formatting
5. Apply matching `postAdapter` transforms
6. Validate and write

**Rationale**:
- Keeps adapters focused on tool formatting, not scattered behavioral rewrites
- Makes agent-specific modifications explicit and testable
- Replaces ad-hoc transform calls in `init`/`update`
- Enables neutral fallback rendering when a tool profile is not verified for literal command syntax

### 4. Fallback policy for unverified command surfaces

**Decision**: When a tool profile has `commandSurface.verified === false`, command tokens SHALL render to neutral workflow guidance instead of literal slash-command strings.

Examples:
- Literal (verified): `Run {{cmd.apply}}`
- Neutral (unverified): `Run the Apply workflow` or `use the apply skill`

**Rationale**:
- Prevents confidently wrong guidance in generated artifacts
- Allows incremental tool-surface verification without blocking rollout
- Keeps templates stable while rendering policy evolves

### 4. Shared `ArtifactSyncEngine`
### 5. Shared `ArtifactSyncEngine`

**Decision**: Introduce a single orchestration engine used by all generation entry points.

Expand All @@ -112,13 +147,15 @@ Responsibilities:
- Enables dry-run and future preview features without re-implementing logic
- Improves reliability of updates and legacy migrations

### 5. Validation + parity guardrails
### 6. Validation + parity guardrails

**Decision**: Add strict checks in tests (and optional runtime assertions in dev builds) for:

- Required skill metadata fields (`license`, `compatibility`, `metadata`) present for all manifest entries
- Projection consistency (skills, commands, detection names derived from manifest)
- Tool profile consistency (adapter existence, expected capabilities)
- Token coverage checks (no unresolved `{{...}}` tokens in rendered outputs)
- Tool command-surface verification matrix and fallback expectations
- Golden/parity output for key workflows/tools

**Rationale**:
Expand All @@ -143,7 +180,8 @@ Adding manifest/profile/transform registries increases conceptual surface area.
## Implementation Approach

1. Build manifest + profile + transform types and registries behind current public API
2. Rewire `getSkillTemplates`/`getCommandContents` to derive from manifest
3. Introduce `ArtifactSyncEngine` and switch `init` to use it with parity checks
4. Switch `update` and legacy upgrade flows to same engine
5. Remove duplicate/hardcoded lists after parity is green
2. Tokenize command/terminology references in workflow templates
3. Rewire `getSkillTemplates`/`getCommandContents` to derive from manifest
4. Introduce `ArtifactSyncEngine` and switch `init` to use it with parity checks
5. Switch `update` and legacy upgrade flows to same engine
6. Remove duplicate/hardcoded lists after parity is green
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ The recent split of `skill-templates.ts` into workflow modules improved readabil

- Workflow definitions are split from projection logic (`getSkillTemplates`, `getCommandTemplates`, `getCommandContents`)
- Tool capability and compatibility are spread across `AI_TOOLS`, `CommandAdapterRegistry`, and hardcoded lists like `SKILL_NAMES`
- Agent/tool-specific transformations (for example OpenCode command reference rewrites) are applied in different places (`init`, `update`, and adapter code)
- Agent/tool-specific transformations are applied in different places (`init`, `update`, and adapter code)
- Command and terminology references are currently hardcoded in workflow text, but tool invocation surfaces vary (`/opsx:apply`, `/opsx-apply`, `/opsx/apply`, and tool-specific naming)
- Artifact writing logic is duplicated across `init`, `update`, and legacy-upgrade flow

This fragmentation creates drift risk (missing exports, missing metadata parity, mismatched counts/support) and makes future workflow/tool additions slower and less predictable.
Expand All @@ -15,13 +16,16 @@ This fragmentation creates drift risk (missing exports, missing metadata parity,
- Introduce a `ToolProfileRegistry` to centralize tool capabilities (skills path, command adapter, transforms)
- Introduce a first-class transform pipeline with explicit phases (`preAdapter`, `postAdapter`) and scopes (`skill`, `command`, `both`)
- Introduce a shared `ArtifactSyncEngine` used by `init`, `update`, and legacy upgrade paths
- Add tokenized workflow text rendering so command references and tool terminology are resolved per tool profile at generation time
- Add explicit command-surface profiles per tool (pattern, namespace/path style, alias support, verification status)
- Add safe fallback behavior: when a tool command surface is not verified, render neutral workflow guidance (for example skill/workflow names) instead of potentially wrong literal command strings
- Add strict validation and test guardrails to preserve fidelity during migration and future changes

## Capabilities

### New Capabilities

- `template-artifact-pipeline`: Unified workflow manifest, tool profile registry, transform pipeline, and sync engine for skill/command generation
- `template-artifact-pipeline`: Unified workflow manifest, tool profile registry, token-aware transform pipeline, and sync engine for skill/command generation

### Modified Capabilities

Expand All @@ -41,7 +45,9 @@ This fragmentation creates drift risk (missing exports, missing metadata parity,
- **Testing additions**:
- Manifest completeness tests (workflows, required metadata, projection parity)
- Transform ordering and applicability tests
- Tool command-surface/terminology profile validation tests
- End-to-end parity tests for generated skill/command outputs across tools
- **User-facing behavior**:
- No new CLI surface area required
- Existing generated artifacts remain behaviorally equivalent unless explicitly changed in future deltas
- Generated text may become more tool-accurate for verified tool profiles
- Generated text may intentionally use neutral workflow wording for unverified tools to avoid incorrect slash-command guidance
20 changes: 13 additions & 7 deletions openspec/changes/unify-template-generation-pipeline/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@
- [ ] 2.1 Add `ToolProfile` types and `ToolProfileRegistry`
- [ ] 2.2 Map all currently supported tools to explicit profile entries
- [ ] 2.3 Wire profile lookups to command adapter resolution and skills path resolution
- [ ] 2.4 Replace hardcoded detection arrays (for example `SKILL_NAMES`) with manifest-derived values
- [ ] 2.4 Add per-tool `commandSurface` metadata (pattern, aliases, `verified` flag)
- [ ] 2.5 Add per-tool terminology metadata (for example change/workflow/command labels)
- [ ] 2.6 Replace hardcoded detection arrays (for example `SKILL_NAMES`) with manifest-derived values

## 3. Transform Pipeline

- [ ] 3.1 Introduce transform interfaces (`scope`, `phase`, `priority`, `applies`, `transform`)
- [ ] 3.2 Implement transform runner with deterministic ordering
- [ ] 3.3 Migrate OpenCode command reference rewrite to transform pipeline
- [ ] 3.4 Remove ad-hoc transform invocation from `init` and `update`
- [ ] 3.3 Add token renderer transform for command + terminology tokens (`{{cmd.*}}`, `{{term.*}}`)
- [ ] 3.4 Implement neutral fallback rendering for tools with unverified command surfaces
- [ ] 3.5 Migrate OpenCode command reference rewrite to transform pipeline
- [ ] 3.6 Remove ad-hoc transform invocation from `init` and `update`

## 4. Artifact Sync Engine

Expand All @@ -29,10 +33,12 @@
## 5. Validation and Tests

- [ ] 5.1 Add manifest completeness tests (metadata required fields, command IDs, dir names)
- [ ] 5.2 Add tool-profile consistency tests (skillsDir support and adapter/profile alignment)
- [ ] 5.3 Add transform applicability/order tests
- [ ] 5.4 Expand parity tests for representative workflow/tool matrix
- [ ] 5.5 Run full test suite and verify generated artifacts remain stable
- [ ] 5.2 Add tool-profile consistency tests (skillsDir support, adapter/profile alignment, command-surface metadata)
- [ ] 5.3 Add token rendering tests (all tokens resolved, per-tool rendering correctness)
- [ ] 5.4 Add fallback tests for unverified tool command surfaces
- [ ] 5.5 Add transform applicability/order tests
- [ ] 5.6 Expand parity tests for representative workflow/tool matrix
- [ ] 5.7 Run full test suite and verify generated artifacts remain stable

## 6. Cleanup and Documentation

Expand Down
Loading