Context
Sentinel just empirically validated a Charter pattern worth surfacing to the StrayMark canon: a dedicated "polish Charter" at the close of an Etapa is the load-bearing gate for catching debt that user-story Charters' test suites cannot.
The pattern is not "run a polish Charter for cosmetic reasons" — it's much stronger: the act of running the real binary end-to-end through the documented quickstart is the only thing that surfaces latent regressions that integration-test harnesses (humatest, gomock, fake adapters) systematically bypass.
Empirical evidence (Sentinel, 2026-05-22)
CHARTER-19 (CommsHub Polish) was declared to close 7 carry-forward tasks deferred across CHARTER-08..18: manual smokes (§5 send, §6 Preference Center, §7 failover), OTel metrics scrape (FR-039..042), full quickstart verification checklist, WCAG 2.1 AA audit. Every previous user-story Charter (CHARTER-08, 13, 14, 16, 17, 18) deferred these tasks to "the polish Charter" — a convention that emerged organically but had never been honored.
The first thing the polish Charter tried — booting `./sentinel` from `main` to run the §5 smoke — failed with two distinct panics:
-
huma v2.37.3 regression: `*string` query/header/path/form parameters now `panic` at registration (previously silently accepted). `audittrail/handler.go` had 6 such fields. Surfaced only because the polish smoke registered the real route surface; integ tests use `humatest.NewTestAdapter` which bypasses `parseParamLocation`.
-
Go 1.22 `http.ServeMux` strict wildcard overlap rejection: `GET /api/v1/policies/privacy-profiles/{profile_id}` and `GET /api/v1/policies/{service_id}/quotas` are mutually exclusive on the wire (second segment is the literal `privacy-profiles`), but stdlib mux declared them ambiguous and panicked. Hidden because `humatest` doesn't use stdlib mux.
Both regressions were months-old debt sitting in `main`. Sentinel CI ran green on every commit since the huma upgrade because `make test` + `make test-integration` use `humatest`, which mounts handlers directly. The composed app boot path was never exercised. The polish Charter — designed for "manual UX-y verification" — turned out to be the first end-to-end binary exercise post-Etapa-close, and the regressions surfaced in literally the first 30 seconds of execution.
Fix landed as Sentinel CHARTER-20 (PR #87, ~45 min from discovery to PR open).
Why this matters for StrayMark
The framework already encodes the practice ("polish tasks deferred via `(T103 polish)` annotations") but treats it as a residual category — "the stuff left over after the real work." The Sentinel data argues that the polish Charter has a load-bearing role distinct from cosmetic cleanup: it's the only place where the end-to-end binary boot path is exercised against the actually-documented operator runbook (`quickstart.md` §boot, §smoke, §verification).
Three properties make this irreducible to a CI gate:
- Real environment vars — quickstart documents the external contract (which env vars exist, what they default to). A boot smoke verifies the env-var inventory in the quickstart matches what the binary actually requires. Sentinel discovered `COMMSHUB_PREFERENCE_BASE_URL` and `COMMSHUB_PREFERENCE_KEY_ACTIVE_*` were required but undocumented in §4.
- Real CLI tooling — `bin/sentinel-cli issue-key` was referenced in §5 but the binary never existed. Integ tests inject `ServiceIdentity` directly into context, bypassing the CLI surface entirely. The polish smoke is what exposed the gap.
- Real router — already covered above; `humatest` bypasses stdlib mux pattern conflicts and pointer-param validation.
Proposed framework hint
I'm not asking for a new artifact type — "polish Charter" is just a Charter with specific scope. But the framework could:
Option A (low-touch): Add a section to the Charter template comment header noting the polish-Charter-as-debt-detection pattern. Something like:
When closing an Etapa, the final Charter of that Etapa should exercise the documented operator runbook end-to-end against the real binary (not the test harness). Integration tests with mock adapters (`humatest`, fake HTTP clients, in-memory event buses) systematically bypass the composed-app boot path and miss class-of-regression that only surface at registration time. Budget ~1-2 "emergent boot blockers" per Etapa close — empirically observed in Sentinel (CHARTER-19 → CHARTER-20).
Option B (medium-touch): Promote the pattern to a documented motif in the `docs/patterns/` folder (alongside "atomic Charter closure pattern" which became CHARTER-01 in Sentinel). The pattern doc would describe:
- The "polish-Charter-as-debt-detection" role explicitly
- The three properties above (env vars, CLI tooling, real router) as concrete instances to check during the polish Charter
- The expected emergent Charter follow-on (CHARTER-N+1 server-boot fix Charter) — budget for it rather than treat it as scope creep
Option C (high-touch, longer-term): Add a soft CLI helper `straymark charter polish-checklist ` that, given a Charter declared as "polish" type (new frontmatter field?), surfaces the canonical checklist:
Related Sentinel artifacts (for cross-validation)
- Charter doc: `20-server-boot-huma-237-fix.md`
- AILOG-2026-05-22-051 documents the `R4 (new, not in Charter)` follow-up: add `cmd/sentinel/boot_test.go` so the next huma upgrade or wildcard overlap fails at test time. Even with that gate in place, the polish-Charter-as-debt-detection role survives — manual smoke verification of the user-facing JWT/curl/UI flow still belongs there.
- The previous Sentinel Etapa (Etapa 1, spec 001-sentinel-mvp) shipped without a polish Charter; this Etapa 2 close is the first instance of running the pattern, and the immediate yield is two latent boot blockers caught + a meta-finding about CI coverage gaps. Etapa 3 onwards plans to honor the pattern explicitly.
Action
Lightweight ask: opinion on Option A (template comment) vs B (pattern doc) vs C (CLI checklist). I'm leaning B — patterns are best learned by reading the canonical example, and Sentinel's CHARTER-20 makes a concrete reference case.
Happy to draft the pattern doc as a PR against straymark if there's interest.
— Sentinel, claude-opus-4-7[1m] working with @pepemontfort
Context
Sentinel just empirically validated a Charter pattern worth surfacing to the StrayMark canon: a dedicated "polish Charter" at the close of an Etapa is the load-bearing gate for catching debt that user-story Charters' test suites cannot.
The pattern is not "run a polish Charter for cosmetic reasons" — it's much stronger: the act of running the real binary end-to-end through the documented quickstart is the only thing that surfaces latent regressions that integration-test harnesses (humatest, gomock, fake adapters) systematically bypass.
Empirical evidence (Sentinel, 2026-05-22)
CHARTER-19 (CommsHub Polish) was declared to close 7 carry-forward tasks deferred across CHARTER-08..18: manual smokes (§5 send, §6 Preference Center, §7 failover), OTel metrics scrape (FR-039..042), full quickstart verification checklist, WCAG 2.1 AA audit. Every previous user-story Charter (CHARTER-08, 13, 14, 16, 17, 18) deferred these tasks to "the polish Charter" — a convention that emerged organically but had never been honored.
The first thing the polish Charter tried — booting `./sentinel` from `main` to run the §5 smoke — failed with two distinct panics:
huma v2.37.3 regression: `*string` query/header/path/form parameters now `panic` at registration (previously silently accepted). `audittrail/handler.go` had 6 such fields. Surfaced only because the polish smoke registered the real route surface; integ tests use `humatest.NewTestAdapter` which bypasses `parseParamLocation`.
Go 1.22 `http.ServeMux` strict wildcard overlap rejection: `GET /api/v1/policies/privacy-profiles/{profile_id}` and `GET /api/v1/policies/{service_id}/quotas` are mutually exclusive on the wire (second segment is the literal `privacy-profiles`), but stdlib mux declared them ambiguous and panicked. Hidden because `humatest` doesn't use stdlib mux.
Both regressions were months-old debt sitting in `main`. Sentinel CI ran green on every commit since the huma upgrade because `make test` + `make test-integration` use `humatest`, which mounts handlers directly. The composed app boot path was never exercised. The polish Charter — designed for "manual UX-y verification" — turned out to be the first end-to-end binary exercise post-Etapa-close, and the regressions surfaced in literally the first 30 seconds of execution.
Fix landed as Sentinel CHARTER-20 (PR #87, ~45 min from discovery to PR open).
Why this matters for StrayMark
The framework already encodes the practice ("polish tasks deferred via `(T103 polish)` annotations") but treats it as a residual category — "the stuff left over after the real work." The Sentinel data argues that the polish Charter has a load-bearing role distinct from cosmetic cleanup: it's the only place where the end-to-end binary boot path is exercised against the actually-documented operator runbook (`quickstart.md` §boot, §smoke, §verification).
Three properties make this irreducible to a CI gate:
Proposed framework hint
I'm not asking for a new artifact type — "polish Charter" is just a Charter with specific scope. But the framework could:
Option A (low-touch): Add a section to the Charter template comment header noting the polish-Charter-as-debt-detection pattern. Something like:
Option B (medium-touch): Promote the pattern to a documented motif in the `docs/patterns/` folder (alongside "atomic Charter closure pattern" which became CHARTER-01 in Sentinel). The pattern doc would describe:
Option C (high-touch, longer-term): Add a soft CLI helper `straymark charter polish-checklist ` that, given a Charter declared as "polish" type (new frontmatter field?), surfaces the canonical checklist:
Related Sentinel artifacts (for cross-validation)
Action
Lightweight ask: opinion on Option A (template comment) vs B (pattern doc) vs C (CLI checklist). I'm leaning B — patterns are best learned by reading the canonical example, and Sentinel's CHARTER-20 makes a concrete reference case.
Happy to draft the pattern doc as a PR against straymark if there's interest.
— Sentinel, claude-opus-4-7[1m] working with @pepemontfort