Guidelines

Canon URL Stability Guideline

**Version: v1** **Applies to: every file that cites a `https://canon.gyrum.ai/(principles|guidelines|decisions)/<slug>` URL — Markdown docs, source code comments, shell wrappers, gate failure messages, prompt snippets, ticket bodies.**

v1

Canon URL Stability Guideline

Version: v1 Applies to: every file that cites a https://canon.gyrum.ai/(principles|guidelines|decisions)/<slug> URL — Markdown docs, source code comments, shell wrappers, gate failure messages, prompt snippets, ticket bodies.

This guideline is the operational rule body that the upcoming structural canon-url-resolves gate (warp#3722) enforces. It is the meta-tier expression of the triple-derive contract (ADR-185) — every URL the fleet cites is a promise that the cited content exists. PRs touching files in scope cite Guideline: canon-url-stability@v1 in the PR body so persona reviewers (ADR-115) verify against this exact version.

Rule

Every canon URL of the form https://canon.gyrum.ai/(principles|guidelines|decisions)/<slug> cited in a PR diff, ADR body, CLAUDE.md section, gate failure message, prompt snippet, or ticket body MUST resolve to HTTP 200 (or 308 → 200) before merge.

The canon site serves guidelines / principles / decisions via canonical slugs. A 308 → 200 chain (the site's canonical-slug redirect to the final URL) counts as resolved. Any other status — 301 to an unrelated path, 404, 410, 5xx — fails the gate.

A consumer file that cites a canon URL must satisfy ONE of the following:

  1. URL resolves now. curl -fsS -o /dev/null -w '%{http_code}' <url> returns 200 or 308. This is the default and dominant case.

  2. Companion-PR marker. The cited line carries an immediately-preceding HTML comment <!-- canon-url-pending: warp#NNN --> (or <!-- canon-url-pending: warp#NNN — <short reason> -->) referencing an open canon-side sister ticket in ready / claimed / in_progress state on gyrum-labs/canon. The marker applies to the next non-blank line only.

  3. Audited skip flag. gyrum-review-pr --skip-canon-url-resolves "<reason ≥ 30 chars>" was invoked, the reason was logged to ~/.gyrum/admin-overrides.log, and the PR body carries the same reason in the ## Audited overrides section.

The rule applies regardless of citation medium — Markdown links, bare prose URLs, shell-script heredocs, Go string literals, Svelte <a href> attributes, YAML field values, ticket-body links. The gate scans textually; the language of the surrounding code is irrelevant.

Why

Today's empirical evidence: the fleet's gate-failure messages, persona reviewer prompts, and CLAUDE.md sections increasingly cite https://canon.gyrum.ai/... URLs as the canonical "what this gate enforces / why this rule exists" reference. The pattern relies on a trust contract — when an agent or operator clicks the cited URL, the cited content is there. The contract is load-bearing in three places:

  1. Gate failure messages. Every structural gate's refusal message points at the canon URL for the rule body (see canon-extension-discipline, single-prop-render, filter-vs-metric, calm-first-cta, svelte-component). An agent reading a refusal message expects the cited URL to explain the rule and the override criteria; a 404 leaves the agent guessing.

  2. Prompt snippets. Per ADR-185, the persona reviewers (ADR-115) and type: claude steps (ADR-109) receive the guideline's prompt_snippet field with a trailing "Full rule: ". A broken URL turns the prompt into a partial-context call.

  3. Documentary cross-links. CLAUDE.md, ADRs, and ticket bodies cite canon URLs as the "authoritative source" for fleet-wide rules. The whole reason canon is the central authority is that it's reachable; a non-resolving URL silently demotes canon to "wherever the prose used to live."

The failure-mode rate-of-incidence is non-zero and grows: warp#3709 already documented a sync-content data-loss path where canon docs disappeared during a routine sync (the V94 backup-first fix at PR#103); separately, a canon URL cited in a CLAUDE.md section can outlive the slug if the doc is renamed or hierarchically reorganised. Without a structural gate, the only signal is "an agent clicked the link and got 404," which is invisible until someone notices.

This guideline forces every PR that cites a canon URL to either (a) confirm the URL resolves now, (b) mark the citation as companion-PR-pending with a tracked sister ticket, or (c) burn an audited override that names why the citation is intentionally pointing at a non-resolving URL. The 404-as-fix-hint failure mode the upcoming canon-url-resolves gate (warp#3722) prevents is the one this guideline exists to retire.

Examples — passes

URL resolves now (the dominant case):

See [canon extension discipline](https://canon.gyrum.ai/guidelines/canon-extension-discipline)
for the consumer-tier CSS rule.

The cited URL returns 200 (or 308 → 200); the gate clears silently.

Companion-PR marker referencing an open sister ticket:

The triple-derive trust contract is documented at
<!-- canon-url-pending: warp#3717 — meta-doc lands in companion PR -->
[canon.gyrum.ai/principles/triple-derive](https://canon.gyrum.ai/principles/triple-derive).

The gate sees the canon-url-pending marker on the immediately-preceding line, resolves warp#3717 against the warp API, confirms it's in ready / claimed / in_progress on gyrum-labs/canon, and accepts the citation.

Audited skip — only when the citation genuinely needs to point at a non-resolving URL (e.g. a historical reference for an archived deprecation note):

<!-- PR body section: ## Audited overrides
     --skip-canon-url-resolves "archived deprecation note;
     cites historical canon URL for the v0.x guideline that was
     superseded by v1; URL intentionally points at the retired
     slug for audit-trail completeness." -->
The pre-v1 rule body once lived at
https://canon.gyrum.ai/guidelines/legacy-canon-extension (retired 2026-03-01).

Gate-failure message embedding a canon URL (passes because the URL is the live guideline that explains the gate):

echo "Fix: see https://canon.gyrum.ai/guidelines/canon-url-stability"

Examples — fails

URL returns 404, no marker:

<!-- FAILS — cited URL returns 404, no companion-PR marker, no audited skip -->
See https://canon.gyrum.ai/guidelines/some-rule-that-doesnt-exist for details.

URL returns 410 (gone — slug retired):

<!-- FAILS — cited URL was retired; either restore the slug or update the citation -->
The old rule lived at https://canon.gyrum.ai/guidelines/retired-rule-name.

Companion-PR marker references a closed ticket:

<!-- FAILS — marker references warp#1234 which is in 'done' state -->
<!-- canon-url-pending: warp#1234 -->
See [my-rule](https://canon.gyrum.ai/guidelines/my-rule) for the body.

Companion-PR marker references a non-canon-repo ticket:

<!-- FAILS — marker references warp#5678 on devtools repo, not gyrum-labs/canon -->
<!-- canon-url-pending: warp#5678 -->
See [my-rule](https://canon.gyrum.ai/guidelines/my-rule) for the body.

Marker on the wrong line (must be immediately-preceding):

<!-- FAILS — marker not on the immediately-preceding line -->
<!-- canon-url-pending: warp#3717 -->

See [my-rule](https://canon.gyrum.ai/guidelines/my-rule) for the body.

Audited skip with generic reason:

<!-- FAILS — reason text is generic ("temporary"); audit rejects -->
<!-- PR body: --skip-canon-url-resolves "temporary" -->
See https://canon.gyrum.ai/guidelines/will-add-later for the body.

Path forward when the cited URL doesn't yet resolve

Path A — companion canon-side PR (default)

When you are authoring a new structural rule, gate, or principle that needs a canon meta-doc, ship the canon-side doc FIRST:

  1. File a canon-side ticket: warp-add with repo: gyrum-labs/canon.
  2. gyrum-start-work canon-<slug>-meta-doc --ticket warp#NNN in the canon repo.
  3. Author the doc at content/guidelines/<slug>.md (or content/principles/<slug>.md or content/decisions/<n>-<slug>.md).
  4. gyrum-review-prgyrum-complete-pr.
  5. Confirm curl -fsS -o /dev/null -w '%{http_code}' https://canon.gyrum.ai/<path>/<slug> returns 200 or 308.
  6. THEN merge the citing PR (devtools, dark-factory, ai-frontend, etc.).

This is the dominant path. The canon site re-deploys on merge to main; the URL resolves within minutes.

Path B — sister-ticket marker for in-epic concurrent work

When the citation + canon-side meta-doc are part of the same epic and must ship in parallel (typically because the gate-side and meta-doc-side are interlocked), mark the citing line with the companion-PR marker:

<!-- canon-url-pending: warp#NNN -->
See [my-rule](https://canon.gyrum.ai/guidelines/my-rule) for the body.

The warp#NNN ticket MUST be:

  • Filed on gyrum-labs/canon (the gate verifies repo field).
  • In ready / claimed / in_progress state (the gate refuses on done / cancelled / blocked — closed tickets indicate the citation should already resolve OR the canon-side work was abandoned, both of which need a new ticket).

Once the canon-side PR merges and the URL resolves, file a sweeper to remove the marker on the consumer side — the marker is debt, not a permanent annotation. (The closed-loop sweeper auto-files a retirement ticket on the consumer side when the canon-side sister-ticket closes; the consumer PR removes the marker + re-runs the gate to confirm.)

Audited override

gyrum-review-pr --skip-canon-url-resolves "<reason ≥ 30 chars>" — logged to ~/.gyrum/admin-overrides.log per the audit-on-override convention. Use ONLY when the citation genuinely needs to point at a non-resolving URL:

  • Historical reference in an archived deprecation note where the URL pointing at the retired slug is the entire point of the citation.
  • External canon reference where the URL is canon.gyrum.ai shape but documents a fleet that is intentionally not running (e.g. a sandbox fork's archived canon).
  • Operator-only debug shim that cites a non-resolving URL for diagnostic reasons known to the operator.

The reason text MUST name (a) why the citation cannot point at a resolving URL and (b) what makes the non-resolution intentional rather than oversight. Generic reasons ("temporary", "will fix later", "not in scope", "doesn't matter") are rejected by the operator audit.

The skip flag does NOT apply to canon URLs in gate failure messages or persona reviewer prompts — those MUST resolve. A gate citing a 404 in its failure message is the exact failure mode the gate exists to prevent; the skip flag refuses on triggers.files matching **/canon-*-gate.sh, library/prompts/**, or **/gate_failure_template.

PR body citation

Required line in the PR body when changing files in scope (any file that cites a canon URL):

Guideline: canon-url-stability@v1

The persona reviewer (ADR-115) fetches this exact version and verifies the implementation against this text. Bumping the version is a separate PR through gyrum-revise-guideline canon-url-stability that includes a regression-corpus re-run.

Revision process

This document is versioned. Updates ride gyrum-revise-guideline canon-url-stability (separate devtools wrapper, separate ticket). Hand-edits without that wrapper skip the regression suite. The regression corpus at regression-corpus/guidelines/canon-url-stability/ includes one fixture per pass / fail example above plus an end-to-end fixture that runs the gate against a synthetic PR diff containing 12 canon URLs of mixed resolve / 404 / 308 / 410 / companion-PR-marker shapes.

References