BOHICA-LABS / BOHICA-LABS/vsdd-factory

enhancement(steady-state): post-SHIPPED PRs to develop bypass every factory quality gate — no spec-drift check, no consistency-validator, no input-hash scan

Open
#488 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
2
Forks
1
Avg merge
6h 43m
Merged PRs (30d)
29

Description

## Defect class

Once a VSDD project reaches `SHIPPED` and enters steady-state, PRs to `develop` bypass every factory quality gate that phase-1..7 enforced. `orchestrator/steady-state.md` (referenced in the orchestrator system prompt as a load-on-demand file) exists but is not automatically invoked by any git hook, GitHub Action, or `/vsdd-factory:` skill. `/vsdd-factory:check-input-drift` is phase-gate-only.

Silent-drift class of failure: post-SHIPPED PRs land on `develop`, touch files that ARE (or OUGHT to be) inputs to specs, but no factory step notices. Spec versions freeze at their last-phase-7 values while the codebase drifts underneath.

## Observed failure (switchboard-blue, 2026-07-04)

After `v0.1.0-rc.1 SHIPPED` (Burst 100), two consecutive PRs landed on `develop`:

- **PR #74** — user-facing operator docs (docs/getting-started.md, docs/sbctl.md).
- **PR #75** — Formula rename `switchboard.rb` → `switchboard-a.rb` (alpha channel reservation, sbctl packaging omission).

Both introduced facts that belong in `.factory/specs/`:

- ARCH-06 §Distribution & Packaging (Homebrew alpha channel `switchboard-a`, formula-slot reservation, sbctl packaging plan).
- cicd-setup.md §1 workflow rows (the alpha-publish workflow that runs on tag push).

Neither PR triggered any factory gate. Spec catalog stayed at v1.0. The user, not the factory, caught the drift **two days after PR #75 merged** — only by asking directly during a steady-state operator-doc + spec-drift audit.

## Root cause

Three layers, each with a gap:

1. **Automation gap.** No workflow/hook watches PRs to `develop` post-SHIPPED against `inputDocuments:` frontmatter. `/vsdd-factory:check-input-drift` exists but is a phase-gate skill, not a steady-state trigger.
2. **Documentation gap.** `orchestrator/steady-state.md` describes steady-state at a policy level but has no enforceable gate. No mandatory step ties spec version to changed inputs.
3. **Frontmatter gap.** `inputDocuments:` is stale in every spec that references shipped files. ARCH-06 v1.0 did not list `.github/workflows/ci.yml`; cicd-setup.md v1.0 did not list `Formula/switchboard-a.rb`. The gate would fail-open on incomplete input lists even if the gate existed.

## Failure scenario

Any PR to `develop` after `SHIPPED` that touches a file listed (or that OUGHT to be listed) in some spec's `inputDocuments:` — the spec version stays at 1.0, no changelog row is added, no adversary/consistency-validator sees it. Multi-PR drift compounds silently.

Detected only when:
- A human asks directly.
- The next release cycle's phase-1 adversary catches accumulated drift weeks or months later.
- An operator hits a docs-vs-behavior mismatch.

## Proposed fix (three-part)

### 1. New workflow `.github/workflows/spec-drift.yml`

Auto-generated as part of `phase-1-cicd-setup` for every project so every VSDD-managed repo inherits it. On every PR to `develop`:

- Reads every spec's `inputDocuments:` frontmatter (glob `.factory/specs/**/*.md`).
- Runs `git diff --name-only $BASE..HEAD` and intersects with the union of all `inputDocuments:`.
- Fails with a specific listing of "PR touches file X which is an input to spec Y v1.N; spec Y has not been amended in this PR" if the intersection is non-empty AND the spec itself was not touched by the PR.
- Optional escape hatch: `[skip-spec-drift]` in the PR body for PRs that pre-declare the drift as accepted (with a follow-up story ID).

### 2. Register `steady-state-spec-drift` as a mandatory step

Add to `agents/orchestrator/steady-state.md` a step that runs after every merge to `develop`. The orchestrator picks up the workflow output and either:
- Dispatches spec-steward to amend the affected spec(s) in a follow-up PR.
- Records the intentional deferral in a drift-register with a target release.

### 3. New skill `/vsdd-factory:steady-state-drift-check`

CLI-invokable local check with the same scan logic as (1). Operators can run it before opening a PR to see whether their diff will trigger the gate.

## Acceptance criteria

- [ ] `phase-1-cicd-setup` scaffolds `.github/workflows/spec-drift.yml`
- [ ] `orchestrator/steady-state.md` has a `steady-state-spec-drift` step
- [ ] `/vsdd-factory:steady-state-drift-check` skill registered
- [ ] `docs/FACTORY.md` or `docs/VSDD.md` picks up "spec drift in steady-state" as a first-class concern
- [ ] All template `inputDocuments:` frontmatter examples in the plugin cover CI/CD + packaging files (backfill from switchboard-blue as blueprint)

## Duplicate check

- Not #396 (citation-corpus sweep — operates inside a phase, not steady-state).
- Not #487 (smoke sentinel — operator-boundary regression, not spec-drift).
- Related: #396 (in-phase citation sweep), #487 (smoke gate in delivery loop) — both close different perimeters of the same "we need a gate that catches what we don't know we're missing" pattern.

## Priority

**HIGH** — silent drift accumulation. Every VSDD project reaching SHIPPED will hit this within days of steady-state. switchboard-blue hit it within 48h.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.