fix(planning-home): honor config.yaml changesDir and schema for repo homes - #1320
fix(planning-home): honor config.yaml changesDir and schema for repo homes#1320stanleykao72 wants to merge 42 commits into
Conversation
Allow projects to customize where changes are stored by adding a `changesDir` field to `openspec/config.yaml`. This enables monorepo setups where changes live per-module (e.g., `src/module/.specs/changes`) instead of the default `openspec/changes/`. Changes: - Add `changesDir` to ProjectConfigSchema (Zod validated, optional) - Add `getChangesDir(projectRoot)` helper that reads config with fallback - Replace all 16 hardcoded `path.join(..., 'openspec', 'changes')` with `getChangesDir()` across commands, core, and utils Usage: ```yaml # openspec/config.yaml schema: spec-driven changesDir: user/my_module/.specs/changes # custom path ``` When omitted, defaults to `openspec/changes` (fully backward compatible).
Custom schema for Odoo SDD development: - proposal.md: status table + BR linkage + impact matrix (models/views/security/i18n) - spec.md: delta spec with Target BR and Odoo-specific scenario rules - tasks.md: P0/P1/P2 priority tiers + Mermaid dependency graph + bug-fix tracking - apply instruction: TDD workflow + Lore Protocol commits + PR-based flow DAG: proposal → specs → tasks (no design.md — Odoo changes rarely need it)
Define verify (6 steps) and archive (3 steps) lifecycle phases as YAML: - verify.yaml: coverage, regression, tech, e2e, stage-merge, stage-check with parallel groups, rollback rules, and environment preferences - archive.yaml: main-merge, BR writeback (with confirm_before), branch cleanup with br_writeback rules for ADDED/MODIFIED/REMOVED delta types These files are read by the /change skill at runtime. OpenSpec CLI does not parse them — they're a convention layered on top of the schema directory structure.
Real failure: /opsx:propose generated free-format spec (tables, numbered lists) instead of the ### Requirement: / #### Scenario: structure that OpenSpec's delta parser expects. Archive silently found "no operations". Changes: - spec.md template: added explicit warning, full examples for each delta type, comments explaining WHY format matters - schema.yaml instruction: added error/correct examples, CRITICAL warnings about free-format substitution, explicit "archive depends on this format" Root cause: AI saw the template but improvised with tables and numbered lists. The instruction didn't make clear that format deviation = archive failure.
…sdd schema Extend ApplyPhaseSchema with gates (pre/post quality checkpoints) and steps (execution phases with TDD method support). Add GateChecker for automated structural checks (capability coverage, scenario-task ratio, task completion, TDD markers). New CLI command `openspec gate check` runs gates and produces JSON reports. Enable /opsx:verify in CORE_WORKFLOWS. Create odoo-sdd schema integrating Odoo SDD workflow with alignment gates and TDD enforcement. Constraint: Gates are optional in schema — existing spec-driven schema unaffected Constraint: AI-review gates return prompts for AI execution, engine never calls LLM Rejected: Pure instruction-based gates | AI can skip text instructions, schema gates are structural Rejected: Obsidian dashboard approach | Real problem was spec-code alignment, not visibility Rejected: Integrating into Odoo module | Business system boundary should not include dev tools Confidence: high Scope-risk: moderate Reversibility: clean Directive: When adding new check types to GateChecker, register them in checkGate() dispatcher Tested: Build passes, CLI gate check returns valid JSON, backward compat with spec-driven Not-tested: End-to-end gate enforcement during actual agent-teams apply session Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… instructions Cover all gate-related functionality: Zod schema parsing (valid/invalid/optional), backward compatibility with spec-driven schema, GateChecker methods (capability-coverage, scenario-task-ratio, all-tasks-done, TDD markers), checkGate dispatcher, and generateApplyInstructions with gates/steps. Tested: npx vitest run — 63/63 pass Confidence: high Scope-risk: narrow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dd gate exit code tests Existing tests hardcoded CORE_WORKFLOWS as 4 items. Updated 7 test files to include 'verify' as the 5th core workflow. Added 2 new tests verifying gate check exit code behavior (blocking=1, warning=0). Added trade-off comment to odoo-sdd schema explaining ai-review choice for test-exists gate. Tested: All 180 targeted tests pass Confidence: high Scope-risk: narrow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nment process.env.ZSH (set by Oh My Zsh) short-circuits isOhMyZshInstalled() before the filesystem check, causing 18 test failures on macOS with Oh My Zsh installed. Save/clear/restore process.env.ZSH in beforeEach/afterEach. Constraint: Cannot modify source code — fix must be in test isolation Tested: 50/50 zsh-installer tests pass on macOS with Oh My Zsh Confidence: high Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ster workflow Mirrors the odoo-claude-code workflow migration. PR base changed from staging to master. Removed stage-merged/stage-checked verify steps. Archive phase renamed main-merged to pr-merged. Constraint: Only affects odoo-specific schemas, core OpenSpec unchanged Confidence: high Scope-risk: narrow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… and bundled schemas Extensible plugin architecture allowing projects to add lifecycle hooks (propose/apply/archive pre/post), custom gate types, and bundled schemas without modifying OpenSpec core. Plugin system features: - Three-tier resolution (project → user → package) matching schema pattern - Whitelist-based loading from config.yaml plugins array - Hybrid handlers: command (shell), prompt (AI agent), both - Plugin config declaration and validation with required field enforcement - Plugin-provided schemas in resolver chain - Plugin gate types extending the gate checker - CLI commands: openspec plugin list/info - Lazy plugin loading with cache for existing call sites Constraint: No new npm dependencies — semver check is inline Constraint: All existing call sites work unchanged (optional parameters) Rejected: npm-style plugin registry | over-engineering for current needs Rejected: Auto-discovery without whitelist | security risk Confidence: high Scope-risk: moderate Reversibility: clean Tested: 40 new tests + 1406 existing tests pass Not-tested: Windows cross-platform command execution Directive: Plugin prompt handlers depend on the calling AI agent — keep them tool-agnostic Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…s via skill_overlays Plugins could define schemas, hooks, and gates but had no way to influence the content of generated skill/command files. This forced plugin authors to maintain out-of-band instructions that were lost on every `openspec update`. Added `skill_overlays` to plugin manifest schema — plugins declare overlay files per workflow ID, and `openspec update` appends their content to the corresponding skill and command output via a composable transformer pipeline. Constraint: Only `append` operation supported initially; schema uses .strict() to reject unknown ops Rejected: Array of operations per workflow | unnecessary complexity for single-operation use case Rejected: Modify skill-generation.ts signature | compose pattern preserves existing API contract Confidence: high Scope-risk: moderate Reversibility: clean Directive: Future prepend/replace_section ops can be added to SkillOverlaySchema without migration Tested: 1466 tests pass (17 new: schema validation, overlay resolution, transformer composition) Not-tested: Integration with real plugin overlay files during openspec update (manual verification needed) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ation README plugin section was missing the new skill_overlays feature. Added manifest field reference and usage example with overlay files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Synced 3 new specs (skill-overlay-manifest, skill-overlay-injection, skill-overlay-cli) and merged 2 modified specs (cli-update, config-loading) into main spec directory. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enable schema-level verify and archive phase definitions (VerifyPhaseSchema, ArchivePhaseSchema) so plugins can define custom verification steps and archive workflows per schema. Also adds verify.pre/verify.post hook points. Constraint: Must be backward compatible — schemas without verify/archive definitions fallback to existing behavior Rejected: Only use overlays without framework support | inconsistent with apply phase which has ApplyPhaseSchema Confidence: high Scope-risk: moderate Reversibility: clean Tested: vitest 1463/1466 pass (1 pre-existing failure in source-specs-normalization) Not-tested: Runtime schema-aware verify/archive flow (requires plugin with verify/archive definitions) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ution (#3) Enable --subagents/--teams flags on all workflow phases. CLI analyzes task groups, domain tags, and plugin declarations to output OrchestrationHints — declaring WHAT can be parallel without dictating HOW. Two-layer resolution: plugins declare parallel capabilities (parallel_with), schemas override with project-level decisions. Hook/gate dispatchers support parallel execution (Promise.all for commands, pending markers for prompts). Includes change artifacts, two reference plugins (dual-review, alignment-check), and README orchestration docs. Also fixes 3 source specs missing ## Purpose/## Requirements headers. Constraint: CLI must remain AI-harness-agnostic — hints only, no agent spawning Constraint: parallel_with must be bidirectional (both gates must declare) Rejected: CLI directly spawns parallel processes | prompt gates need AI judgment Rejected: Schema-only orchestration | plugin authors know concurrency safety best Confidence: high Scope-risk: moderate Reversibility: clean Tested: 52 new tests (group-builder, domain-parser, resolver, parallel-hooks, parallel-gates, integration), 1529 total — all passing Not-tested: Windows CI (no Windows runner available locally) Directive: If adding new gate types, ensure they declare orchestration if they can run independently — the resolver won't auto-parallelize without it Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These plugins (dual-review, alignment-check) belong in consuming Odoo projects, not in the OpenSpec CLI development config. The CLI repo has no plugin files at the resolvable paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pipeline runner for automatic gate/hook execution. New commands: openspec run start/complete, openspec gate resolve. Enhanced tdd-markers with [skip-tdd]. 50 new tests, 1579 total. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
) * [openspec]: feat Add Covers auto-injection, change class routing, and gate escape hatch CLI enhancements to support the 3-tier artifact alignment gate system. Covers annotations are auto-injected by `openspec instructions` to reduce manual maintenance. Change classes route different gate profiles. Waiver system provides an auditable escape hatch for urgent fixes. - instructions command: auto-inject Covers from proposal/specs into templates - new-change command: --class flag (feature/single-cap/infra/hotfix) - pipeline runner: gate filtering by change class (Tier A/B/C profiles) - run complete: --gate-profile override with .waiver.yaml requirement - waiver list: scan all changes for active waivers Constraint: Must not break existing CLI commands or schema behavior Constraint: Covers injection reads existing artifacts, never modifies them Rejected: Stable IDs (REQ-001) for traceability | deferred to future migration Rejected: openspec-disable comment for escape | too easy to copy-paste, untrackable Confidence: high Scope-risk: moderate Reversibility: clean Tested: TypeScript build passes, manual verification of all spec scenarios Not-tested: End-to-end with alignment-check plugin gates (requires plugin deploy) Directive: When adding new gate tiers, update GATE_PROFILES in runner.ts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [openspec]: fix Enforce propose.post gates by adding run complete to propose skill The propose skill template only called `run start` (pre-hooks) but never `run complete` (post-hooks/post-gates). This meant Tier A/B/C alignment gates would never fire. Now both start and complete are called, with hard-block gate failure preventing propose from completing. Constraint: Must not break existing propose flow when no gates are configured Confidence: high Scope-risk: narrow Tested: TypeScript build passes Related: 44bb493 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…not project root (#6) Plugin hooks with `run: "node gates/structural.js"` failed with MODULE_NOT_FOUND because execCommand() used context.projectRoot as CWD. The relative path in `run:` is relative to the plugin directory, not the project root. Prompt handlers already used plugin.dir correctly. Constraint: OPENSPEC_PROJECT_ROOT env var must remain unchanged (scripts use it) Tested: openspec run complete --phase propose — structural.js and traceability.js both PASS Not-tested: both-type handlers (no current plugins use both with relative paths) Confidence: high Scope-risk: narrow Reversibility: clean Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…r orchestration (#7) Schemas can now declare a default orchestration mode (e.g., default_mode: teams) that kicks in when the user doesn't pass --teams/--subagents/--sequential. Priority: user flag > schema default > null. Added --sequential as a third mutually exclusive orchestration flag, serving as an escape hatch for simple changes where team overhead isn't justified. Constraint: mode_from must distinguish user_flag vs schema vs default for overlay decision-making Rejected: Hardcode default in overlay | different schemas need different defaults Confidence: high Scope-risk: narrow Reversibility: clean Tested: Manual verification of all 3 flags + mutual exclusion + schema default_mode resolution Not-tested: Integration with actual TeamCreate execution (overlay behavior) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* [openspec]: fix Pass loadedPlugins to schema resolution in CLI commands (#8) Plugin-provided schemas (declared in plugin.yaml schemas: field) were invisible to CLI commands: schema which/validate/fork, status, templates. Root cause: getSchemaDir() and listSchemas() accept optional loadedPlugins parameter, but CLI callers never passed it. Additionally, resolveSchemaForChange() derived projectRoot from changeDir (path.resolve(changeDir, '../../..')) which fails when changesDir points to an external directory (e.g., Obsidian vault). Added optional projectRoot parameter so loadChangeContext can pass the correct value. Files fixed: - commands/schema.ts: checkAllLocations, getAllSchemasWithResolution, validate, fork commands + display grouping for plugin source - commands/workflow/shared.ts: validateSchemaExists - commands/workflow/schemas.ts: schemasCommand - commands/workflow/templates.ts: templatesCommand + TemplateInfo source type - utils/change-metadata.ts: validateSchemaName, readChangeMetadata, resolveSchemaForChange (added projectRoot parameter) - core/artifact-graph/instruction-loader.ts: pass projectRoot to resolveSchemaForChange Constraint: resolveSchema() already had auto-load failsafe (line 130) — but getSchemaDir/listSchemas did not, causing inconsistent behavior Rejected: Add failsafe to getSchemaDir/listSchemas | explicit is better than implicit Confidence: high Scope-risk: moderate Tested: openspec schema which --all shows plugin schemas, status reports correct schemaName Not-tested: Edge case where plugin dir is missing but plugin.yaml declares schemas Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [openspec]: fix Repair 9 test failures introduced by our plugin customizations Hook dispatcher tests (7 failures): - Commit dc0f945 changed command cwd from projectRoot to plugin.dir - Tests created mock plugins without mkdir for plugin.dir - Fix: Add fs.mkdirSync(dir, { recursive: true }) in makePlugin helpers and inline plugin construction (env-check test) Template parity tests (2 failures): - Commit ecf33bc modified propose template content (added gate enforcement) - Expected content hashes in test were not updated - Fix: Update 3 hashes (getOpsxProposeSkillTemplate, getOpsxProposeCommandTemplate, openspec-propose) Tested: 1579/1579 tests pass (was 1570/1579) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… (#9) loadTemplate() called getSchemaDir(schemaName, projectRoot) without loadedPlugins, causing "Schema 'odoo-sdd' not found" for plugin-provided schemas. This was the last missing callsite after PR #8. The error message was misleading — appeared as schema resolution failure but was actually template loading failure because getSchemaDir returned null for plugin schemas. Constraint: loadTemplate is called from generateInstructions, which is the hot path for every `openspec instructions` command Tested: 1579/1579 tests pass, `openspec instructions proposal --change X` correctly reports schemaName: odoo-sdd with plugin schema Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…or staleness detection (#10) Gate results now include a SHA256 fingerprint computed from tracked artifact files (proposal.md, specs/**/*.md, design.md, tasks.md). On subsequent gate runs, isSynthesisStale() compares current vs stored fingerprint to detect when specs have changed since last gate execution. Constraint: Only tracks spec/design artifacts, not implementation files (.py/.ts/.xml) Constraint: Content-based hash (not mtime) for stability across git checkout/CI Rejected: Per-file hash dict | single composite hash is simpler and sufficient for stale detection Rejected: mtime-based comparison | unstable in CI/CD and git worktree environments Confidence: high Scope-risk: narrow Reversibility: clean Tested: 14 unit tests covering determinism, mtime-independence, staleness detection, and synthesis integration Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Update skill template parity hashes for rebased content - Move requirements outside ## Requirements section to fix findMainSpecStructureIssues validation (upstream Fission-AI#966) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
validateConfigRules warned on every rules key not in the current schema,
making it impossible for a single flat rules: map in config.yaml to
cover multiple schemas. Running odoo-bugfix warned on odoo-sdd keys
(proposal/specs/design/tasks) and vice versa.
Added optional knownArtifactIds param (union of artifact IDs across all
registered schemas). Keys valid for another schema are now skipped
silently — only truly unknown keys produce warnings. Caller in
instruction-loader builds the union via listSchemasWithInfo.
Backward-compatible: when knownArtifactIds is omitted the function
falls back to original single-schema validation behavior.
Constraint: Must not break single-schema projects that omit the 4th arg
Rejected: Make rules schema-scoped (rules: { schema: {...} }) | breaking change, upstream-unfriendly
Confidence: high
Scope-risk: narrow
Tested: openspec instructions fix (bugfix) and proposal (sdd) both produce no warnings
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…m-v1.3.1 Resolves CORE_WORKFLOWS to union both verify (fork) and sync (upstream). Nests fork's getChangesDir() inside upstream's canonicalizeExistingPath(). Mechanically applies 6-entry CORE list to test fixtures. Constraint: fork has v1.3.0 base + 26 commits ahead, upstream landed workspace foundation Rejected: rebase (linear history) | 26 commit replay would hit same conflict each time Confidence: medium Scope-risk: moderate Reversibility: clean (merge commit, can revert) Tested: pnpm install + test + build + validate (Stage 12 follow-up) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…WS union After merging upstream/main, CORE_WORKFLOWS now contains both verify and sync. The 'extra workflow' test scenario (project has artifacts beyond configured workflows) needed a workflow that's truly non-core. Switched helper from openspec-verify-change/verify.md to openspec-new-change/new.md since 'new' is in ALL_WORKFLOWS but not CORE_WORKFLOWS. Constraint: warning test requires a non-core workflow artifact to trigger Tested: pnpm test test/commands/config-profile.test.ts → 18/18 pass Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…th workspace-aware revisions Adds the long-tracked umbrella change that maps fork's 26 commits to a 5-PR upstream contribution plan. Originally drafted 2026-04-17 (memory project_openspec_upstream_strategy.md). Updated 2026-05-04 to account for workspace-foundation landing (PR Fission-AI#1045) and TabishB's 21-day silence since the 04-13 PR Fission-AI#891 ack. Key revisions: - T0 icebreaker: marked stalled-not-negative; push T1 to force review - T1 (plugin foundation): risk MEDIUM → HIGH, surface area churned by workspace-foundation; submit FIRST despite higher rebase cost - T5 (fingerprinting): submit IN PARALLEL with T1 (independent, no workspace coupling) - T3 (orchestration hints): risk MEDIUM → LOW, submit AFTER T1 lands - T2 (verify/archive phases): DEFERRED — overlaps slice 6 workspace-verify-and-archive proposal - T4 (pipeline runner): DEFERRED — overlaps slice 5 workspace-apply-repo-slice proposal; apply semantics being redefined Section 0.5 records the 2026-05-04 sync merge (fork PR #12). Constraint: spec-driven schema validation fails (no deltas) — acceptable, this is a planning umbrella, not a capability change Confidence: high (analysis based on reading all 4 workspace slice proposals on upstream/main) Scope-risk: narrow (fork-only docs, never contributed) Reversibility: clean Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…orkspace-revision docs: track upstream contribution strategy with workspace-aware 5-PR revision
Background: when openspec CLI is invoked from a git worktree (e.g.
worktrees/fr-fx-formula-persistence), the plugin schema lookup falls back
to the package version (this file) instead of the project's plugin override
(odoo-claude-code/openspec/plugins/odoo-lifecycle/schemas/odoo-sdd). The
package version had no `archive:` phase, so `/opsx:archive` step 5 ("if
schema defines archive steps... else skip") evaluated false → archive.post
hooks (including obsidian-sync) never fired → vault sync silently dropped.
Fix: mirror the plugin version's archive phase into the package version
with inline self-contained obsidian-synced instructions (parse archive_dir,
mcp__obsidian__write_note path/frontmatter/content). Tells agent what to
do even if the project doesn't have the odoo-lifecycle plugin overlay.
After this change, both:
- `cd /worktrees/<wt> && openspec schema which odoo-sdd` (package fallback)
- `cd /project-root && openspec schema which odoo-sdd` (plugin override)
return a schema with an `archive` phase, so step 5 always runs and step
`obsidian-synced` always executes.
Constraint: package schema must stay in sync with plugin override pattern
for users without the odoo-lifecycle plugin
Confidence: high
Scope-risk: narrow (one schema file, opt-in for users who pick odoo-sdd)
Reversibility: clean
Tested: `cd /worktrees/<wt> && openspec schema which odoo-sdd` now shows
Source: package, archive phase = 1 (was 0)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nline delta→main transformation
The archive-change skill / opsx command template referenced a Skill
'openspec-sync-specs' that is not installed in current marketplace
distributions. As a result, /opsx:archive would either silently fail to
sync delta specs to main specs or invoke a non-existent skill via Task
tool, leaving archived changes with delta-format spec.md files that
openspec validate parses as 0 requirements.
Inline the entire delta→main transformation as concrete numbered steps
(a-e):
a. Read delta spec
b. NEW vs EXISTING capability branches (frontmatter + Purpose + flat
Requirements for NEW; append/overwrite/delete for EXISTING)
c. Write to project-local openspec/specs/<cap>/spec.md
d. Validate via `openspec validate --specs`
e. Advisory stage (no auto-commit)
Also resolve the changesDir path from openspec/config.yaml so projects
that relocate changes (e.g. to an Obsidian vault) work correctly,
instead of assuming `openspec/changes/`.
Updated 4 occurrences:
- getArchiveChangeSkillTemplate(): step 4 + Guardrails
- getOpsxArchiveCommandTemplate(): step 4 + Guardrails
Build verified: `npm run build` passes.
…ix options (#14) Documents the silent scenario-loss bug when two changes MODIFY the same requirement and archive sequentially (specs-apply.ts:297 whole-block replace with no scenario merge), traces the root cause to source, and lays out three fix options (A fingerprint gating, B scenario-level merge, C phased). Analysis and design only; no code change. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ly run/gate (#15) * [openspec]: docs Add RFC for parallel-archive scenario-loss bug and fix options Documents the silent scenario-loss bug when two changes MODIFY the same requirement and archive sequentially (specs-apply.ts:297 whole-block replace with no scenario merge), traces the root cause to source, and lays out three fix options (A fingerprint gating, B scenario-level merge, C phased). Analysis and design only; no code change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(templates): let plugin overlays drive apply/verify, drop fork-only run/gate opsx 簡化 P4:把 base workflow template 從「硬 wire fork pipeline」改成 「可被 plugin overlay 接管」,讓 overlay (append-only) 能可靠 redirect 到 Claude Code Workflow 扇出。 verify-change.ts: - step 4 移除 `STOP HERE` 終止語意 + schema-branch;改成早處前指 「plugin overlay takes precedence — 若下方 overlay 定義執行(如 workflow), follow it and skip default steps 5+」。解決 append-only overlay 無法中和 「更早出現的終止指令」的根本問題 (agent 由上往下讀,step 4 就被導向 overlay)。 - 移除 Output Format 的 `openspec run start/complete --phase verify` 引用。 apply-change.ts: - 移除 guidelines 的 `openspec run start/complete` (apply.gates) + `openspec gate resolve` 兩條 fork-only bullet。 兩 template 各有 skill/command 兩份副本,均同步修改。 Constraint: plugin overlay 只支援 append (loader 無 prepend/replace) → base 必須在早處主動前指 overlay,否則 overlay 永遠被 base 的早期指令蓋過 Rejected: 只在 overlay 加 supersede 段 | codex 兩輪確認 fragile,supersede 出現在 base STOP 之後,agent 可能先停 Confidence: high Scope-risk: moderate Reversibility: clean Directive: 此 fork 的全域 CLI 是 npm-link,改 src 後須 `pnpm build` 才生效;dist 為 gitignored 不入 commit。schema verify.steps 的執行已由 workflow+hook 取代,base 不再 honor (no-overlay 情境 fall through 到 default 三維) Tested: pnpm build OK; openspec update --force 重新合成 .claude/commands/opsx/verify.md 無 STOP/run/gate 殘留、base step 4 前指 overlay、overlay 驅動 opsx-verify-dimensions workflow;codex dual-review 判 order 問題已解 (PASS) Not-tested: apply overlay 端到端 (P3b-apply 待做);其他非本專案 repo 使用此 fork CLI 的回歸 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`loadTemplate` always treated an artifact's `template` field as a filename resolved under `schemas/<name>/templates/`. The odoo-trivial schema (alone among the plugin schemas) defines `template` as inline YAML literal-block content, so the whole block was used as a path and `instructions memo` failed with "Template not found: .../templates/## Memo...". The `instruction` field was already used inline; `template` now matches. loadTemplate now distinguishes by shape: a single-line, path+extension string is loaded from disk (missing files still raise, so typos are not silently swallowed); anything else is returned verbatim as inline content. Constraint: filename-shaped templates must keep raising on missing files — typos must not degrade to silent inline content Rejected: externalize odoo-trivial's memo template to templates/memo.md | fixes one schema but leaves the loader brittle for any inline-template author Confidence: high Scope-risk: narrow Reversibility: clean Tested: isolated odoo-trivial repro (json + text modes) now resolves; odoo-sdd proposal still loads from disk; instruction-loader.test.ts 41 passed (3 new inline cases) Not-tested: full fork suite — 9 pre-existing skill-templates-parity failures are unrelated (apply-change.ts WIP, confirmed on stashed baseline) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…etion) P4 (#15) 把 verify step 4 改成前指 plugin overlay,但 apply step 6 的等價前指 當初只在 working tree、未 commit,於 fork main 同步時遺失。補回:apply base step 6 加「plugin overlay takes precedence — 若下方 overlay 定義 orchestration (如 workflow fan-out),follow that overlay instead of this inline loop」,與 verify 一致,讓 P3b apply overlay 的 workflow 接管在 base 端也有強化前指。 Constraint: apply base 無 STOP HERE,order 風險較 verify 輕,但為一致性與 reinforcement 補上 Confidence: high Scope-risk: narrow Reversibility: clean Tested: pnpm build 後 openspec update --force 合成 apply.md base step 6 含前指 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…12) Brings upstream v1.3.0→v1.3.1 (14 commits) + workspace foundation on top of the opsx-simplification work (P4 + P3b overlays + schema fixes). Only file overlap was instruction-loader.ts (git auto-merge). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v1.3.1 sync 帶入 skill-templates-parity 快照測試,其 baseline hash 與 fork 客製 template 不符:apply/verify/archive-change template 因 opsx P4(overlay-precedence 前指 + 移除 run/gate)與 fork archive 改動而內容變。更新 9 個 expected hash (6 function + 3 generated-content)到 fork 實際輸出。benign 快照更新,非 v1.3.1 破壞(generateSkillContent 正常運作、只是內容不同)。 Tested: pnpm test → 90 files / 1722 tests all pass (was 9 fail) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… opsx) Upgrade fork v1.3.1 → v1.4.1 (24 upstream commits / 247 files): multi-repo workspace + initiative + context-store system, planning-home abstraction, change metadata enrichment (goal/affected_areas/initiative), Kimi/Mistral tools, sync core profile, spec-delta-merge hardening. 11 conflicts resolved in parallel (workflow), preserving BOTH upstream v1.4.1 AND fork customizations (opsx overlay-precedence templates, run/gate/pipeline/ waiver, plugin overlays, inline-template instruction-loader). Follow-up fixes: - re-add fork `class` field to ChangeMetadata schema (change-metadata/schema.ts) — upstream moved metadata schema; runner.ts gate-profile reads metadata.class - widen skill-templates-parity types to SkillTemplate | CommandTemplate - regenerate 33 parity hashes for merged template content Constraint: parallel conflict agents can't see each other → cross-file gaps fixed by main agent (class field, parity types) after tsc Confidence: medium Scope-risk: wide (247-file upstream merge) Tested: pnpm build OK; src tsc 0 errors; parity test 35/35 Not-tested: 12 functional tests (workspace/initiative/artifact-workflow/command-registry) still failing — under isolation vs pure v1.4.1 to separate merge-breakage from sandbox-env/upstream Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Post-merge fixes so the v1.4.1 fork integration passes the full suite. Pure
v1.4.1 passed all these tests; the failures were fork-customization gaps newly
surfaced by v1.4.1's tests (isolated via a v1.4.1 worktree baseline).
Real source fixes (regressions from the parallel conflict resolution):
- src/utils/change-metadata.ts: resolveSchemaForChange wrapped the metadata read
in a swallowing try/catch → ChangeMetadataError no longer propagated. Removed
the catch to restore v1.4.1's "throw when metadata exists but unreadable".
- openspec/specs/cli-update/spec.md: the fork's "Plugin overlay injection" was
resolved under `## Edge Cases` → v1.4.1's stricter source-spec normalization
flagged it as a hidden requirement. Relocated above `## Edge Cases`.
- src/core/completions/command-registry.ts: register fork commands missing from
the completions registry that v1.4.1's command-registry parity test walks —
gate(check/resolve), run(start/complete), waiver(list), plugin(list/info),
plus instructions --subagents/--teams/--sequential and new-change --class.
Test-expectation updates (fork's legitimate supersets the upstream tests missed):
- test/core/completions/command-registry.test.ts: add 'class' to new-change flags.
- test/commands/workspace.{test,interactive.test}.ts: add 'verify' to core
workflow expectations — the fork intentionally added verify to CORE_WORKFLOWS
(profiles.ts) and already updated 87 other tests; these 2 were missed.
Tested: pnpm build OK; src tsc 0 errors; pnpm test → 108 files / 1948 tests all pass
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Classified all commits ahead of upstream: 7 upstreamable (incl. the changesDir/split-brain workspace fix), 16 core plugin/gate/pipeline engine (fork's raison d'être pending an upstream RFC), 5 movable to odoo-claude-code bundled schemas, 12 merge noise. Convergence order: O → U → K-RFC; fork either retires (RFC accepted) or shrinks to a 16-commit thin patch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…homes The v1.4.1 planning-home merge hardcoded openspec/changes in repoPlanningHome() while the legacy getChangesDir() path (run, validate, archive, gate, list) reads changesDir from openspec/config.yaml. Any project with a configured changesDir got a split brain: `new` created changes in a place `run` could not see (hit twice in production use on 2026-07-08 — `openspec run --phase apply` listed only vault changes and could not find the change `new` had just created). repoPlanningHome() now resolves the same config: changesDir joins onto the repo root, and the configured schema becomes the repo default (previously `new` without --schema silently fell back to spec-driven even when config said otherwise). Unreadable config falls back to the old defaults, and workspace planning homes are untouched. Verified live against the odoo18ee project: `new` lands in the vault changesDir with schema odoo-sdd, `run start` immediately finds it, and a worktree with a config lacking changesDir still resolves branch-local. Full suite: 108 files / 1950 tests green (2 new). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (142)
📝 WalkthroughWalkthroughThis PR introduces an OpenSpec plugin system (manifests, hooks, gates, config, skill overlays), an orchestration engine for parallel task/gate/hook execution, deterministic gate checking with a pipeline runner and lock, new CLI commands (plugin, gate, run, waiver), config-driven changes-directory resolution, new Odoo workflow schemas, and extensive proposal/spec documentation. ChangesPlugin System, Orchestration & Gate Pipeline
Documentation, Proposals & Odoo Schemas
Estimated code review effort: 5 (Critical) | ~150 minutes Possibly related issues
Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Closing — this fix depends on the fork-only |
問題(split-brain,v1.4.1 merge 引入)
fork 同時存在兩套 changes 解析:
getChangesDir()changesDir(vault)resolveCurrentPlanningHomeSync()openspec/changes(repo-local)實際症狀(2026-07-08 兩度發生):
openspec new建的 change,openspec run --phase apply完全看不到(只列 vault changes)。修法
repoPlanningHome()改讀openspec/config.yaml:changesDir→ join 到 repo root(與getChangesDir()行為一致)schema→ 成為 repo default schema(原本new不加--schema一律 fallbackspec-driven,無視 config)驗證
new→ vault +odoo-sdd;run start立即找到;worktree(config 無 changesDir)仍解析 branch-local對應收斂計畫(docs/upstream-convergence-plan.md)U 類 — 此修法屬 upstream workspace PR 的候選內容。
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes