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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openspec/changes/upstream-contribution/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-13
155 changes: 155 additions & 0 deletions openspec/changes/upstream-contribution/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Design: Upstream Contribution Strategy

## Architecture Decisions

### AD-1: contextFiles type adaptation (v1.3.0)

Upstream changed `ApplyInstructions.contextFiles` from `Record<string, string>` to `Record<string, string[]>` to support glob artifact outputs.

**Impact on fork code:**
- `src/core/pipeline/runner.ts` — reads contextFiles for gate synthesis context
- `src/core/orchestration/resolver.ts` — reads contextFiles for task grouping
- `src/commands/workflow/instructions.ts` — covers injection reads contextFiles

**Resolution:** Handled during rebase (2026-04-13). All fork code now treats contextFiles values as `string[]`. The rebase was clean — auto-merge succeeded for `shared.ts` type change.

### AD-2: update.ts transformer composition

Fork adds `composeTransformers(overlayTransformer, toolTransformer)` pattern. Upstream added `pi` tool to the hyphen-command condition.

**Resolution:** Merged both — `pi` added to condition, overlay composition preserved:
```typescript
const toolTransformer = (tool.value === 'opencode' || tool.value === 'pi')
? transformToHyphenCommands : undefined;
const transformer = composeTransformers(overlayTransformer, toolTransformer);
```

### AD-5: Workspace foundation impact (added 2026-05-04)

Upstream merged `workspace-foundation` (PR #1045, archived as canonical spec) on 2026-05-04. This introduces a cross-repo planning model: workspaces live at `<global-data-dir>/workspaces/<name>/`, link multiple repos via stable names, and own `changes/` at the workspace root.

Six slices are planned (1+2 landed, 3-6 proposed):

| Slice | Status | Surface that conflicts with our PRs |
|-------|--------|-------------------------------------|
| `workspace-foundation` | landed | `instructions.ts`, `templates.ts`, `instruction-loader.ts`, `profiles.ts` — already merged into fork via sync/upstream-v1.3.1 |
| `workspace-create-and-register-repos` | landed (CLI beta) | Setup CLI surface — no overlap with our PRs |
| `workspace-open-agent-context` | proposed | Context injection — overlaps T1's plugin-loaded skill content |
| `workspace-change-planning` | proposed | New change creation — neutral |
| `workspace-apply-repo-slice` | proposed | **`apply` redefined as repo-slice implementation** — directly conflicts with T4's `openspec run start/complete` model |
| `workspace-verify-and-archive` | proposed | **verify/archive at workspace + repo level** — directly conflicts with T2's phase extension model |

**Strategic implications:**

1. **T1 (Plugin Foundation)** — surface already churned by foundation slice. Rebase will be expensive but achievable. Submit early before slice 3 lands and adds another layer.

2. **T2 (Workflow Phases)** — verify/archive phase types we want to add will likely be redefined by slice 6. Two paths:
- (a) Submit T2 anyway, position as "phase machinery that slice 6 can build on"
- (b) Wait for slice 6, then merge our verify/archive intent into the workspace model
- Default: (b) — saves rework, signals respect for upstream direction.

3. **T4 (Pipeline Runner)** — `apply` semantics redefined by slice 5. `openspec run start/complete` would need to know whether it's running on a workspace change or a repo-local change. Defer until slice 5 stabilizes.

4. **T3 (Orchestration Hints)** — workspace-neutral; flags affect agent dispatch regardless of change scope. Lower-risk; can ship after T1.

5. **T5 (Fingerprinting)** — gate-checker internal, no workspace coupling. Independent.

**CORE_WORKFLOWS union** (sync/upstream-v1.3.1 merge resolution): both `verify` (fork) and `sync` (upstream workspace) are now default-active. T2 PR upstream must reckon with this — either remove `verify` from CORE if upstream prefers minimal default, or argue for keeping both. This is a foreseeable point of friction.

### AD-3: Odoo-specific content exclusion

The following content exists in the fork but MUST NOT be included in any upstream PR:

| Content | Location | Reason |
|---------|----------|--------|
| `schemas/odoo-sdd/` | Deleted from fork, lives in odoo-claude-code | Domain-specific |
| `schemas/odoo-workflow/` | Deleted from fork, lives in odoo-claude-code | Domain-specific |
| Odoo change proposals | `openspec/changes/` | Project-specific |
| `openspec-parallel-merge-plan.md` | Root | Fork-specific planning doc |

### AD-4: PR dependency chain

```
T0 (icebreaker) ── no code dependency
T1 (plugin foundation)
│ exports: PluginManifest, PluginLoader, HookDispatcher, ConfigValidator
│ new CLI: openspec plugin list|info
├── T2 (workflow phases) ── depends on T1 schema types
│ extends: SchemaYaml with verify/archive phases
├── T3 (orchestration) ── depends on T1 plugin loader
│ new CLI flags: --subagents, --teams, --sequential
│ new module: src/core/orchestration/
│ └── T4 (pipeline runner) ── depends on T1 + T3
│ new CLI: openspec run, openspec gate
│ new module: src/core/pipeline/
└── T5 (fingerprinting) ── weak dependency on T4 gate-checker
extends: gate-checker with content fingerprints
```

## Commit-to-PR Mapping

### T1: Plugin Foundation
| Fork Commit | Description |
|-------------|-------------|
| `a3a0270` | Plugin system core (loader, hooks, config, gates, schemas) |
| `a037ec5` | Skill overlays injection |
| `6ba2731` | README plugin documentation |
| `354c7f2` | Archive add-skill-overlays change |
| `fbec042` | Fix plugin-provided schema resolution |
| `9446dbd` | Fix loadTemplate plugin schema resolution |

### T2: Workflow Phase Extension
| Fork Commit | Description |
|-------------|-------------|
| `11c22d2` | Configurable changesDir |
| `63cae69` | Verify and archive phase schema support |

### T3: Orchestration Hints
| Fork Commit | Description |
|-------------|-------------|
| `34af9ac` | CLI-native orchestration hints |
| `c552889` | Schema default_mode and --sequential flag |

### T4: Pipeline Runner
| Fork Commit | Description |
|-------------|-------------|
| `a324c3c` | Pipeline runner (runner, lock, types) |
| `5e0c7db` | Fix hook command CWD resolution |
| `df81ea0` | Covers auto-injection, change class routing |

### T5: Fingerprinting
| Fork Commit | Description |
|-------------|-------------|
| `375ce99` | Content-based fingerprinting for gate staleness |

### Not included in any PR (Odoo-specific or fork-only)
| Fork Commit | Description | Reason |
|-------------|-------------|--------|
| `acea753` | odoo-workflow schema | Odoo-specific |
| `39f5636` | Lifecycle addon for odoo-workflow | Odoo-specific |
| `c0f249b` | Align odoo-sdd schemas | Odoo-specific |
| `1b0cc82` | Schema-level quality gates + odoo-sdd | Mixed (gates go in T1, odoo-sdd stays) |
| `4c762cc` | 63 tests for gates | Goes with T1/T4 |
| `9b3818e` | Test fixes for verify addition | Goes with T2 |
| `13bb4e9` | ZshInstaller test isolation | Goes with T1 |
| `22dde36` | Strengthen spec template format | Goes with T2 |
| `778f1a5` | Ignore .actrc | Already in upstream via rebase |
| `2c92b77` | Remove Odoo plugins from dev config | Fork cleanup |

## Per-PR Checklist

For each PR before submission:

1. [ ] Create branch from latest upstream/main
2. [ ] Cherry-pick relevant commits
3. [ ] Remove any Odoo-specific content that leaked in
4. [ ] Ensure all new exports are properly typed
5. [ ] Run `npm run build` — clean compile
6. [ ] Run `npx vitest run` — only pre-existing failures allowed
7. [ ] Write PR description with context for upstream reviewers
8. [ ] Cross-reference any relevant upstream issues (#879, #920, etc.)
64 changes: 64 additions & 0 deletions openspec/changes/upstream-contribution/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Upstream Contribution: Plugin System & Orchestration Platform

## Problem

OpenSpec is currently a static spec-driven development tool. It generates instruction files and manages change artifacts, but lacks:

1. **Extensibility** — No way for teams to add custom lifecycle hooks, quality gates, or domain-specific schemas without forking
2. **Quality assurance** — No automated validation that artifacts (proposal, specs, design, tasks) are aligned and traceable
3. **Orchestration** — No mechanism to express parallel/sequential execution preferences for multi-agent workflows
4. **Pipeline execution** — No runtime for automatically executing gates and hooks at lifecycle boundaries

This fork has developed and production-tested these capabilities over 3 months of daily use in an Odoo 18 Enterprise development environment.

## Proposed Solution

Contribute the fork's 25 commits to upstream Fission-AI/OpenSpec as 5 sequential PRs, preceded by a Phase 0 icebreaker engagement. Each PR builds on the previous, and we wait for merge before opening the next.

### PR Sequence (revised 2026-05-04 after workspace foundation landed)

Upstream has shifted priority to a **cross-repo workspace model** (workspace-foundation merged in PR #1045 on 2026-05-04). Workspace slice 3–6 proposals overlap with our T2/T4 surface area. The original sequential plan is preserved below for context, but execution order and risk have been reassessed.

| PR | Name | New order | Risk | Workspace overlap |
|----|------|-----------|------|-------------------|
| T0 | Icebreaker | DONE (PR #891 comment, TabishB ack 04-13, then 21+ days silent) | — | n/a |
| **T1** | Plugin Foundation | **submit first** | **HIGH** (was MEDIUM) | Touches `init.ts/templates.ts/instructions.ts` — same surface workspace-foundation just refactored |
| **T5** | Fingerprinting | **submit in parallel with T1** | LOW | None — gate-checker internal |
| **T3** | Orchestration Hints | submit after T1 lands | LOW (was MEDIUM) | Cross-cutting, workspace-neutral |
| T2 | Workflow Phase Extension (verify/archive) | **defer or reframe** | MEDIUM | **Direct overlap** with `workspace-verify-and-archive` slice 6 (proposed). Either reframe as "phase mechanism for slice 6" or fold in. |
| T4 | Pipeline Runner | **defer until slice 5 lands** | HIGH | **Direct overlap** with `workspace-apply-repo-slice` slice 5 (proposed). `apply` semantics being redefined per repo-slice; T4's `openspec run start/complete` would need workspace-awareness. |

**Why this order**: T1 + T5 + T3 ship the broad-utility primitives; T2/T4 are deferred until upstream commits to a workspace-friendly seam, otherwise we waste rebase effort fighting the wrong abstraction.

### What stays internal (NOT contributed)

- Odoo-specific schemas (odoo-sdd, odoo-bugfix, odoo-trivial, odoo-refactor)
- alignment-check, dual-review, code-quality plugins (kept as independent examples)
- Obsidian vault sync hooks
- Git branch/worktree policy hooks

## Success Criteria

- All 5 PRs merged into Fission-AI/OpenSpec main
- Upstream tests pass (excluding pre-existing `@inquirer/core` issue)
- No Odoo-specific code in upstream
- Plugin system documented in upstream README

## Constraints

- Conservative strategy: one PR at a time, wait for merge
- Each PR must rebase onto latest upstream/main (which includes previous merged PR)
- Upstream maintainer (TabishB) has ~24-48h review turnaround
- Estimated total timeline: 3-6 weeks
- `contextFiles` type changed from `string` to `string[]` in v1.3.0 — all fork code adapted during rebase

## Risks

| Risk | Mitigation |
|------|-----------|
| Upstream rejects plugin architecture | Phase 0 done (TabishB ack 04-13); silence since then is risk indicator — push T1 to force a review |
| Workspace path eats T2/T4 surface | Defer T2/T4; reframe as workspace-aware after slice 5/6 stabilize |
| API changes requested after PR1 | Each subsequent PR rebases from merged upstream, adapts as needed |
| Long review cycles | Work on other projects during wait; conservative strategy reduces rework |
| Workspace foundation blocks plugin auto-discovery for cross-repo | T1 must explicitly state "plugin-foundation is repo-local; workspace-level plugins are out of scope here" |
| Maintainer attention saturated by workspace path | Submit T1 + T5 with explicit "complementary, not competing" framing; reference slice 1/2 architecture in PR body |
97 changes: 97 additions & 0 deletions openspec/changes/upstream-contribution/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Tasks: Upstream Contribution

## 0. Icebreaker — Establish trust with upstream maintainer

- [x] Review open P0 issues (#879, #881, #920) and identify one where plugin system insight is relevant
- [x] Leave a thoughtful comment explaining how the fork's plugin architecture addresses the issue
- Posted on PR #891: https://github.com/Fission-AI/OpenSpec/pull/891#issuecomment-4234369497
- Connected to TabishB's "unify-template-generation-pipeline" vision
- [x] Maintainer ack — 2026-04-13: TabishB replied "definitely be interested, let me take a look and get back to you"
- [x] **Status (2026-05-04)**: 21 days silence. TabishB's attention shifted to workspace foundation (PR #1045 merged 05-04). Treat as **stalled, not negative** — push forward with T1 to force review.

## 0.5. Sync upstream/main into fork (2026-05-04)

- [x] Merge `upstream/main` into `sync/upstream-v1.3.1` branch
- 9 conflict files, 32 hunks; 4 real semantic decisions (CORE_WORKFLOWS union, instruction-loader nesting, etc.)
- [x] All tests green: 1719/1719
- [x] PR opened: https://github.com/stanleykao72/OpenSpec/pull/12
- [x] Update this umbrella with workspace-aware revisions (this commit)

## 1. PR: Plugin Foundation (T1) — submit FIRST

Commits: a3a0270, a037ec5, 6ba2731, 354c7f2, fbec042, 9446dbd

**Risk: HIGH** — surface area was just refactored by workspace-foundation (PR #1045). Rebase from latest upstream/main (after #1045 merge) and expect conflict resolution work in `init.ts/templates.ts/instructions.ts/instruction-loader.ts`. Reference sync/upstream-v1.3.1 PR #12 in fork as proof-of-concept that conflicts are tractable.

- [ ] Create branch `feat/plugin-system` from latest upstream/main (post-#1045)
- [ ] Cherry-pick and adapt commits (remove Odoo references)
- [ ] Verify: `src/core/plugin/` (types, loader, hook-dispatcher, config-validator, context)
- [ ] Verify: `src/commands/plugin.ts` (list, info subcommands)
- [ ] Verify: skill overlay injection in `src/core/update.ts`
- [ ] Verify: schema resolution supports plugin-bundled schemas
- [ ] Include `schemas/spec-driven/schema.yaml` as default example
- [ ] PR body: cite sync PR #12 conflict resolution; explicitly state "plugin-foundation is repo-local; workspace-level plugins are out of scope"
- [ ] Run build + tests
- [ ] `gh pr create -R Fission-AI/OpenSpec`
- [ ] Record PR URL: ___
- [ ] Track review feedback and iterate
- [ ] Merged: [ ]

## 2. PR: Fingerprinting & Staleness Detection (T5) — submit IN PARALLEL with T1

Commits: 375ce99

**Risk: LOW** — gate-checker internal, no workspace coupling. Submit in parallel with T1 (no dependency).

- [ ] Create branch `feat/gate-fingerprinting` from latest upstream/main
- [ ] Cherry-pick: content-based fingerprinting
- [ ] Verify: SHA256 fingerprinting of tracked artifacts
- [ ] Verify: stale gate detection in gate synthesis
- [ ] Run build + tests
- [ ] `gh pr create -R Fission-AI/OpenSpec`
- [ ] Record PR URL: ___
- [ ] Merged: [ ]

## 3. PR: Orchestration Hints (T3) — submit AFTER T1 lands

Commits: 34af9ac, c552889

**Risk: LOW** (downgraded from MEDIUM) — workspace-neutral cross-cutting flags.

- [ ] Rebase from upstream/main (now includes T1)
- [ ] Create branch `feat/orchestration-hints`
- [ ] Cherry-pick: CLI-native orchestration, default_mode, --sequential
- [ ] Verify: `src/core/orchestration/` (types, resolver, domain-parser, group-builder)
- [ ] Verify: --subagents, --teams, --sequential CLI flags
- [ ] Run build + tests
- [ ] `gh pr create -R Fission-AI/OpenSpec`
- [ ] Record PR URL: ___
- [ ] Merged: [ ]

## 4. PR: Workflow Phase Extension (T2) — DEFERRED

Commits: 11c22d2, 63cae69, 22dde36, 9b3818e

**Risk: MEDIUM** — overlaps with `workspace-verify-and-archive` slice 6 (proposed). Default plan: wait for slice 6 to land, then refactor T2 into workspace-aware verify/archive support OR fold our intent into upstream's design.

Decision gates before submitting:
- [ ] Has slice 6 (workspace-verify-and-archive) landed in upstream?
- If yes → re-pitch T2 as a workspace-aware addition (or skip if slice 6 covers our use case)
- If no after 60+ days → submit T2 anyway as "phase mechanism for slice 6"; cite slice 6 proposal in PR body
- [ ] CORE_WORKFLOWS friction: be ready to argue for keeping `verify` in CORE alongside upstream's `sync`

(Sub-tasks unchanged when execution time arrives — see prior section content.)

## 5. PR: Pipeline Runner + Gates/Hooks Execution (T4) — DEFERRED

Commits: a324c3c, 5e0c7db, df81ea0, 1b0cc82 (gates portion), 4c762cc, 13bb4e9

**Risk: HIGH** — `apply` semantics being redefined by slice 5 `workspace-apply-repo-slice` (proposed). `openspec run start/complete` must reckon with workspace vs repo-local change scope. Hard to ship before slice 5 lands.

Decision gates before submitting:
- [ ] Has slice 5 (workspace-apply-repo-slice) landed?
- If yes → refactor T4's runner to be workspace-aware; gate-checker reads from workspace `changes/` if applicable
- If no after 90+ days → submit T4 anyway as "pipeline mechanism for slice 5"; offer to add workspace-aware path in follow-up
- [ ] Verify gate-checker remains decoupled from `apply` semantics (so slice 5 doesn't force gate-checker rewrite)

(Sub-tasks unchanged when execution time arrives — see prior section content.)