openup-sync-spec

Back-propagate pure refactors to stale artifacts; classify the diff, refuse behaviour-changes, propose targeted edits for approval (read-only by default)

6 stars

Best use case

openup-sync-spec is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Back-propagate pure refactors to stale artifacts; classify the diff, refuse behaviour-changes, propose targeted edits for approval (read-only by default)

Teams using openup-sync-spec should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/openup-sync-spec/SKILL.md --create-dirs "https://raw.githubusercontent.com/GermanDZ/open-up-for-ai-agents/main/docs-eng-process/.claude-templates/skills/openup-sync-spec/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/openup-sync-spec/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How openup-sync-spec Compares

Feature / Agentopenup-sync-specStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Back-propagate pure refactors to stale artifacts; classify the diff, refuse behaviour-changes, propose targeted edits for approval (read-only by default)

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Sync Spec

Back-propagate **pure refactors** into the artifacts they touched. This skill is the
refactor-only half of the **"Fix the spec first"** rule: behaviour changes go
*spec-first* through the originating `/openup-create-*` skill; pure refactors go
*code-first* and then reconcile here. It diffs code against each artifact's
`last-synced` git ref, classifies the diff, and — **only** for refactor diffs —
proposes targeted section edits for the user to approve, then bumps the ref.

**This skill is READ-ONLY BY DEFAULT.** Steps 1–5 read and propose only. The single
write point (step 6) is gated on explicit user approval and executed by the
`openup-scribe` agent. It never regenerates a whole document and never auto-writes.

> **Refactor-only skill (`model: inherit`).** Classification needs judgment — unlike the
> mechanical readiness skill, this one reasons about whether a diff changes behaviour.
> When in doubt it **refuses** and routes spec-first. The cost asymmetry below is
> load-bearing: refusing a true refactor costs one re-run; silencing a behaviour change
> reintroduces exactly the drift this skill exists to prevent.

## Inputs

1. **Per-artifact baseline — `last-synced` front-matter.** Each of the four artifact
   types carries an optional `last-synced` key (full 40-char git SHA, or `""`). This is
   the diff base for that artifact. Empty / absent = **never synced**.
2. **The diff range.** `git diff <last-synced>..HEAD` per artifact, or the `since`
   argument if supplied (a git ref, or `"last commit"` → `HEAD~1..HEAD`).
3. **The artifacts themselves.** The four bounded types and their headings:
   `use-case-specification.md`, `architecture-notebook.md`, `iteration-plan.md`,
   `task-spec.md`. An unknown artifact type is reported and skipped, never guessed at.

## Diff classification (drop-in heuristic)

Run `git diff <last-synced>..HEAD` (use `--stat` first for the file map, then full
hunks for changed files). Classify the **whole diff** as **REFACTOR** only if
*every* hunk matches a refactor signal and *no* hunk matches a behaviour signal.
If any behaviour signal fires, or the diff is ambiguous, classify as
**BEHAVIOUR-CHANGE**. This asymmetry is intentional: refusing a true refactor costs
one re-run; mislabelling a behaviour change silences exactly the drift SPDD warns
against.

**REFACTOR signals (safe to back-propagate):**
- Symbol **rename** with all call sites updated in the same diff (identifier churn,
  no new branches).
- **Extract / inline** method or variable — same inputs/outputs, control flow
  preserved.
- **Move** a file/symbol across modules with no signature change (path churn only).
- **Formatting / whitespace / import reordering**; comment or docstring edits.
- Type-only annotations that do not change runtime behaviour.
- Test-only changes that track a rename (no new assertions on new behaviour).

**BEHAVIOUR-CHANGE signals (refuse — go spec-first):**
- **Public API signature change**: added/removed/reordered parameters, changed
  return type, changed exported/visibility surface, renamed *public* endpoint/route.
- **Business-logic / conditional change**: added or altered `if`/`switch`/loop
  conditions, changed constants/thresholds, new/removed early returns, changed error
  handling or validation rules.
- **Acceptance-criteria-affecting change**: anything that would alter what a use-case
  scenario, an iteration-plan objective, or a task-spec requirement asserts as the
  observable end state.
- **New or deleted feature surface**: new functions/endpoints/flags that did not
  exist at `last-synced`, or removed capability.
- **Data-shape / schema / contract change**: persisted format, serialized payload,
  config keys, migration.

**Ambiguity rule:** if a diff mixes refactor and behaviour hunks, or you cannot
confidently place a hunk, classify the **whole run** as BEHAVIOUR-CHANGE and refuse.
Do not partially sync a mixed diff.

## Process

Run this linear, read-only pipeline. Treat all four artifact types as candidates (or
the single type named by `artifact`); skip any whose `touches`/content is unrelated to
the diff.

### 1. Resolve baseline

Read each artifact's `last-synced`. If empty / absent → **never-synced handling**:
report `no baseline (last-synced unset) — set a baseline by approving the current HEAD
as the reference, or run the originating /openup-create-* skill` and take **no** edit
action unless the user explicitly asks to set the baseline to `HEAD`. Do not invent a
baseline or diff the whole history. Otherwise use the SHA (or the `since` argument) as
the diff base.

### 2. Diff

`git diff <last-synced>..HEAD` — `--stat` first for the file map, then full hunks for
the changed files.

### 3. Classify

Apply the **Diff classification heuristic** above. A **BEHAVIOUR-CHANGE** verdict
(including ambiguous) short-circuits the flow — **no** section detection, **no** edit
proposal, **no** scribe call, **no** `last-synced` bump. Emit the refusal (below) and
STOP for that run.

### 4. Detect stale sections (refactor only)

Build the set of changed **files and symbols** from the diff (renamed-from/to pairs,
moved paths, extracted names). A section is **likely stale** iff its prose names one of
those files or symbols — the *old* name on the left of a rename is the strongest
signal. Scope the match to the artifact's own headings. Report each candidate as:

```
<artifact> › <section heading> — names <symbol/file>, changed by <rename|move>
```

Sections that name nothing in the changed set are left **untouched**.

### 5. Propose targeted edits

For each stale section, draft the **minimal** edit (old symbol → new symbol, old path →
new path). Present all proposals across all artifacts as **one unified review block**
before any write. **Never regenerate a whole document; never auto-write.**

### 6. Apply on approval (write path)

Only after **explicit user approval**, delegate the writes to the **`openup-scribe`**
agent (Agent tool, `subagent_type: "openup-scribe"`) — the orchestrator decides the
values, the scribe only writes. The same approved batch applies the section edits
**and** bumps `last-synced` to the current `HEAD` SHA. One scribe brief per touched
artifact; the scribe reports the exact lines changed.

- The bump and the section edits are **one atomic, user-approved write per artifact** —
  never a silent or standalone bump.
- Bump `last-synced` **only** on artifacts whose edits were applied this run; never
  bump an artifact the user deferred (avoids divergent baselines on the next run).
- If the working tree is dirty/uncommitted, resolve `HEAD` after the user commits, or
  record the SHA the diff was computed against — never bump to a SHA the edits were not
  validated against.

> **Commit hygiene note.** The refactor-vs-behaviour split is only meaningful when
> refactors and behaviour changes land in *separate* commits/ranges. A mixed commit
> forces a whole-run refusal (correct, but blocking). Commit refactors separately so
> this skill can act on a clean range.

## Behaviour-change refusal (drop-in)

On BEHAVIOUR-CHANGE (including ambiguous), stop before any edit, name the offending
signal, and route the user to the originating skill. Never offer a "force / sync
anyway" escape hatch.

**Artifact → originating skill routing map:**

| Artifact | Originating skill |
|---|---|
| `use-case-specification.md` | `/openup-create-use-case` |
| `architecture-notebook.md` | `/openup-create-architecture-notebook` |
| `iteration-plan.md` | `/openup-create-iteration-plan` |
| `task-spec.md` | `/openup-create-task-spec` |

**Refusal message (print verbatim, filling in the concrete signal and file/symbol):**

> **`/openup-sync-spec` refused — this diff changes behaviour, not just structure.**
>
> `<last-synced>..HEAD` contains a behaviour signal: **`<signal name, e.g. "public
> API signature change in src/foo.py:bar()">`**. Back-propagation is only for pure
> refactors; a behaviour change must update the spec **first** (the "Fix the spec
> first" rule), then the code.
>
> Re-run the originating skill for each affected artifact, then bring the code in
> line:
> - use-case → `/openup-create-use-case`
> - architecture notebook → `/openup-create-architecture-notebook`
> - iteration plan → `/openup-create-iteration-plan`
> - task spec → `/openup-create-task-spec`
>
> If you believe this is genuinely a refactor, narrow the diff (commit the
> behaviour change separately) and re-run `/openup-sync-spec` on the
> refactor-only range.

The refusal always lists all four routes (the skill does not assume which artifact the
user cares about).

## Safeguards

- **Read-only by default.** Steps 1–5 read and propose only. The single write point is
  step 6, gated on explicit user approval and executed by the scribe.
- **Targeted, never wholesale.** No full-doc regeneration; edits are confined to
  flagged sections.
- **Bounded scope.** Only the four known artifact types
  (`use-case-specification`, `architecture-notebook`, `iteration-plan`, `task-spec`).
  An unknown artifact type is reported and skipped, not guessed at.
- **No false-positive silencing.** Ambiguous → BEHAVIOUR-CHANGE → refuse.

## Success Criteria

After this skill runs, ALL of these must be true:

- [ ] The diff was classified REFACTOR or BEHAVIOUR-CHANGE by the documented heuristic.
- [ ] A BEHAVIOUR-CHANGE (or ambiguous) verdict produced the refusal + routing and
      wrote nothing.
- [ ] For a REFACTOR, only sections naming changed files/symbols were flagged; no whole
      document was regenerated.
- [ ] No artifact was written without explicit user approval.
- [ ] `last-synced` was bumped to `HEAD` **only** on artifacts whose edits were applied
      this run, in the same approved scribe batch as the section edits.
- [ ] Never-synced artifacts were reported (no auto-edit) unless the user asked to set a
      baseline.

## See Also

- [openup-complete-task](../complete-task/SKILL.md) — closes the task whose code these
  artifacts describe; run sync-spec before completing if a refactor left specs stale
- [openup-readiness](../readiness/SKILL.md) — sibling read-only skill; reads the same
  change-folder frontmatter this skill keeps in sync
- `/openup-create-use-case`, `/openup-create-architecture-notebook`,
  `/openup-create-iteration-plan`, `/openup-create-task-spec` — the spec-first path for
  behaviour changes this skill refuses

Related Skills

openup-transition

6
from GermanDZ/open-up-for-ai-agents

Initialize and manage Transition phase activities - deploy to users

openup-tdd-workflow

6
from GermanDZ/open-up-for-ai-agents

Guide Test-Driven Development cycle adapted for AI agents with a pragmatic approach

openup-start-iteration

6
from GermanDZ/open-up-for-ai-agents

Begin a new OpenUP iteration with proper phase context and task selection

openup-shared-vision

6
from GermanDZ/open-up-for-ai-agents

Create shared technical vision for team alignment

openup-retrospective

6
from GermanDZ/open-up-for-ai-agents

Generate iteration retrospective with feedback and action items

openup-request-input

6
from GermanDZ/open-up-for-ai-agents

Create an input request document for asynchronous stakeholder communication

openup-readiness

6
from GermanDZ/open-up-for-ai-agents

Compute the change-folder dependency DAG and print READY/BLOCKED/collision report for PM intake

openup-quick-task

6
from GermanDZ/open-up-for-ai-agents

Fast iteration mode for small changes - simplified workflow with minimal overhead

openup-plan-feature

6
from GermanDZ/open-up-for-ai-agents

Generate iteration plan and roadmap entry for a feature idea

openup-phase-review

6
from GermanDZ/open-up-for-ai-agents

Check phase completion criteria and prepare for phase review

openup-orchestrate

6
from GermanDZ/open-up-for-ai-agents

Run a full orchestrated iteration — PM decomposes the goal, delegates to specialist roles, collects outputs, and synthesizes results

openup-next

6
from GermanDZ/open-up-for-ai-agents

Run ONE OpenUP delivery cycle — read the derived board, claim the top READY lane, execute it, tick its progress, and exit through a legal exit. The sequential continue-loop.