Skip to content

[AAASM-3757] 👷 (aggregate): Harden version-set verify gate, hermetic channel seed, shared go TOML#43

Merged
Chisanan232 merged 4 commits into
mainfrom
v0.0.1/AAASM-3757/aggregator_hardening
Jun 25, 2026
Merged

[AAASM-3757] 👷 (aggregate): Harden version-set verify gate, hermetic channel seed, shared go TOML#43
Chisanan232 merged 4 commits into
mainfrom
v0.0.1/AAASM-3757/aggregator_hardening

Conversation

@Chisanan232

Copy link
Copy Markdown
Contributor

Description

Three non-blocking hardening fixes to the docs-hub aggregator
(docs/scripts/aggregate.sh), surfaced while reviewing #42. No change to the
aggregated output for the current tag set; all three close silent-failure gaps
that could ship a partial/stale/broken version switcher.

  1. Count-floor verify gate. The archived-set gate asserted only ≥1 dir per
    module, so a partial multi-tag rebuild (some tags built, others silently
    dropped) still shipped a truncated dropdown. Each build now records the tags
    that must produce a snapshot in expected-archived.txt (core: every
    release tag that ships docs; go-sdk: every valid semver tag, identical to
    archived[] in versions.toml) and the gate fails the build if any expected
    tag's /<tag>/index.html is missing.
  2. Hermetic core channel-pointer seed. build_core seeded the moving
    pre-release/stable pointers via a live curl of the deployed versions.json
    — non-hermetic and silently non-fatal (could ship stale/empty pointers). They
    are now derived from the rebuilt git tags using core's own semver logic
    (docs/ci/channels.py); no build-time network dependency, and a channel can
    only point at a tag actually rebuilt. build_versions.py still applies the
    pre-release gate.
  3. Go versions.toml serializer guard. go-sdk reuses its channel logic
    (versions_channels.py, already imported) but exposes no reusable TOML
    serializer — it lives inline in docs-site.yml, so build_go's emit step
    is a hand-kept mirror. Documented as such and added a tomllib parse check
    so a serializer drift into malformed output fails the build loudly.

AGGREGATION.md updated to reflect all three.

Type of Change

  • 🐛 Bug fix (correcting inaccurate or missing content)
  • 🔧 Configuration / CI change

Related Issues

Documentation Checklist

  • AGGREGATION.md updated to match the hardened behavior
  • Commits follow GitEmoji convention and are small / atomic
  • Validated locally (see below)

How to verify

Ran the edited functions against fresh full clones of agent-assembly (13 tags)
and go-sdk (8 tags):

  • build_core/core/{latest,<13 tags>}/ + versions.json with channels
    latest + pre-release (v0.0.1-beta.4) derived without any curl;
    archived[] = 13. Gate verify_archived_set core13/13 PASS.
  • Partial-set test: hid one tag dir → gate aborts with
    Partial archived set for core/: 12/13 ... missing: v0.0.1-beta.2. Restored → PASS.
  • build_go → 8 archived tag dirs + latest + pre-release; recomputed
    versions.toml parses via tomllib (10 entries); gate verify_archived_set go-sdk8/8 PASS.
  • Served public/ and confirmed HTTP 200 for /core/latest/,
    /core/versions.json, /go-sdk/latest/, /go-sdk/<tag>/, /go-sdk/pre-release/;
    core manifest lists all 13 archived tags, go selector lists all 8 — no
    regression to [AAASM-3753] ✨ (aggregate): Mirror core & go-sdk archived versions into hub switcher #42.

Closes AAASM-3757

🤖 Generated with Claude Code

https://claude.ai/code/session_01Cc1vBBiNxp9qLKQ5Gq85w8

Chisanan232 and others added 4 commits June 26, 2026 01:45
The verify gate asserted only >=1 archived dir per module, so a partial
multi-tag rebuild could silently ship a truncated version dropdown. Record
every tag that must produce a snapshot (core: release tags shipping docs;
go-sdk: every valid semver tag) in expected-archived.txt and fail the build
if any expected tag's /<tag>/index.html is missing.

Refs AAASM-3757

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cc1vBBiNxp9qLKQ5Gq85w8
build_core seeded the moving pre-release/stable channel pointers via a live
curl of the deployed versions.json — non-hermetic and silently non-fatal, so
a failed fetch shipped stale or empty pointers. Derive them from the rebuilt
git tags using core's own semver logic (docs/ci/channels.py) instead; no
build-time network dependency, and a channel can only point at a tag that was
actually rebuilt. build_versions.py still applies the pre-release gate.

Refs AAASM-3757

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cc1vBBiNxp9qLKQ5Gq85w8
…r mirror

build_go inlines the versions.toml serializer because go-sdk exposes its
channel logic (versions_channels.py, already reused) but not its TOML
serializer, which lives only inside docs-site.yml. Document that the emit step
is a hand-kept mirror of that workflow and add a tomllib parse check so a
serializer drift into malformed TOML fails the build loudly instead of
shipping a broken version selector.

Refs AAASM-3757

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cc1vBBiNxp9qLKQ5Gq85w8
…er guard

Reflect the AAASM-3757 hardening: the verify gate now asserts the full
expected archived set (count-floor, catches partial dropdowns); core channel
pointers are derived hermetically from git tags (no network curl); and the go
versions.toml serializer is documented as a docs-site.yml mirror that is
parse-checked with tomllib.

Refs AAASM-3757

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cc1vBBiNxp9qLKQ5Gq85w8
@Chisanan232

Copy link
Copy Markdown
Contributor Author

🔎 Claude Code review — aggregator hardening (AAASM-3757)

CI: Green. Aggregate all module docs (the real end-to-end build) PASS 1m10s, SonarCloud PASS; Deploy to GitHub Pages correctly skipped on PR. The passing aggregate run means the new count-floor gate ran against the live tag set and did not falsely fail.

Scope vs AAASM-3757: All 3 items delivered. (1) Count-floor verify gate: verify_archivedverify_archived_set, asserting the full expected-archived.txt set and failing on any missing /<tag>/index.html (partial, not just empty). (2) Hermetic core channel seed: live curl of deployed versions.json replaced by derivation from rebuilt git tags via core's own docs/ci/channels.py (parse_version/compare_versions); build_versions.py still applies the pre-release gate. (3) Go TOML guard: tomllib parse-check after the inline serializer. Note: item 3's ideal (reuse a shared serializer) was not achievable — go-sdk exposes no reusable TOML serializer (it lives inline in its docs-site.yml), so the implementer took the documented fallback (clarifying comment + parse guard). Reasonable given the constraint; flagging only as a scope caveat, not a defect.

Side-effects / regression: NONE.

  • Count-floor over-assert (the key risk): no. The expected-set uses the same filter as the build loop in both modules. Core records a tag in expected-archived.txt inside the [[ -f docs/book.toml ]] branch — the exact condition that gates whether mdbook is even attempted, so a pre-docs tag (no book.toml) is never expected. Go writes expected-archived.txt from the same tag_set that seeds archived[] / drives build_all_versions.sh. So expected == built-set by construction; the gate can only fire on a genuine partial drop, never on a legitimately-skipped tag. Confirmed empirically by the green aggregate run (13/13 core, 8/8 go) plus the author's partial-set test (hid one dir → Partial archived set ... missing: v0.0.1-beta.2).
  • Hermetic pointers match prior: the deployed manifest the old curl fetched was itself produced by the same channels.py semver logic, so deriving from the current rebuilt tags reproduces the same computation — and strictly improves it (self-healing, a channel can only point at a tag actually rebuilt). CI shows pre-release=v0.0.1-beta.4 (newest pre-release) — sane; no stale/empty regression.
  • Go guard non-destructive: reads the already-written file, raises only on unparseable TOML or zero [[versions]] entries; does not alter emitted content.
  • No regression to [AAASM-3752] 🐛 (aggregate): Restore per-module version switcher in docs hub #41/[AAASM-3753] ✨ (aggregate): Mirror core & go-sdk archived versions into hub switcher #42: redirects, /latest/, full core/go version sets, node/python/hub trees and Pagefind scoping are untouched (outside the diff); the latest/manifest gate checks are unchanged.

Readiness: Ready to approve & merge. Purely additive hardening — tighter gate + removed network dependency, no behavior change for the current tag set.

— Claude Code (automated PR review, 2026-06-26)

@Chisanan232 Chisanan232 merged commit 0f721ec into main Jun 25, 2026
3 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-3757/aggregator_hardening branch June 25, 2026 18:05
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant