Skip to content

fix(planning-home): honor config.yaml changesDir and schema for repo homes - #1320

Closed
stanleykao72 wants to merge 42 commits into
Fission-AI:mainfrom
stanleykao72:fix/planning-home-honors-changesdir
Closed

fix(planning-home): honor config.yaml changesDir and schema for repo homes#1320
stanleykao72 wants to merge 42 commits into
Fission-AI:mainfrom
stanleykao72:fix/planning-home-honors-changesdir

Conversation

@stanleykao72

@stanleykao72 stanleykao72 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

問題(split-brain,v1.4.1 merge 引入)

fork 同時存在兩套 changes 解析:

路徑 使用者 解析到
getChangesDir() run / validate / archive / gate / list / specs-apply config changesDir(vault)
v1.4.1 resolveCurrentPlanningHomeSync() new / status / instructions / workflow hardcode 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 一律 fallback spec-driven,無視 config)
  • config 不存在/讀取失敗 → 舊預設,workspace planning home 不受影響

驗證

  • 108 files / 1950 tests 全綠(新增 2 個:config 尊重 + 無 config fallback)
  • Live 驗證於 odoo18ee 專案:根目錄 new → vault + odoo-sddrun start 立即找到;worktree(config 無 changesDir)仍解析 branch-local

對應收斂計畫(docs/upstream-convergence-plan.md)U 類 — 此修法屬 upstream workspace PR 的候選內容。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added plugin support with new commands to list and inspect plugins.
    • Introduced orchestration controls for workflow execution, including parallel task and gate handling.
    • Added new workflow commands for gate checks, run/start-complete, and waiver listing.
    • Expanded update behavior to include plugin-provided overlays in generated content.
  • Bug Fixes

    • Improved archive and validation flows to respect configured project paths and plugin-aware schema resolution.
    • Added stronger handling for lock, gate, and review outputs to keep runs more consistent.

stanleykao72 and others added 30 commits April 13, 2026 14:25
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
stanleykao72 and others added 12 commits May 6, 2026 08:44
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>
@stanleykao72
stanleykao72 requested a review from TabishB as a code owner July 8, 2026 01:09
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bc81b986-5b05-47a6-9d8f-6e62b5bb74eb

📥 Commits

Reviewing files that changed from the base of the PR and between 8886e3a and 57464ef.

📒 Files selected for processing (142)
  • .gitignore
  • README.md
  • docs/rfc-parallel-archive-merge.md
  • docs/upstream-convergence-plan.md
  • openspec/changes/add-plugin-system/.openspec.yaml
  • openspec/changes/add-plugin-system/design.md
  • openspec/changes/add-plugin-system/proposal.md
  • openspec/changes/add-plugin-system/specs/cli-archive/spec.md
  • openspec/changes/add-plugin-system/specs/config-loading/spec.md
  • openspec/changes/add-plugin-system/specs/plugin-cli/spec.md
  • openspec/changes/add-plugin-system/specs/plugin-config/spec.md
  • openspec/changes/add-plugin-system/specs/plugin-gates/spec.md
  • openspec/changes/add-plugin-system/specs/plugin-hooks/spec.md
  • openspec/changes/add-plugin-system/specs/plugin-loading/spec.md
  • openspec/changes/add-plugin-system/specs/plugin-schemas/spec.md
  • openspec/changes/add-plugin-system/specs/schema-resolution/spec.md
  • openspec/changes/add-plugin-system/tasks.md
  • openspec/changes/archive/2026-04-02-add-skill-overlays/.openspec.yaml
  • openspec/changes/archive/2026-04-02-add-skill-overlays/design.md
  • openspec/changes/archive/2026-04-02-add-skill-overlays/proposal.md
  • openspec/changes/archive/2026-04-02-add-skill-overlays/specs/cli-update/spec.md
  • openspec/changes/archive/2026-04-02-add-skill-overlays/specs/config-loading/spec.md
  • openspec/changes/archive/2026-04-02-add-skill-overlays/specs/skill-overlay-cli/spec.md
  • openspec/changes/archive/2026-04-02-add-skill-overlays/specs/skill-overlay-injection/spec.md
  • openspec/changes/archive/2026-04-02-add-skill-overlays/specs/skill-overlay-manifest/spec.md
  • openspec/changes/archive/2026-04-02-add-skill-overlays/tasks.md
  • openspec/changes/orchestration-and-review/.openspec.yaml
  • openspec/changes/orchestration-and-review/design.md
  • openspec/changes/orchestration-and-review/proposal.md
  • openspec/changes/orchestration-and-review/specs/alignment-check-gate/spec.md
  • openspec/changes/orchestration-and-review/specs/codex-review-skill/spec.md
  • openspec/changes/orchestration-and-review/specs/dual-review-gate/spec.md
  • openspec/changes/orchestration-and-review/specs/orchestration-hints/spec.md
  • openspec/changes/orchestration-and-review/specs/parallel-dispatch/spec.md
  • openspec/changes/orchestration-and-review/tasks.md
  • openspec/changes/upstream-contribution/.openspec.yaml
  • openspec/changes/upstream-contribution/design.md
  • openspec/changes/upstream-contribution/proposal.md
  • openspec/changes/upstream-contribution/tasks.md
  • openspec/specs/cli-update/spec.md
  • openspec/specs/config-loading/spec.md
  • openspec/specs/skill-overlay-cli/spec.md
  • openspec/specs/skill-overlay-injection/spec.md
  • openspec/specs/skill-overlay-manifest/spec.md
  • schemas/odoo-sdd/schema.yaml
  • schemas/odoo-sdd/templates/design.md
  • schemas/odoo-sdd/templates/proposal.md
  • schemas/odoo-sdd/templates/spec.md
  • schemas/odoo-sdd/templates/tasks.md
  • schemas/odoo-workflow/lifecycle/archive.yaml
  • schemas/odoo-workflow/lifecycle/verify.yaml
  • schemas/odoo-workflow/schema.yaml
  • schemas/odoo-workflow/templates/proposal.md
  • schemas/odoo-workflow/templates/spec.md
  • schemas/odoo-workflow/templates/tasks.md
  • schemas/spec-driven/templates/design.md
  • schemas/spec-driven/templates/tasks.md
  • src/cli/index.ts
  • src/commands/change.ts
  • src/commands/gate.ts
  • src/commands/plugin.ts
  • src/commands/run.ts
  • src/commands/schema.ts
  • src/commands/validate.ts
  • src/commands/workflow/instructions.ts
  • src/commands/workflow/new-change.ts
  • src/commands/workflow/schemas.ts
  • src/commands/workflow/shared.ts
  • src/commands/workflow/templates.ts
  • src/core/archive.ts
  • src/core/artifact-graph/index.ts
  • src/core/artifact-graph/instruction-loader.ts
  • src/core/artifact-graph/resolver.ts
  • src/core/artifact-graph/types.ts
  • src/core/change-metadata/schema.ts
  • src/core/completions/command-registry.ts
  • src/core/covers/extractor.ts
  • src/core/covers/injector.ts
  • src/core/list.ts
  • src/core/orchestration/domain-parser.ts
  • src/core/orchestration/group-builder.ts
  • src/core/orchestration/index.ts
  • src/core/orchestration/resolver.ts
  • src/core/orchestration/types.ts
  • src/core/pipeline/index.ts
  • src/core/pipeline/lock.ts
  • src/core/pipeline/runner.ts
  • src/core/pipeline/types.ts
  • src/core/planning-home.ts
  • src/core/plugin/config-validator.ts
  • src/core/plugin/context.ts
  • src/core/plugin/hook-dispatcher.ts
  • src/core/plugin/index.ts
  • src/core/plugin/loader.ts
  • src/core/plugin/types.ts
  • src/core/profiles.ts
  • src/core/project-config.ts
  • src/core/shared/index.ts
  • src/core/shared/skill-generation.ts
  • src/core/specs-apply.ts
  • src/core/templates/workflows/apply-change.ts
  • src/core/templates/workflows/archive-change.ts
  • src/core/templates/workflows/propose.ts
  • src/core/templates/workflows/verify-change.ts
  • src/core/update.ts
  • src/core/validation/gate-checker.ts
  • src/core/waiver.ts
  • src/utils/change-metadata.ts
  • src/utils/change-utils.ts
  • src/utils/item-discovery.ts
  • test/commands/config-profile.test.ts
  • test/commands/config.test.ts
  • test/commands/gate-exit-code.test.ts
  • test/commands/gate-instructions.test.ts
  • test/commands/gate-resolve.test.ts
  • test/commands/workspace.interactive.test.ts
  • test/commands/workspace.test.ts
  • test/core/artifact-graph/gate-schema.test.ts
  • test/core/artifact-graph/instruction-loader.test.ts
  • test/core/completions/command-registry.test.ts
  • test/core/completions/installers/zsh-installer.test.ts
  • test/core/init.test.ts
  • test/core/orchestration/domain-parser.test.ts
  • test/core/orchestration/group-builder.test.ts
  • test/core/orchestration/instructions-integration.test.ts
  • test/core/orchestration/parallel-gates.test.ts
  • test/core/orchestration/parallel-hooks.test.ts
  • test/core/orchestration/resolver.test.ts
  • test/core/planning-home.test.ts
  • test/core/plugin/config-validator.test.ts
  • test/core/plugin/hook-dispatcher.test.ts
  • test/core/plugin/loader.test.ts
  • test/core/plugin/types.test.ts
  • test/core/profiles.test.ts
  • test/core/shared/skill-generation.test.ts
  • test/core/templates/skill-templates-parity.test.ts
  • test/core/update.test.ts
  • test/core/validation/gate-checker.test.ts
  • test/core/validation/gate-fingerprint.test.ts
  • test/core/validation/tdd-markers-skip.test.ts
  • test/pipeline/lock.test.ts
  • test/pipeline/runner.test.ts

📝 Walkthrough

Walkthrough

This 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.

Changes

Plugin System, Orchestration & Gate Pipeline

Layer / File(s) Summary
Plugin manifest, loader, config validation, hook dispatch
src/core/plugin/*, test/core/plugin/*
New plugin.yaml manifest schema, three-tier resolution/loading, config validation/env flattening, cached plugin context, and sequential/parallel hook dispatch.
Plugin-aware schema/artifact-graph resolution
src/core/artifact-graph/*, src/commands/schema.ts, src/commands/workflow/schemas.ts, src/commands/workflow/templates.ts, src/utils/change-metadata.ts
Extends gate/step/orchestration schema types and schema resolution/listing to include plugin-provided schemas.
Orchestration engine
src/core/orchestration/*, src/core/covers/*, src/commands/workflow/instructions.ts
Parses task groups/domain tags from tasks.md, resolves plugin/schema orchestration, and injects covers/orchestration hints into apply instructions.
Gate checking and pipeline run/lock
src/core/validation/gate-checker.ts, src/core/pipeline/*, src/core/waiver.ts
Deterministic gate checks with fingerprinting, parallel execution/persistence, plugin gate delegation, session locking, and PipelineRunner start/complete flows.
CLI commands: gate, run, plugin, config plumbing
src/commands/gate.ts, src/commands/run.ts, src/commands/plugin.ts, src/cli/index.ts, src/commands/change.ts, src/commands/validate.ts, src/core/project-config.ts, src/utils/change-utils.ts, ...
New CLI command groups, config-driven getChangesDir, and extended project config for plugins/changesDir.
Archive/update hook and skill overlay integration
src/core/archive.ts, src/core/update.ts, src/core/templates/workflows/*
Dispatches archive hooks and applies plugin skill overlays during update/skill generation.
Add verify workflow to core profile
src/core/profiles.ts, test/*
Adds verify to CORE_WORKFLOWS with corresponding test updates.

Documentation, Proposals & Odoo Schemas

Layer / File(s) Summary
README and repo docs
README.md, docs/*, .gitignore
Documents plugins/orchestration and adds RFC/upstream-convergence planning docs.
OpenSpec change proposals
openspec/changes/*
Proposal/design/tasks/spec docs for plugin system, skill overlays, orchestration-and-review, and upstream-contribution.
openspec/specs requirement updates
openspec/specs/*
Requirement docs for overlay injection and config-loading deferral.
Odoo SDD and workflow schemas/templates
schemas/odoo-sdd/*, schemas/odoo-workflow/*, schemas/spec-driven/templates/*
New Odoo delivery-pipeline and workflow schemas with templates.

Estimated code review effort: 5 (Critical) | ~150 minutes

Possibly related issues

Possibly related PRs

  • Fission-AI/OpenSpec#411: Both extend src/core/artifact-graph/resolver.ts schema resolution logic and SchemaInfo.source handling.
  • Fission-AI/OpenSpec#499: Extends the openspec/config.yaml project-config system with plugin-related fields and wiring.
  • Fission-AI/OpenSpec#522: Both modify getSchemaDir/resolveSchema/listSchemas* in the resolver for different schema sources.

Poem

  • A rabbit hopped through plugin gates,
  • Hooks and gates it orchestrates,
  • Tasks in groups run side by side,
  • Waivers, locks, and runs allied,
  • Odoo schemas join the show —
  • One big burrow, watch it grow! 🐇
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix/planning-home-honors-changesdir

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@stanleykao72

Copy link
Copy Markdown
Contributor Author

Closing — this fix depends on the fork-only changesDir config field and doesn't apply standalone to upstream. Will be included in a complete workspace-config RFC/PR later. Apologies for the noise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant