Skip to content

v2.1.0 — M6 hardening & UX

Choose a tag to compare

@danielPoloWork danielPoloWork released this 27 Jun 14:48
6114ad0

M6 — hardening & UX. The post-v2.0.0 hardening milestone: the automation/completeness gaps
(G2–G4) and feature suggestions (F1–F4) surfaced by the v2.0.0 enterprise review, plus the deferred
cross-spec scope (#72). All opt-in and behind the unchanged pipeline — a MINOR release, no breaking
changes. Highlights: a thin executable phase orchestrator (eados.py), the /eados status doctor,
single-artifact render for refactor, an end-to-end phase smoke, risk-model weights as data,
auto-derived traceability links, hands-off Dependabot action-pin sync, and two new dogfooded gates
(version-lockstep, cross-cutting cross-spec-consistency).

Added

  • M6 / 6.8 — cross-spec gate extended to cross-cutting gates (#72). traceability-lint (the
    git-spec CI gate, not a phase-transition gate) is now registered in workflow.yaml's gate list
    (cross-cutting, required_for: []), and eados_lint's cross-spec-consistency validates
    git.yaml's traceability.gate against that registry — so a typo'd cross-cutting gate id is
    caught too (the scope deferred from #62). test_cross_spec.py covers the resolve + typo cases.
    Completes M6. No pipeline behavior change.
  • M6 / 6.7 — version-lockstep dogfooding (F4, #69). EADOS now dogfoods the version-lockstep
    gate it ships to generated repos: a new eados_lint check asserts every README release badge
    (EN + docs/i18n/*) and the CHANGELOG's "the latest is vX.Y.Z" prose match the CHANGELOG's
    latest released ## [X.Y.Z] heading — so a release bump must move all of them in lockstep or the
    self-lint fails. Pure version_lockstep_problems(); covered by
    tools/tests/test_version_lockstep.py. No pipeline behavior change.
  • M6 / 6.6 — auto-derive traceability links from PR bodies (F2, #67). A new
    tools/derive_links.py builds the {pr, rfc, milestone, commit, release} traceability edges from
    merged PRs — pr/commit/milestone from gh metadata, rfc parsed from the body, release
    from a release PR's title — and emits a links.yaml that traceability.py --links consumes, so
    the graph runs on real data instead of a hand-maintained file. By default it emits only delivery
    PRs (those with an rfc or milestone); --all emits every PR. The parser is pure and tested
    gh-free; the optional fetch degrades cleanly (clear message, exit 2) when gh is absent,
    unauthenticated, or offline — CI never depends on the network. Covered by
    tools/tests/test_derive_links.py. No pipeline behavior change.
  • M6 / 6.5 — thin CLI phase orchestrator (G3, #64). A new tools/eados.py <phase> <manifest>
    runs a phase's deterministic outgoing gates — read from workflow.yaml (no hardcoded chain) —
    evaluating the ones it can (manifest-valid, rfc-approved, roadmap-covers-rfcs) via the
    sibling tools and marking render-time / human gates [manual], then prints the legal next
    transitions and points at the procedure; eados.py status delegates to the doctor (6.4). It is
    the executable spine beneath the markdown /eados <phase> procedures — it reports and gates,
    never authoring or advancing state. Covered by tools/tests/test_eados.py. No pipeline behavior
    change.
  • M6 / 6.4 — /eados status doctor (F1, #66). A new read-only tools/doctor.py (the
    /eados status surface, commands/status.md) reports a project's delivery health at a glance:
    current phase (+ its owning role and what it produces), the legal next transitions (+ gates and
    human-gating, via phase_runner), the recorded rfcs/milestones refs, and traceability
    coverage (roadmap-covers-rfcs, plus traceability-lint when a links file is present, via
    traceability). It composes the existing tools — never re-implements — and exits non-zero on an
    actionable problem (undeclared phase, uncovered RFC, dangling edge), doubling as a pre-flight
    check. Covered by tools/tests/test_doctor.py. Read-only; no pipeline behavior change.
  • M6 / 6.3 — single-artifact render for the refactor phase (G2, #63). A new
    tools/render_artifact.py renders one template with the manifest context — reusing
    render.py's engine and the validate_manifest + unresolved-placeholder gates, so a single
    artifact is byte-identical to its whole-render twin — and writes it into a target repo through
    tools/sandbox.py (safe_write: contained, never .git, additive). It performs the "render the
    missing artifact → sandbox" step commands/refactor.md describes (now invoked there instead of
    done by hand). Covered by tools/tests/test_render_artifact.py. Factory tooling; no pipeline
    behavior change.
  • CI — Dependabot pin-sync now auto-re-triggers via a GitHub App (ADR-0013 addendum). The
    dependabot-pin-sync workflow mints a short-lived App token (actions/create-github-app-token,
    SHA-pinned) when SYNC_APP_ID + SYNC_APP_PRIVATE_KEY are set and pushes the pin re-sync with it,
    so CI re-triggers and the failed action-pins check goes green by itself; absent the App
    secrets it falls back to GITHUB_TOKEN (the fix still lands, check re-runs on the next event). The
    setup guide is rewritten App-first; DEPENDABOT_SYNC_TOKEN is now the swap-in PAT fallback, not the
    default. Factory-only; no pipeline behavior change.
  • M6 / 6.1 — end-to-end phase-flow smoke (G4, #65). A new tools/tests/test_phase_smoke.py
    threads one coherent fixture project (manifest + RFC + ROADMAP + links) through design → plan → audit by invoking the real phase tool CLIs (rfc_check, traceability, risk_score,
    phase_runner) the way an agent runs a phase. It asserts each gate passes on the good
    fixture and fails on a deliberately broken one, that phase_runner --propose reports every
    transition declared in workflow.yaml LEGAL (and rejects an undeclared one), and that each entry
    gate's backing tool exists on disk — catching tool-integration (seam) bugs the per-tool unit
    tests cannot. Wired into the CI self-lint job. No pipeline behavior change.
  • M6 / 6.2 — risk-model weights as data (F3, #68). The factor weights (security surface, size,
    blast radius), the blast_radius_threshold, and the points→level cutoffs move out of
    risk_score.py into risk.yaml as data — each per-domain overridable (weights shallow-merged),
    exactly as mandatory_gate_level already was (OQ2). The scorer reads them via a new
    resolve(cfg, domain) with built-in fallbacks, so a pre-6.2 risk.yaml still scores identically
    (back-compat) and the shipped default scores are unchanged. risk/_schema.md documents the new
    keys; covered by the expanded test_risk_score.py. Knowledge as data — no special-casing in code.
  • M6 / 6.9 — auto-sync shared action pins into the rendered templates (#76). A new
    tools/sync_action_pins.py (--check / --fix) rewrites the workflow templates'
    (templates/.github/workflows/*.tmpl) action pins to the factory CI's pin for each shared action
    — reusing eados_lint's pin regex so the fixer and the action-pins gate can never disagree. A
    weekly Dependabot github-actions bump now needs no manual template edit to pass the lockstep
    gate. The new dependabot-pin-sync workflow (workflow_run, not pull_request_target;
    ADR-0013) applies the fix automatically on a Dependabot PR — true zero-touch — gated to genuine
    in-repo Dependabot PRs; the same --fix is the manual/local fallback (stay-current routine).
    Deterministic and dependency-free; covered by tools/tests/test_sync_action_pins.py. Factory-only
    (generated repos render no templates). No pipeline behavior change.
  • Docs — DEPENDABOT_SYNC_TOKEN setup guide. maintenance/dependabot-sync-token.md documents
    the optional token for green-by-itself Dependabot pin auto-sync (ADR-0013): fine-grained PAT
    (drop-in) vs GitHub App (robust, with the workflow snippet), least-privilege (Contents-write only),
    storage via gh secret set, verification, and rotation. Linked from the stay-current routine.
    Maintainer-facing; no behavior change.

Security