spec/018: adoption readiness — README and onboarding#33
Draft
outergod wants to merge 35 commits into
Draft
Conversation
outergod
added a commit
that referenced
this pull request
May 6, 2026
Branch pushed to origin/018-adoption-readiness; draft PR opened at #33. Operator confirmed the Mermaid block renders as a diagram on the Files tab (not a raw fenced code block), satisfying T019's pass criterion. A small `nodeSpacing` tweak in 40001bb addresses GitHub's zoom/pan control overlap with the rightmost node. Closes out US3 (T017–T019). US2 (walkthrough + cast) and remaining phases (US4, Polish) are next. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
outergod
added a commit
that referenced
this pull request
May 6, 2026
Four integration tests under tests/integration/ asserted on README section names from the pre-spec/018 layout (## What is CoreOps?, ## Credibility, ## Installation (Current Phase)) and one fixture pinned the controller version at 2.2.0. After the README restructure (T004-T009) and the 2.2.0 -> 2.2.1 bump driven by packaged_readme_surface, all four turned red on PR #33's CI: - test_distribution_credibility::credibility_surface_matches_release_metadata_fixture - test_distribution_entrypoint::readme_contains_required_entrypoint_sections - test_distribution_installation::readme_documents_binary_installation_sequence - test_status_contract::controller_version_provenance_matches_cargo_package_version This is mechanical fixture maintenance: the assertions track section names and a version string, neither of which represents new test surface or new behavioral coverage. FR-017's original prohibition on tests/ modifications was authored without anticipating that the README rename would propagate into existing structural assertions, and is relaxed here in the same shape as the prior packaged_readme_surface carve-out (decision_018-packaged-readme-surface-cargo-bump). Spec changes: - spec.md FR-017: tests/integration/ and tests/fixtures/ MAY be updated for FR-001 section renames or for the bumped Cargo.toml version. New tests, new fixtures, and new behavioral assertions remain prohibited. - spec.md SC-010: matching adjustment; Cargo.toml/Cargo.lock/tests/ excluded from the no-source-touched diff check. - tasks.md: Tests-Exempted, Path-conventions, T024, and Notes updated to reflect the carve-out. Test changes: - test_distribution_credibility.rs: ## Credibility -> ## Trust and release model (FR-001 §10 fold). Snapshot-fixture assertions track the new FR-001 section names. - test_distribution_entrypoint.rs: heading list replaced with the FR-001 12-section ordering. - test_distribution_installation.rs: ## Installation (Current Phase) -> ## Quick start (FR-001 §7 fold). - valid-success.json: controller.version 2.2.0 -> 2.2.1 (matches Cargo.toml). - entrypoint-snapshot.md: section list updated to track the FR-001 ordering. Notably untouched: tests/fixtures/distribution/release-metadata.json's credibility_location field still points at the removed README.md#credibility anchor. Modifying that fixture would trigger machine_readable_distribution_contract (major bump) which is out of scope for spec/018's patch budget; flagged as a follow-up. Verification: $ cargo test 472 passed $ cargo clippy --all-targets -- -D warnings clean $ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) $ git diff master..HEAD --stat -- src/ .github/workflows/ examples/ LICENSE empty Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
outergod
added a commit
that referenced
this pull request
May 7, 2026
Branch pushed to origin/018-adoption-readiness; draft PR opened at #33. Operator confirmed the Mermaid block renders as a diagram on the Files tab (not a raw fenced code block), satisfying T019's pass criterion. A small `nodeSpacing` tweak in 40001bb addresses GitHub's zoom/pan control overlap with the rightmost node. Closes out US3 (T017–T019). US2 (walkthrough + cast) and remaining phases (US4, Polish) are next. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
outergod
added a commit
that referenced
this pull request
May 7, 2026
Four integration tests under tests/integration/ asserted on README section names from the pre-spec/018 layout (## What is CoreOps?, ## Credibility, ## Installation (Current Phase)) and one fixture pinned the controller version at 2.2.0. After the README restructure (T004-T009) and the 2.2.0 -> 2.2.1 bump driven by packaged_readme_surface, all four turned red on PR #33's CI: - test_distribution_credibility::credibility_surface_matches_release_metadata_fixture - test_distribution_entrypoint::readme_contains_required_entrypoint_sections - test_distribution_installation::readme_documents_binary_installation_sequence - test_status_contract::controller_version_provenance_matches_cargo_package_version This is mechanical fixture maintenance: the assertions track section names and a version string, neither of which represents new test surface or new behavioral coverage. FR-017's original prohibition on tests/ modifications was authored without anticipating that the README rename would propagate into existing structural assertions, and is relaxed here in the same shape as the prior packaged_readme_surface carve-out (decision_018-packaged-readme-surface-cargo-bump). Spec changes: - spec.md FR-017: tests/integration/ and tests/fixtures/ MAY be updated for FR-001 section renames or for the bumped Cargo.toml version. New tests, new fixtures, and new behavioral assertions remain prohibited. - spec.md SC-010: matching adjustment; Cargo.toml/Cargo.lock/tests/ excluded from the no-source-touched diff check. - tasks.md: Tests-Exempted, Path-conventions, T024, and Notes updated to reflect the carve-out. Test changes: - test_distribution_credibility.rs: ## Credibility -> ## Trust and release model (FR-001 §10 fold). Snapshot-fixture assertions track the new FR-001 section names. - test_distribution_entrypoint.rs: heading list replaced with the FR-001 12-section ordering. - test_distribution_installation.rs: ## Installation (Current Phase) -> ## Quick start (FR-001 §7 fold). - valid-success.json: controller.version 2.2.0 -> 2.2.1 (matches Cargo.toml). - entrypoint-snapshot.md: section list updated to track the FR-001 ordering. Notably untouched: tests/fixtures/distribution/release-metadata.json's credibility_location field still points at the removed README.md#credibility anchor. Modifying that fixture would trigger machine_readable_distribution_contract (major bump) which is out of scope for spec/018's patch budget; flagged as a follow-up. Verification: $ cargo test 472 passed $ cargo clippy --all-targets -- -D warnings clean $ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) $ git diff master..HEAD --stat -- src/ .github/workflows/ examples/ LICENSE empty Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
f022319 to
6433b50
Compare
outergod
added a commit
that referenced
this pull request
May 7, 2026
Branch pushed to origin/018-adoption-readiness; draft PR opened at #33. Operator confirmed the Mermaid block renders as a diagram on the Files tab (not a raw fenced code block), satisfying T019's pass criterion. A small `nodeSpacing` tweak in 40001bb addresses GitHub's zoom/pan control overlap with the rightmost node. Closes out US3 (T017–T019). US2 (walkthrough + cast) and remaining phases (US4, Polish) are next. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
outergod
added a commit
that referenced
this pull request
May 7, 2026
Four integration tests under tests/integration/ asserted on README section names from the pre-spec/018 layout (## What is CoreOps?, ## Credibility, ## Installation (Current Phase)) and one fixture pinned the controller version at 2.2.0. After the README restructure (T004-T009) and the 2.2.0 -> 2.2.1 bump driven by packaged_readme_surface, all four turned red on PR #33's CI: - test_distribution_credibility::credibility_surface_matches_release_metadata_fixture - test_distribution_entrypoint::readme_contains_required_entrypoint_sections - test_distribution_installation::readme_documents_binary_installation_sequence - test_status_contract::controller_version_provenance_matches_cargo_package_version This is mechanical fixture maintenance: the assertions track section names and a version string, neither of which represents new test surface or new behavioral coverage. FR-017's original prohibition on tests/ modifications was authored without anticipating that the README rename would propagate into existing structural assertions, and is relaxed here in the same shape as the prior packaged_readme_surface carve-out (decision_018-packaged-readme-surface-cargo-bump). Spec changes: - spec.md FR-017: tests/integration/ and tests/fixtures/ MAY be updated for FR-001 section renames or for the bumped Cargo.toml version. New tests, new fixtures, and new behavioral assertions remain prohibited. - spec.md SC-010: matching adjustment; Cargo.toml/Cargo.lock/tests/ excluded from the no-source-touched diff check. - tasks.md: Tests-Exempted, Path-conventions, T024, and Notes updated to reflect the carve-out. Test changes: - test_distribution_credibility.rs: ## Credibility -> ## Trust and release model (FR-001 §10 fold). Snapshot-fixture assertions track the new FR-001 section names. - test_distribution_entrypoint.rs: heading list replaced with the FR-001 12-section ordering. - test_distribution_installation.rs: ## Installation (Current Phase) -> ## Quick start (FR-001 §7 fold). - valid-success.json: controller.version 2.2.0 -> 2.2.1 (matches Cargo.toml). - entrypoint-snapshot.md: section list updated to track the FR-001 ordering. Notably untouched: tests/fixtures/distribution/release-metadata.json's credibility_location field still points at the removed README.md#credibility anchor. Modifying that fixture would trigger machine_readable_distribution_contract (major bump) which is out of scope for spec/018's patch budget; flagged as a follow-up. Verification: $ cargo test 472 passed $ cargo clippy --all-targets -- -D warnings clean $ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) $ git diff master..HEAD --stat -- src/ .github/workflows/ examples/ LICENSE empty Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bce0d5b to
f64c284
Compare
Author specs/018-adoption-readiness/spec.md targeting README + onboarding
adoption readiness post-spec/017. Four prioritized user stories (P1: 5-min
mental simulation; P2: walkthrough credibility; P2: architecture diagram;
P3: structural contract for future maintainers). Nineteen functional
requirements split across README structure (FR-001..003), onboarding
artifacts (FR-004..009a), tone preservation (FR-010..014), Spec Kit
deliverables (FR-015..016), and explicit negative requirements
(FR-017..019). Twelve+ structural success criteria (grep / wc /
file-existence) plus an author self-attested dogfooding pass.
Five clarifications integrated in Session 2026-05-06:
- Recording sanitization mirrors spec/017 FR-009 (RFC 2606 / RFC 5737,
generic prompt, no operator-private values).
- Hard cap of 90 seconds on docs/onboarding.cast; narrow scope rather
than extend.
- Walkthrough plan-output blocks are verbatim from real invocations,
`...` elision permitted, no paraphrasing or hand-tuning.
- Dogfooding pass via author self-attestation (acknowledged limit
traded against feasibility for solo-author project).
- Static walkthrough carries plan + idempotent re-run snippet (~25
lines); apply / status are recording-only.
Release fragment declares release_intent: patch, scope: docs.
Validates as exempt under always_exempt_documentation_or_formatting.
Branched from master at v2.2.0 (cfc0914).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 0 / Phase 1 outputs from /speckit.plan workflow:
- plan.md: Technical Context, Constitution Check (PASS — VM-backed
scenario exemption recorded), project structure decision,
Phase 0 / 1 summaries, Complexity Tracking (no entries), and post-
design constitution re-check.
- research.md: five resolved decisions (R1 asciinema tooling pin,
R2 Mermaid GitHub render fidelity, R3 README size benchmarks,
R4 sanitization at recording time via env-scrubbed shell, R5
walkthrough fidelity verification at PR review). Three follow-ups
captured (static SVG sidecar, CONTRIBUTING/ARCHITECTURE follow-up,
multi-language docs) — none blocking.
- quickstart.md: one-page operator pointer covering what 018 changes
on disk, what stays unchanged, local verification commands,
re-recording instructions, and relationship to spec/017.
data-model.md and contracts/ are explicitly omitted per spec FR-015 —
no new data structures or CLI contracts are introduced.
CLAUDE.md regenerated via .specify/scripts/bash/update-agent-context.sh
to reflect the (minimal) tech-stack delta.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
28 tasks across 7 phases:
- Phase 1 Setup: 2 parallel scaffold tasks (checklist + synthesis
skeletons).
- Phase 2 Foundational: docs/onboarding-script.sh regeneration entry
point with version-pinned asciinema and env-scrubbed shell.
- Phase 3 (US1, P1, MVP): 7 tasks restructuring README into the
canonical 12-section ordering, promoting badge row, authoring the
30-second mental model, compressing philosophy, folding Trust
section, and inserting placeholders for US2/US3 fills.
- Phase 4 (US2, P2): 6 tasks capturing verbatim plan + idempotent
re-run output, populating the walkthrough section, recording the
cast (≤ 90 s), sanitizing, and linking from README.
- Phase 5 (US3, P2): 3 tasks authoring the Mermaid block, the
non-Mermaid prose fallback, and verifying GitHub render.
- Phase 6 (US4, P3): 1 task populating the structural checklist
runbook with one runnable command per FR/SC.
- Phase 7 Polish: 8 tasks (4 parallel structural checks, dogfooding
pass after 24h cool-off, synthesis authoring, release-governance
re-validation, PR open).
Tests are exempted per spec FR-019. Rust gates (cargo test / clippy)
remain authoritative for the codebase but are not exercised by this
docs-only iteration.
US1 is the MVP — restructured README is shippable as a draft PR even
before US2/US3 fill the placeholders.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolves the four MEDIUM-severity findings from the post-tasks analysis pass: - F1 (spec.md Edge Case #3): replace stale "FR-008" reference with "FR-006" — the verbatim-from-real-invocation rule is the actual mitigation for walkthrough drift. - F2 (spec.md Edge Case #3): replace stale "Phase 5" reference with "polish phase / Phase 7" — re-validation lives in tasks.md Phase 7 (T021/SC-007a), not Phase 5 (US3 Mermaid). - F3 (tasks.md T011/T012): drop [P] from T012 and document the serialization rationale — apply mutates `--host immich` state that T011's pre-apply plan reads. Sequential by default; parallel only on isolated hosts. Updated Phase 4 dependency note and Parallel Opportunities accordingly. - F4 (spec.md US2 Independent Test + Why-this-priority): update "the static block" (singular) phrasing to reflect post-clarify FR-006 two-block structure (plan + idempotent re-run). LOW findings (F5–F10) deferred — cosmetic / acknowledged-tradeoff / stale-on-arrival line references that don't affect implementation. No constitution alignment changes, no new FRs/SCs, no new tasks. Validation re-passes as exempt under always_exempt_documentation_or_formatting. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Empty skeleton for the post-implementation runbook used by US4 (T020) to verify the structural contract at PR-review time. Pre-populated with the FR/SC index for each check; commands themselves are filled later by T020 once US1/US2/US3 land and the final README shape stabilizes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Skeleton retrospective with section headers for the dogfooding pass (T025), the proposal §9 questions (T026), the follow-up candidates flagged in research.md, and a "judgment calls" section to capture non-trivial implementer decisions the spec did not pre-resolve (e.g., placement of existing-but-not-canonical sections like "What CoreOps Does" and "Supported Systems"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Structural reorder only; content preserved verbatim per task scope.
Subsequent tasks fill the new sections (T005 badge promotion,
T006 mental model, T007 philosophy compression, T008 Trust fold,
T009 Architecture/Walkthrough placeholders).
- Move Real-world examples (was line 115, FR-012) above Quick start.
- Fold Installation (Current Phase) + First Interaction +
Supported Systems into one ## Quick start section. Supported
Systems becomes a ### subsection of Quick start.
- Move Why CoreOps exists / What CoreOps is not down to §8/§9.
- Move Credibility, Minimal Trust Story, Release & Verification
Model adjacent to each other in §10 area for T008 to fold.
- Lowercase headings: AI authorship, Why CoreOps exists,
What CoreOps is not, Real-world examples, Further reading,
Target audience.
- Consolidate Target Audience + License + Further Reading into
one ## Target audience · License · Further reading section.
- Insert HTML comments where T006/T009 will fill new sections.
- Legacy "What is CoreOps?" + "What CoreOps Does" kept in place
for T006 to absorb into the 30-second mental model.
README: 275 → 264 lines.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per FR-002 / SC-002:
- Badge row moved to immediately after the title block (centered,
inline HTML to match the existing logo + tagline style).
- Added 4th badge: License (AGPL-3.0-or-later) linking to LICENSE.
- Final badge row order: CI · E2E Gate · Latest Release · License.
- Dissolved the "## Credibility" heading; the signal table and
blurb remain in their current position for T008 to fold into
"## Trust and release model".
Used inline <p align="center"> + <a><img> markup (matching the
existing logo/tagline pattern) instead of shields.io badge markdown
to keep the badges centered and grouped on a single visual line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per FR-001 §3 / SC-003. ~150 words (under the 200-word cap). Covers all four required topics: host-native convergence, systemd/Quadlet centricity, declarative reconciliation, Git-driven operation. Heading at line 20 (within the 120-line target). Replaces the legacy "## What is CoreOps?" introduction and absorbs the "## What CoreOps Does" feature bullets into the plan/apply/status command beats. Net README change: 269 → 263 lines (-6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per FR-001 §8/§9/§11 budgets. Final section line counts (heading + content, excluding the trailing --- separator): - Why CoreOps exists: 11 lines (budget ≤ 15) - What CoreOps is not: 8 lines (budget ≤ 12) - AI authorship: 12 lines (budget ≤ 12) Why CoreOps exists collapsed two short bulleted paragraphs into one prose paragraph: same content, no semantic loss, drops 4 lines. What CoreOps is not and AI authorship were already within budget; no edits required for them. README: 263 → 257 lines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per FR-001 §10. Three previously separate sections collapsed into one cohesive ## Trust and release model: - Credibility table (artifacts row + verification environment row) - Minimal Trust Story (audit-surface story) - Release & Verification Model (release-gate / promote story) Verification environment row preserved verbatim (`fedora-coreos-self-hosted@2026-04-fcos`). Bullet lists collapsed into prose where the bullets were short enough to read more naturally as a sentence (audit-surface enumeration in the first paragraph; spec/scenarios/gate enumeration in the third). The release-job description now reads as one paragraph instead of three sub-paragraphs. README: 257 → 225 lines (-32). Section ordering now matches FR-001 for §1, §3, §6–§12; §4 Architecture and §5 Walkthrough are still HTML-comment placeholders pending T009. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Insert proper ## Architecture (§4) and ## What using CoreOps feels like (§5) headings in their canonical positions, with blockquoted "[Populated by USx implementation (tasks Tnnn-Tnnn)]" notes naming exactly which user story / tasks fill each section. After this commit, README has all 12 canonical sections of FR-001 in order: §1 Title (block), §2 Badge row (no heading), §3 Mental model, §4 Architecture (placeholder), §5 Walkthrough (placeholder), §6 Real-world examples, §7 Quick start, §8 Why CoreOps exists, §9 What CoreOps is not, §10 Trust and release model, §11 AI authorship, §12 Target audience · License · Further reading. The README is now structurally compliant with FR-001 ordering; content for §4 and §5 will be filled by US3 (T017–T019) and US2 (T011–T016) respectively in subsequent sessions. README: 225 → 243 lines (+18, all in placeholder blockquotes). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Read-only verification against post-T009 README.md. All structural checks pass: SC-001 README line budget: 243 lines (≤ 400) — PASS SC-003 mental model heading: line 20 (≤ 120) — PASS SC-008 hype stop-list: 0 matches — PASS Compatibility: 9 pre-018 link targets all resolve — PASS All 12 canonical sections of FR-001 present and ordered correctly: §1 Title (block) §2 Badge row (no heading) §3 ## 30-second mental model §4 ## Architecture (placeholder) §5 ## What using CoreOps feels like (placeholder) §6 ## Real-world examples §7 ## Quick start §8 ## Why CoreOps exists §9 ## What CoreOps is not §10 ## Trust and release model §11 ## AI authorship §12 ## Target audience · License · Further reading US1 MVP complete. The README is shippable as a draft PR; the Architecture and Walkthrough placeholders explicitly call out which user stories will fill them. Release governance still passes (exempt under always_exempt_documentation_or_formatting). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Background: The README modifications landed in T004–T009 trigger the release-governance rule `packaged_readme_surface` because README.md ships in published release bundles per the Quick Start documentation. The rule (correctly) requires a Cargo.toml patch bump to keep the packaged README's "this is the version you're getting" promise honest. Spec/018 FR-017 was authored without anticipating this rule and forbade Cargo.toml modifications outright. That over-restriction is relaxed here — Cargo.toml MAY be patch-bumped when triggered by release-governance rules; the bump is metadata-only and does not constitute a source-code change. Cargo.lock follows. Changes: - Cargo.toml: version 2.2.0 → 2.2.1 - Cargo.lock: regenerated (cargo update --workspace --offline) - spec.md FR-017: relax to permit governance-driven Cargo.toml bumps - spec.md SC-010: matching adjustment `core-ops-release validate --base-ref master` now reports: Outcome: passed | Classification: releasable Required bump: patch | Declared bump: patch | Version bump: patch CHANGELOG aligned: yes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `asciinema` 2.4.0 (nixpkgs-pinned) to the dev shell so `docs/onboarding-script.sh` (T003) can re-record `docs/onboarding.cast` (T014) without an out-of-shell install. Version is asserted in the script header per spec/018 R1 + FR-009. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ayout The spec consistently referenced `--host immich` for the canonical walkthrough command, but `examples/03-immich/hosts/example/host.yaml` declares `host: example` — the only host overlay in the example. `--host immich` does not resolve and would have produced a fabricated walkthrough block, violating FR-006's verbatim-from-real-invocation rule. Aligns with the existing README convention (line 81 already uses `--host example` for examples/01-caddy-whoami). Mechanical s/--host immich/--host example/g across spec.md, tasks.md, research.md, quickstart.md — 11 occurrences, no semantic change beyond the host name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Regeneration entry point for `docs/onboarding.cast` (T014). Records
the spec/017 stateless `--source-repo` workflow against
`examples/03-immich --host example`: initial plan, apply, idempotent
re-run.
Sanitization (FR-009a, mirrors spec/017 FR-009) is enforced at
recording time via an env-scrubbed `bash --noprofile --norc` subshell:
env -i HOME=/home/op PATH=/usr/local/bin:/usr/bin:/bin
TERM=xterm-256color PS1='op@example $ '
The SC-006a stop-list grep is intentionally NOT embedded in this
script — putting the regex in the file would self-match. The check
lives in the spec's structural checklist (T020) and is run from there.
Pinned to asciinema 2.4.0 (nix devshell pin from prior commit). The
script header documents operator prerequisites including the
GPU-passthrough edge case for `examples/03-immich/services/immich-ml`.
Flips T003 in tasks.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the US3 placeholder in README ## Architecture with a
left-to-right flowchart of the five primary nodes:
GIT → CORE → STATE → HOST (primary convergence flow)
CORE -.-> AUDIT, HOST -.-> AUDIT (audit + status side outputs,
dashed to signal secondary)
Verified: ≥4 nodes (5), substrings `Git` / `core-ops` / `systemd`
present, audit edges dashed (FR-004 / SC-004). Render verification
on the GitHub PR preview is T019.
Surrounding prose for non-Mermaid renderers comes in T018.
Flips T017 in tasks.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a 5-line "read left-to-right" paragraph after the Mermaid block that names all four primary nodes (`Git repository`, `core-ops`, `systemd + Quadlet units`, `host`) and the side output (`audit + status`) in plain text. Per US3-AC-3, the architecture must be recoverable on render contexts that do not display Mermaid (RSS, mirrors, terminal viewers like \`glow\`). Flips T018 in tasks.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GitHub's Mermaid player overlays zoom/pan/fullscreen controls in the
top-right corner of the rendered diagram. With the rightmost `HOST`
node positioned tight against the edge, the controls cover it on
initial render. Adds a `%%{init}%%` directive bumping `nodeSpacing`
to 50 and `rankSpacing` to 70 so the layout fits with margin.
GitHub honors `init` directives in Mermaid blocks; if a future
renderer strips them, the diagram falls back to defaults — no
content change, only spacing.
FR-004 invariants reverified: ≥4 nodes (5), substrings `Git` /
`core-ops` / `systemd` present, audit edges remain dashed.
Branch pushed to origin/018-adoption-readiness; draft PR opened at #33. Operator confirmed the Mermaid block renders as a diagram on the Files tab (not a raw fenced code block), satisfying T019's pass criterion. A small `nodeSpacing` tweak in 40001bb addresses GitHub's zoom/pan control overlap with the rightmost node. Closes out US3 (T017–T019). US2 (walkthrough + cast) and remaining phases (US4, Polish) are next. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four integration tests under tests/integration/ asserted on README section names from the pre-spec/018 layout (## What is CoreOps?, ## Credibility, ## Installation (Current Phase)) and one fixture pinned the controller version at 2.2.0. After the README restructure (T004-T009) and the 2.2.0 -> 2.2.1 bump driven by packaged_readme_surface, all four turned red on PR #33's CI: - test_distribution_credibility::credibility_surface_matches_release_metadata_fixture - test_distribution_entrypoint::readme_contains_required_entrypoint_sections - test_distribution_installation::readme_documents_binary_installation_sequence - test_status_contract::controller_version_provenance_matches_cargo_package_version This is mechanical fixture maintenance: the assertions track section names and a version string, neither of which represents new test surface or new behavioral coverage. FR-017's original prohibition on tests/ modifications was authored without anticipating that the README rename would propagate into existing structural assertions, and is relaxed here in the same shape as the prior packaged_readme_surface carve-out (decision_018-packaged-readme-surface-cargo-bump). Spec changes: - spec.md FR-017: tests/integration/ and tests/fixtures/ MAY be updated for FR-001 section renames or for the bumped Cargo.toml version. New tests, new fixtures, and new behavioral assertions remain prohibited. - spec.md SC-010: matching adjustment; Cargo.toml/Cargo.lock/tests/ excluded from the no-source-touched diff check. - tasks.md: Tests-Exempted, Path-conventions, T024, and Notes updated to reflect the carve-out. Test changes: - test_distribution_credibility.rs: ## Credibility -> ## Trust and release model (FR-001 §10 fold). Snapshot-fixture assertions track the new FR-001 section names. - test_distribution_entrypoint.rs: heading list replaced with the FR-001 12-section ordering. - test_distribution_installation.rs: ## Installation (Current Phase) -> ## Quick start (FR-001 §7 fold). - valid-success.json: controller.version 2.2.0 -> 2.2.1 (matches Cargo.toml). - entrypoint-snapshot.md: section list updated to track the FR-001 ordering. Notably untouched: tests/fixtures/distribution/release-metadata.json's credibility_location field still points at the removed README.md#credibility anchor. Modifying that fixture would trigger machine_readable_distribution_contract (major bump) which is out of scope for spec/018's patch budget; flagged as a follow-up. Verification: $ cargo test 472 passed $ cargo clippy --all-targets -- -D warnings clean $ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) $ git diff master..HEAD --stat -- src/ .github/workflows/ examples/ LICENSE empty Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n blocks T011 (initial plan capture) and T012 (apply + idempotent re-run capture) were exercised end-to-end against `core-ops-uat` (Fedora CoreOS guest on ulthar libvirt). Apply succeeded after PR #34's postgres image-tag fix landed and after the operator-prereq podman secret `immich-db-password` was created on the host (per `examples/03-immich/README.md`). T013 replaces the `## What using CoreOps feels like` placeholder with two verbatim fenced code blocks per FR-006: - Plan output for `core-ops plan --source-repo examples/03-immich --host example` on a clean host: header + `[+] Create • 10` + `immich-database.container` entry with its `requires` graph and diff fragment + `...` elision + summary footer. - Idempotent re-run after `core-ops apply` converged the host: `[·] Unchanged • 10` + three representative service entries + `...` + `10 unchanged` summary. Every non-elided line appears byte-for-byte in actual core-ops output; `...` lines elide repeats and uninteresting content per FR-006. Combined non-blank line count: 25 (SC-007b ~25 budget). Five recognizable Quadlet unit identifiers from `examples/03-immich/services/` appear in the walkthrough (immich-database, immich-server, traefik-edge, immich-internal, immich-db-data) — well above SC-007's "≥ 1" threshold. Notes from exercising the example: - The `(stateless) (recovery from failed initial apply)` annotation in the second block reflects spec/017's stateless mode semantics: in stateless mode core-ops keeps no state under `/var/lib/`, so any plan invoked after a successful apply on the same host inspects raw host state and tags the run as "recovery from failed initial apply" because there is no persisted apply record. The annotation is truthful for stateless mode and is preserved verbatim. - The host overlay drop-in `examples/03-immich/hosts/example/immich-ml/quadlet/immich-ml.container.d/20-gpu.conf` was removed locally on the recording host (no `/dev/dri`); this is the documented host-shape-mismatch workaround from `docs/onboarding-script.sh`. README total: 295 lines (≤ 400). Verification: $ cargo test 472 passed $ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) $ wc -l README.md 295 (≤ 400) PASS SC-001 $ awk '/^## What using CoreOps feels like/,/^## Real-world examples/' README.md | grep -c '^```text' 2 PASS FR-006 $ <walkthrough section>: 5 distinct unit identifiers from examples/03-immich/services/ PASS SC-007 T014 (record asciinema cast) and T016 (link cast from README) carry through the recording-host work that follows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… from README
T014: docs/onboarding.cast recorded against core-ops-uat (Fedora CoreOS
guest on ulthar libvirt) exercising plan → apply → idempotent re-plan
against `examples/03-immich --host example`. Asciicast v2 format
(SC-005), duration 4.92 s (well under the 90 s FR-007 cap), recorded at
30×110 with `--idle-time-limit=2`. Image cache was preserved across the
clean state wipe so the apply beat completed in ~4 s of network/start
activity rather than the ~5 min image-pull path.
T015: SC-006a stop-list grep returns zero matches across both the cast
and the regeneration script:
grep -iE '(not\.one|ulthar|192\.168\.|10\.0\.|172\.16\.)' \
docs/onboarding.cast docs/onboarding-script.sh → 0 matches
The cast has been post-processed to strip pam_systemd-emitted OSC 3008
session-tracking sequences (which leak `hostname=core-ops-uat`,
`machineid=...`, and PID metadata when sudo creates a session under a
terminal that supports them) and to replace the recorder's
nix-store-path SHELL env value with `/bin/bash`. Both leak vectors are
outside the SC-006a regex but within FR-009a's broader sanitization
intent (no operator-private hostnames, no operator-private setup
values). The post-processor also computes the `duration` header field
from the last event timestamp — asciinema 2.4.0 omits it from the
header on completion in some cases, and SC-005a verifies via jq.
T016: README walkthrough section gains a one-line **Recording** anchor
linking `docs/onboarding.cast` with an `asciinema play` invocation hint.
No `<script>`, `<iframe>`, or `https://asciinema.org/...js` reference
in the diff (FR-013).
Process notes:
- The recording was produced via SSH delegation: asciinema 2.4.0 ran on
the operator workstation (nix devshell), the inner `env -i bash`
subshell ran `ssh -tq core@core-ops-uat 'cd ... && sudo <command>'`
for each demo beat. This deviates from the canonical
`docs/onboarding-script.sh` flow (which assumes a host with
asciinema 2.4.0 + core-ops + repo all present locally) because
Fedora CoreOS does not ship Python and rpm-ostree apply-live of
python3-asciinema was not authorized on the shared UAT VM. The
script remains valid for the documented use case.
- The OSC 3008 strip is a post-recording sanitization step. A future
iteration could amend `docs/onboarding-script.sh` to apply it
inline; flagged in synthesis follow-up.
Verification:
$ head -n 1 docs/onboarding.cast | jq '.version' 2 PASS SC-005
$ head -n 1 docs/onboarding.cast | jq '.duration' 4.918944 (≤ 90) PASS SC-005a
$ wc -l README.md 297 (≤ 400) PASS SC-001
$ grep -E '(asciinema\.org/.*\.js|<iframe|<script)' README.md (no matches) PASS FR-013
$ grep -iE '(not\.one|ulthar|192\.168\.|10\.0\.|172\.16\.)' docs/onboarding.cast docs/onboarding-script.sh (no matches) PASS SC-006a
$ asciinema play docs/onboarding.cast plays end-to-end PASS SC-005
$ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) PASS
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r-FR/SC checks Replaces the T001 skeleton table with 11 runnable checks (C-001 through C-011), each labeled with the FR/SC anchor it implements. The checklist is the falsifiable contract that catches future deviations from the 12-section FR-001 ordering, the FR-002 badge composition, the FR-009a sanitization rule, and so on, without adding a CI lint step (FR-019 forbids the latter). Corrections from authoring: - C-002 (badge row composition) initially used `[](...)` Markdown badge regex; the actual badges are `<a href><img></a>` HTML. Fixed to match HTML pattern + alt-text ordering. - C-005 (walkthrough two-block + line budget) added a third sub-check for "≥ 1 recognizable Quadlet unit identifier from `examples/03-immich/services/`" — implements SC-007 directly rather than relying on visual inspection. - C-006 (sanitization stop-list) is the canonical home of the SC-006a regex per `docs/onboarding-script.sh`'s header note. The OSC 3008 caveat (pam_systemd-emitted hostname/machineid leak under sudo) is documented inline with a re-runnable Python post-processor for future re-recordings. - C-010 (asciicast format and duration) verifies SC-005 and SC-005a via `jq '.version'` and `jq '.duration'`. - C-011 (regeneration-script invariants) verifies the executable bit, shebang, and `examples/03-immich` literal occurrences (FR-009 / SC-006). Self-test against post-018 tree: C-001 README ≤ 400 → 297 PASS C-002 badge row → 4 + correct alt order PASS C-003 mental model → line 20 (≤ 120) PASS C-004 Mermaid → 1 block, all substrings PASS C-005 walkthrough → 2 blocks, 25 non-blank, 5 unit IDs PASS C-006 SC-006a → 0 matches PASS C-007 SC-008 → 0 matches PASS C-008 link targets → all resolve PASS C-009 FR-013 → 0 matches PASS C-010 cast format → version=2, duration=4.918944 PASS C-011 script → executable, shebang, 8x literal PASS Verification: $ cargo test 472 passed $ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…inal validate Final pre-merge checks for spec/018. All pass against the post-018 tree (commit 8f3ef28): - T021 (structural): wc -l README.md = 297 (≤ 400, SC-001); 30-second mental-model heading present at line 20 (SC-003); Mermaid block present (SC-004). - T022 (stop-list): 0 matches for hype-flagged terms (SC-008). - T023 (link-resolve): every pre-018 link target (LICENSE, CHANGELOG.md, CODE_OF_CONDUCT.md, docs/development.md, examples/0[1-5]-*) resolves (SC-009). - T024 (no-source-touched, FR-017 carve-out scope): `git diff master..HEAD --stat -- src/ .github/workflows/ examples/ LICENSE` returns empty. Cargo.toml/Cargo.lock and tests/ are excluded per the FR-017 carve-out (governance-driven version bump + mechanical fixture maintenance for FR-001 section renames). - T027 (release-validate): Outcome=passed, Classification=releasable, Required=patch, Declared=patch, Version=patch, CHANGELOG=aligned. Remaining tasks blocked on 24-hour cool-off: - T025 (author self-attestation dogfooding pass) requires ≥ 24 h since the last README edit per Clarification Q4. README was last edited 2026-05-07 ~06:30 UTC (T016 commit 08cd4a7); earliest T025 window opens 2026-05-08 ~06:30 UTC. - T026 (author synthesis.md body) depends on T025's captured cold-read takeaway. - T028 (PR ready-for-review) depends on T025/T026 landing. These three tasks remain `[ ]` in tasks.md and will be picked up in a follow-on session after the cool-off elapses. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rebases onto post-promote master at v2.2.3 (which now contains both spec/018-blocking fixes: PR #35 wired the immich-db-password Podman secret into immich-server.container, and PR #36 introduced ApplyRunDisplayState::Stateless so stateless re-plans no longer flag a healthy host as "(recovery from failed initial apply)"). Re-recording on `core-ops-uat` (Fedora CoreOS guest) against the fixed binary + fixed example produces the truthful narrative the spec/018 walkthrough is supposed to demonstrate: Beat 1 (plan): Plan for host example @ (stateless) (first run) Beat 2 (apply): Apply for host example @ (stateless) (first run) Outcome: converged Beat 3 (replan): Plan for host example @ (stateless) 10 unchanged immich-server reaches `active running` (NRestarts=1) and journal shows "Immich Microservices is running [v2.7.5] [production]" — no auth restart loop. The misleading "(recovery from failed initial apply)" suffix is gone. Cast post-processed to strip OSC 3008 sequences (pam_systemd hostname/machineid leak under sudo) and replace nix-store-path SHELL env value, per decision_018-recording-ssh-delegation. Cast duration 4.80 s, ≤ 90 s SC-005a budget. T013 README walkthrough block updated to keep verbatim fidelity to the new T012 capture: the second fenced block's header and underline now match the corrected output (no "(recovery)" suffix; underline length adjusted from 72 chars to 35 chars to match the shorter title). Block count = 2 (FR-006), combined non-blank lines = 25 (SC-007b), unique unit identifiers = 5 (SC-007). The rebase dropped the prior `chore(release): bump 2.2.1 -> 2.2.2` commit (subsumed by master's PR #34/#35/#36 promotes); spec/018 now bumps `2.2.3 -> 2.2.4` per `packaged_readme_surface` carve-out. Verification: $ cargo test 473 passed $ cargo clippy --all-targets -- -D warnings clean $ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) $ wc -l README.md 297 (≤ 400) PASS SC-001 $ <walkthrough section>: 2 fenced blocks, 25 non-blank lines, 5 unit IDs PASS FR-006/SC-007/SC-007b $ head -n 1 docs/onboarding.cast | jq '.version' 2 PASS SC-005 $ head -n 1 docs/onboarding.cast | jq '.duration' 4.80 (≤ 90) PASS SC-005a $ grep -iE '(not\.one|ulthar|192\.168\.|10\.0\.|172\.16\.)' docs/onboarding.cast docs/onboarding-script.sh (no matches) PASS SC-006a $ grep -c '3008' docs/onboarding.cast 0 PASS FR-009a $ asciinema play docs/onboarding.cast plays end-to-end PASS Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… walkthrough
The pre-existing "play locally with asciinema play" footnote had effective
reach near zero — most operators encounter the project via GitHub and
will not clone the repo + install asciinema to view a recording. The
spec's research.md F1 follow-up explicitly named this gap and proposed
an inline-renderable sidecar; this change promotes F1 from "follow-up"
to in-scope for spec/018 and chooses the highest-friction-removed path:
an animated GIF rendered via `agg` (asciinema-agg) from the same `.cast`
source, embedded inline in the README via standard HTML image syntax
wrapped in an asciinema.org anchor.
Replaces the prior single-line "Recording: [...]" footnote with the
canonical centered-figure pattern (HTML, no JS):
<p align="center">
<a href="https://asciinema.org/a/CAST_ID">
<img src="docs/assets/core-ops-demo.gif" alt="..." width="820">
</a>
</p>
<p align="center">
<a href="...">Watch the full terminal session on asciinema</a>
</p>
The GIF (101 KB, GIF89a, well under SC-005b's 1 MB soft cap) plays inline
on GitHub on first paint with no operator action; the click-through goes
to asciinema.org's full hi-fi player for readers who want pixel-perfect
playback or to copy commands.
Spec amendments (FR-007 / FR-009 / FR-013 / new SC-005b):
- FR-007 expanded: `.cast` remains source-of-truth; `docs/assets/core-ops-demo.gif`
is a derived sidecar produced by `agg` from the same source, regenerated
whenever the cast is re-recorded.
- FR-009 expanded: `docs/onboarding-script.sh` now invokes `agg` after
asciinema and pins both versions in its header (asciinema 2.4.0,
agg 1.7.0).
- FR-013 clarified: the prohibition on third-party JS embeds stays;
standard Markdown / HTML image embeds of the in-tree GIF are
explicitly permitted (no JS, renders everywhere Markdown renders).
The asciinema.org SVG-badge embed pattern is also permitted (static
SVG, not a script).
- SC-005b new: GIF file MUST exist, MUST be a real GIF (`GIF87a`/
`GIF89a` magic), README MUST embed it via image-tag syntax, soft
size cap ≤ 1 MB.
- SC-006a clarified: the same stop-list applies indirectly to the GIF
via the `.cast` source — anything not in the cast cannot appear in
the rendered frames.
Tooling and regeneration:
- `flake.nix`: adds `asciinema-agg` (binary `agg`, version 1.7.0) to
the dev shell. Note: `pkgs.agg` is the unrelated Anti-Grain Geometry
C++ library; don't confuse the two.
- `docs/onboarding-script.sh`: pins agg version, fails fast if agg is
not on PATH, runs `agg --idle-time-limit 2 --quiet $CAST $GIF` after
recording, prints the rendered file's size as a soft-cap proxy.
- `checklists/readme-structure.md` C-011a: new runnable check verifying
GIF existence, magic bytes, size, and README embed.
Operator follow-up: the README anchors `https://asciinema.org/a/CAST_ID`
with `CAST_ID` as a literal placeholder. Once the cast is uploaded to
asciinema.org under the maintainer account (`asciinema auth` then
`asciinema upload docs/onboarding.cast`), the operator substitutes the
real cast ID via a one-line follow-up commit. The local GIF embed
works inline without the substitution; only the click-through anchor
is broken until the upload happens.
Verification:
$ test -f docs/assets/core-ops-demo.gif 0 PASS SC-005b
$ head -c 6 docs/assets/core-ops-demo.gif GIF89a PASS SC-005b
$ wc -c < docs/assets/core-ops-demo.gif 101278 (≤ 1MB) PASS SC-005b
$ grep -E 'docs/assets/core-ops-demo\.gif' README.md | wc -l 1 PASS SC-005b
$ grep -E '(asciinema\.org/.*\.js|<iframe|<script)' README.md | wc -l 0 PASS FR-013
$ wc -l README.md 305 (≤ 400) PASS SC-001
$ cargo test 473 passed
$ cargo clippy --all-targets -- -D warnings clean
$ cargo run --bin core-ops-release -- validate --base-ref master passed (patch)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… playback Operator reported staircase distortion in the rendered cast/GIF: each successive line started indented by the length of the previous line, the classic "LF without CR" pattern. Root cause: the inner recording script piped SSH output through `| sed 's/\r$//'`, which stripped every `\r` that the remote PTY's ONLCR translation had added. The captured cast events therefore contained bare `\n` (line feed only). asciinema 2.4.0 plays casts through a raw-mode local TTY (so it can faithfully replay any escape sequences without double-translation), which means LF stays LF on output — the terminal treats each LF as "down one row" with no column reset, hence the staircase. The original sed filter was probably defensive — line-buffered tools sometimes choke on trailing `\r` — but for asciinema-capture the CRs are essential. Drop the filter and re-record. After re-recording the plan-output event has 124 CRs and 124 LFs (matched), confirming `\r\n` line terminators throughout. `asciinema cat docs/onboarding.cast` now renders left-aligned. The GIF rendered from this cast (`docs/assets/core-ops-demo.gif`, 107 KB GIF89a) displays the correct terminal layout inline on GitHub. Cast re-recorded against the same fixed stack (PRs #34/#35/#36 merged): Beat 1 (plan): Plan for host example @ (stateless) (first run) Beat 2 (apply): Apply for host example @ (stateless) (first run) Outcome: converged Beat 3 (replan): Plan for host example @ (stateless) 10 unchanged Same OSC 3008 strip + SHELL sanitize post-processing applied (per decision_018-recording-ssh-delegation). Duration 4.88 s, well under SC-005a's 90 s budget. Verification: $ head -n 1 docs/onboarding.cast | jq '.version' 2 $ head -n 1 docs/onboarding.cast | jq '.duration' 4.88012 (≤ 90) $ grep -c '3008' docs/onboarding.cast 0 $ grep -iE '(not\.one|ulthar|192\.168\.|10\.0\.|172\.16\.)' docs/onboarding.cast docs/onboarding-script.sh (no matches) $ asciinema cat docs/onboarding.cast | head -3 left-aligned, no staircase $ wc -c < docs/assets/core-ops-demo.gif 106777 (≤ 1 MB) The non-tracked recording driver `/tmp/onboarding-inner.sh` carried the buggy sed pipe in this session; the canonical `docs/onboarding-script.sh` does NOT have a sed filter (its inner `demo()` runs commands directly via `eval`, not through SSH delegation). The bug therefore lives only in the SSH-delegation recording procedure documented in decision_018-recording-ssh-delegation, not in the canonical regeneration script. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #37 (refactor(apply): unify init'd and stateless dispatch behind ApplyTarget) landed on master and the post-merge promote tagged v2.2.4. The fix delivers the spec/006 streaming output to stateless mode, which is the prerequisite spec/018's recording was waiting on. Bump 2.2.4 -> 2.2.5 (`packaged_readme_surface` carve-out; provenance-state fixture pinned in lock-step). FR-007 amendments: - The recording is now **apply-only**. The static plan-output and idempotent-re-run blocks in the README walkthrough section (per FR-006) are the canonical source of plan/re-plan content; including those beats in the recording adds duration without motion. The 90s budget is preserved for the apply step where the line-by-line streaming output now matters. - The recording MUST be produced on a host where `core-ops` runs natively (not via SSH delegation). SSH transport (even with `-t` PTY allocation) collapses the streaming timing that the recording is meant to capture; SSH-delegated recording is explicitly out of spec going forward. The decision file decision_018-recording-ssh-delegation captures the prior procedure as a session-3 historical artifact, not a forward recipe. Tooling amendment: - `docs/onboarding-script.sh` now records a single beat (apply only) instead of the prior plan -> apply -> re-plan trio. The command sequence in the BASH heredoc is one `demo 'sudo core-ops apply --source-repo examples/03-immich --host example'` invocation. Header rewritten to match. The actual cast + GIF re-recording is the operator's next step, to be done natively on a host with `core-ops` 2.2.5 + asciinema 2.4.0 + agg 1.7.0 + the repo present (or an equivalent on-host setup). The current `docs/onboarding.cast` and `docs/assets/core-ops-demo.gif` remain in tree from the prior SSH-delegated session-3 work and will be replaced once the operator records natively. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
c37fe6e to
4c37637
Compare
…s v3 Operator re-recorded `docs/onboarding.cast` natively against the PR #37 fix (core-ops 2.2.5 with stateless streaming). Duration 4.97 s. The recording captures the line-by-line "creating... → created" progression that asciinema 3.x's PTY observation preserves end-to-end — exactly the UX FR-007 was rewritten to require, and the SSH-delegation procedure was unable to capture. Cast was produced by asciinema 3.x, which writes asciicast v3 by default. Spec amendments to accommodate: - FR-008: now accepts asciicast v2 OR v3. Both are rendered by `agg` 1.7.0 and played by asciinema.org. The header MUST declare `"version": 2` or `"version": 3`. - SC-005: same — version MUST be 2 or 3. - SC-005a: duration calculation now branches on version. v2 has an absolute `duration` header field; v3 events are `[delta, type, data]` triples and total duration = sum of all deltas. Either MUST be ≤ 90. - Checklist C-010 updated with the version-branching one-liner. Post-recording sanitization (per decision_018-recording-ssh-delegation and checklist C-006): - OSC 3008 sequences stripped from event data (pam_systemd-emitted `hostname=core-ops-uat`, `machineid=...`, PID metadata under sudo). The post-processor is v3-aware (event shape is identical to v2; header schema differs but the SHELL/duration handling is unchanged for our purposes). - nix-store-path SHELL env value cleaned to `/bin/bash`. GIF re-rendered from the sanitized cast: 56 KB GIF89a, well under SC-005b's 1 MB soft cap. Verification: $ head -1 docs/onboarding.cast | jq '.version' 3 $ awk 'NR>1' docs/onboarding.cast | jq -s 'map(.[0]) | add' 4.965 (≤ 90) PASS SC-005a $ grep -c '3008' docs/onboarding.cast 0 PASS FR-009a $ grep -iE '(not\.one|ulthar|192\.168\.|10\.0\.|172\.16\.)' docs/onboarding.cast docs/onboarding-script.sh (no matches) PASS SC-006a $ head -c 6 docs/assets/core-ops-demo.gif GIF89a PASS SC-005b $ wc -c < docs/assets/core-ops-demo.gif 56923 (≤ 1MB) PASS SC-005b $ cargo run --bin core-ops-release -- validate --base-ref master passed (patch) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two operator-driven changes wrapped together: - Substitute the CAST_ID placeholder with the asciinema.org-uploaded cast (https://asciinema.org/a/XKhpmzM8ZWg56Wu2). Both the GIF-anchor `<a href>` and the secondary "Watch the full terminal session on asciinema" link resolve. Visitors get inline motion via the GIF on first paint and an optional click-through to the hi-fi asciinema.org player. - Operator-driven section reorder of README.md (no FR-001 ordering change required by spec — operator's reordering reflects how the walkthrough flows when reading top-to-bottom). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Operator manually re-recorded `docs/onboarding.cast` with the
paginated plan beat folded in alongside the apply step (the kind
of UX a future built-in pager would deliver — see follow-up
discussion). Duration 13.36 s, comfortably inside SC-005a's 90 s
budget.
Cast ID on asciinema.org rotated XKhpmzM8ZWg56Wu2 -> HaqIw05gehGk2YpH
(both `<a href>` anchors in the README walkthrough section now point
at the new upload).
Same post-recording sanitization applied as the prior cast (per
checklist C-006 and decision_018-recording-ssh-delegation):
- 4 OSC 3008 session-tracking sequences stripped from event data
(pam_systemd-emitted `hostname=core-ops-uat`, `machineid=...`,
PID metadata under sudo).
- SHELL env scrubbed of nix-store path.
GIF re-rendered from the sanitized cast: 755 KB GIF89a 1315×918,
under SC-005b's 1 MB soft cap.
Verification:
$ head -1 docs/onboarding.cast | jq '.version' 3
$ awk 'NR>1' docs/onboarding.cast | jq -s 'map(.[0]) | add' 13.358 (≤ 90) PASS SC-005a
$ grep -c '3008' docs/onboarding.cast 0 PASS FR-009a
$ grep -iE '(not\.one|ulthar|192\.168\.|10\.0\.|172\.16\.)' docs/onboarding.cast docs/onboarding-script.sh
(no matches) PASS SC-006a
$ head -c 6 docs/assets/core-ops-demo.gif GIF89a PASS SC-005b
$ wc -c < docs/assets/core-ops-demo.gif 754920 (≤ 1MB) PASS SC-005b
$ grep -c 'asciinema.org/a/HaqIw05gehGk2YpH' README.md 2 PASS cast linked
$ cargo run --bin core-ops-release -- validate --base-ref master passed (patch)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
External cold readers (non-CoreOps audience) found the prior structure hard to parse. Operator authored a leaner, plain-language pass (305 -> 211 lines) ahead of a second cold-read round. Captures friend feedback as the effective T025 dogfooding signal; synthesis.md entry and any FR/SC amendments follow in subsequent commits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Operator-side dev tooling for spec/018-adjacent JS/web work. Not consumed by the Rust build; devshell-only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/onboarding-script.shregeneration entry point for the (forthcoming)docs/onboarding.cast.Status
Draft. Landed: T001–T010 (US1 MVP), T003 (foundational), T017–T018 (US3, pending render verification on this preview).
Pending: T011–T016 (US2 walkthrough + cast recording), T020 (US4 checklist), T021–T028 (polish + dogfooding + ready-for-review).
Spec: specs/018-adoption-readiness/spec.md · Tasks: tasks.md
Test plan
core-ops-release validate --base-ref masterpassessrc//tests//examples//LICENSE/Cargo.lock/.github/workflows/modifications🤖 Generated with Claude Code