diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e515217..c32b414 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,6 +83,14 @@ jobs: # stops flagging itself as a mirror (DOC-01..09). Toolchain-free. run: ./tools/check-doc-truthing.sh + - name: Issue #176 — over-claim ratchet (DOC-08/09) + # Companion to the banner guard above (DOC-16): a frozen-baseline + # ratchet that fails any *new* backend-breadth / "production-ready" + # / stdlib-% phrase beyond tools/doc-overclaims.allow — the + # DOC-08/09 detection the banner guard deliberately leaves to bots. + # Toolchain-free. See tools/check-doc-overclaims.sh (DOC-17). + run: ./tools/check-doc-overclaims.sh + - name: Check formatting run: opam exec -- dune build @fmt diff --git a/.machine_readable/6a2/STATE.a2ml b/.machine_readable/6a2/STATE.a2ml index ea7a5ee..f97f4b2 100644 --- a/.machine_readable/6a2/STATE.a2ml +++ b/.machine_readable/6a2/STATE.a2ml @@ -9,6 +9,7 @@ status = "active" authoritative-status-doc = "docs/CAPABILITY-MATRIX.adoc" drift-flag = "STALE as of 2026-05-23 PM: this file's [components]/[features]/[project-context] still predate landed PRs since 2026-05-19. It MIRRORS, it does not LEAD. Authoritative sources by topic — readiness: docs/CAPABILITY-MATRIX.adoc; spine + AS↔typed-wasm contract: docs/ECOSYSTEM.adoc; coordination ledger / critical path: docs/TECH-DEBT.adoc; test taxonomy + PR-level gates: docs/standards/TESTING.adoc (added 2026-05-23); panic-attack SOP: docs/standards/PANIC-ATTACK.adoc (added 2026-05-23). Gate baseline: CAPABILITY-MATRIX records 260/260 at 2026-05-19 reconstruction; subsequent borrow-checker work has lifted it (#240 → 263, return-escape → 271/274, &mut surface → 278/281). The exact live number for any given commit comes from `dune runtest --force` — do not hard-code it here. (DOC-05, issue #176.)" session-note-2026-05-26-publish-104 = "ISSUE #104 CLOSED — FIRST NPM PUBLISH LANDED. @hyperpolymath/affine-vscode@0.1.0 is now on registry.npmjs.org. Owner-action sequence completed today: (1) npm org `hyperpolymath` created on free public-package tier; (2) Granular Access Token generated for scope @hyperpolymath/* with Read+Write, uploaded to repo secret NPM_TOKEN; (3) signed annotated tag affine-vscode-v0.1.0 pushed at origin/main (RSA key 9639451754496E51D6B537CAD119017EBF695AB1); (4) .github/workflows/affine-vscode-publish.yml ran green — `npm publish --access public` succeeded; (5) `npm view @hyperpolymath/affine-vscode` resolves. Downstream consumers (my-lang#66, standards#160) which un-vendored their adapters on 2026-05-21 now have a working `npm install` path; vscode-smoke workflow (skipped per #381 while package was unpublished) will start exercising the live package on its next PR run. Lineage for future @hyperpolymath/* publishes: org+token are reusable; mirror `affine-vscode-publish.yml`'s shape (tag trigger, version-match guard, .npmrc write from secret, npm publish --access public). NPM_TOKEN rotation advised post-publish (token value transited a session transcript during wire-up); see .machine_readable/6a2/PLAYBOOK.a2ml [npm-publish] for the runbook." +session-note-2026-05-30 = "DOC-16 + DOC-17 — DOC-TRUTHING MONITOR FULLY MECHANICAL (issue #176). Two complementary in-repo guards now enforce the doc-truthing rules that were previously external-bot-only. DOC-16 (PR #476, tools/check-doc-truthing.sh): banner-PRESENCE invariant — fails if any over-claiming doc loses its CAPABILITY-MATRIX banner, if the matrix stops self-declaring primacy / loses its 'What AffineScript is NOT' section, or if STATE.a2ml drops its mirror keys; deliberately does NOT phrase-scan (a naive grep false-positives on the negating banners + future-roadmap text). DOC-17 (PR #475, tools/check-doc-overclaims.sh + tools/doc-overclaims.allow): the phrase-detection complement — a frozen-baseline RATCHET over README + docs/** (excluding CAPABILITY-MATRIX + TECH-DEBT, which quote the rule) that fails any NEW backend-breadth / 'production-ready' / stdlib-% occurrence beyond the 13-line baseline (all current entries legit: future-tense roadmap milestones + dated history snapshots + corrective banners); re-baseline via `--update` / `just doc-overclaims-bless`, diff = audit trail. Both wired into `just check` (guard recipe) + ci.yml build job, both toolchain-free bash (run without OCaml). #475 was originally a superset of #476 (built in parallel, same session); on discovering #476 had merged first, #475 was reworked to drop the duplicated banner check and keep only the unique ratchet, renamed check-doc-truth.sh→check-doc-overclaims.sh to avoid the name clash (DOC-DEDUP-clean). Gate-number policy unchanged (DOC-05): live `dune runtest --force` count never hard-coded. No compiler code touched. Refs #176 / #175." session-note-2026-05-26 = "MIGRATION-ASSISTANT PHASE 2C + REPO-TIDY STACK (T-1..T-7) + STDLIB BLOCKER CLOSURES. (1) PR #357 — feat(res-to-affine) Phase 2c on branch claude/epic-gauss-Mbi0E: tree-sitter walker extended from #322's single Side_effect_import detector to all six anti-patterns. New detectors in tools/res-to-affine/walker.ml — detect_raw_js (any extension_expression node), detect_untyped_exception (try_expression / call to value_identifier \"raise\" / member_expression starting with Js.Exn or ending with Promise.catch), detect_mutable_global (top-level let_declaration whose body is call to value_identifier \"ref\", OR top-level mutation_expression), detect_inline_callback_record (>=3 inline function values in a record literal or a call_expression's arguments list — handles direct function children + labeled_argument + record_field wrappers), detect_oversized_function (function node whose stop.row - start.row + 1 > 50). Module-toplevel predicate refactored to a single at_module_toplevel helper that walks the ancestor chain refusing on `function` or `let_binding` body. Findings deduped by (kind, line) so the AST walker doesn't emit more bullets than the line-based scanner. CLI flipped --engine=walker to the default in tools/res-to-affine/main.ml (scanner remains as fallback when grammar / tree-sitter CLI missing — pre-existing graceful-fallback path from #322 unchanged). Scanner.kind extended with Inline_callback_record + Oversized_function variants; scanner.ml gives them labels + guidance. New fixture test/fixtures/phase2c.res exercises the two walker-only kinds. test_walker.ml grew per-kind tests under three new suites (walker-side-effect-import / walker-phase2c-parity / walker-phase2c-new-kinds). README + walker.mli updated. (2) Phase 2c CI fix push (e7a3a44): initial Phase 2c commit had build+lint failing; defensive rewrite replaced the labeled-only `mk_finding ~kind:K ~line:L ~excerpt:E :: acc` emit pattern with explicit `let finding : Scanner.finding = { ... } in finding :: acc` matching Phase 2b's working style, plus replaced non-ASCII glyphs in comments (≥ → >=, … → ...) defensively. (3) DIAGNOSED: `main` itself is red. PR #359 (T-1, pure file-rename + delete + one-line CONTRIBUTING.md edit, zero OCaml touched) also fails on build+lint. That conclusively shows the build failure is inherited from main, not introduced by Phase 2c or any tidy work. Matches CLAUDE.md §\"CI signal reliability\" — auto-merge fires even when build is red; the historical pattern of #334/#335/#336/#344 landing red applies. Root cause on main is NOT diagnosed in this session (needs the actual `dune build` log; WebFetch on the actions UI returns React skeletons, not log content; container has no OCaml toolchain to repro locally). Filed implicit follow-up: someone with shell access should run `gh run view --log-failed ` against any of the recent failing runs to identify the underlying lib/ compile error. (4) REPO-TIDY STACK (T-1..T-7) — six small PRs landed off origin/main, each reviewable in isolation, none touching .ml/.mli, all inheriting the same baseline build/lint failure as PR #359 (proof above). T-1 PR #359 *MERGED* — AI.a2ml → 0-AI-MANIFEST.a2ml (Hypatia root_hygiene rule + sibling-repo convention), delete AI.djot (superseded), docs/TECH-DEBT-alt.adoc → docs/TECH-DEBT.adoc (restoring the canonical name every cross-link in the repo already points at; PR #356's -alt suffix during the #351 split is dead weight post-#355). T-2 PR #360 — delete 2,182 lines of submarine-game docs (DAMAGE-SYSTEM.md, CONTROLS-REFERENCE.md, GAME-BUNDLING-STRATEGY.md), zero cross-references. T-3 PR #365 — 13 loose root .md/.adoc moved into docs/ subtree (ABI-FFI-README → docs/reference/ABI-FFI.md, ALPHA-1-RELEASE-NOTES → docs/history/, BACKEND-{ANALYSIS,IMPLEMENTATION} → docs/architecture/, COMPILER-CAPABILITIES → docs/reference/, EXPLAINME/KNOWN-ISSUES/NAVIGATION/PROOF-NEEDS/ROADMAP → docs/, LICENSING-GUIDE/SECURITY-SETUP → docs/governance/, RSR_OUTLINE → docs/standards/RSR-OUTLINE.adoc), two new subdirs docs/architecture/ + docs/reference/, cross-refs fixed in CAPABILITY-MATRIX / BACKEND-IMPLEMENTATION / CONTRIBUTING / NAVIGATION / res-to-affine; root drops 17→5 community-health files. T-4 PR #366 — RSR_COMPLIANCE.adoc at root with four documented deviations (no guix.scm/flake.nix; STATE.scm substituted by .machine_readable/6a2/STATE.a2ml because .scm is reserved for Guix per language policy; 7 TS exemptions; 2 runtime exemptions — all cite CLAUDE.md as authoritative). T-5 PR #367 — wiki/README.md rewrite (drops ~20 dead links to non-existent .md files, updates stale ../ROADMAP.md → ../docs/ROADMAP.adoc path, annotates Features-at-a-Glance examples with current maturity, switches Ownership example from &File/&mut File sigil syntax to canonical ref File/mut File keyword types) + parse-only honesty banner on wiki/language-reference/dependent-types.md + partial honesty banner on wiki/language-reference/traits.md. T-6 — direct issue triage, no PR: closed #246 (ESC-02 JSON.t — stdlib/json.affine delivers Json ADT + encoders/decoders/get_field/stringify) and #247 (ESC-03 Dict.t — stdlib/dict.affine delivers empty/from_pairs/get/contains/size/insert/set/remove/keys/values), both with confirmation comments referencing the LANDED status in docs/TECH-DEBT.adoc STDLIB-02/03 rows. T-7 this PR — adds this session-note + the T-1..T-7 ledger entry below in docs/TECH-DEBT.adoc. (5) ALSO RESOLVED EARLIER IN SESSION (pre-T-6, as part of addressing the sustainabot tracker blockers the user asked about): #161 (Json) and #162 (Dict) closed with explicit owner-author-acknowledged closure comments dated 2026-05-24; this session was the explicit owner request to act on those. Migration-assistant tracker #57 stays open — Phase 2c lands #322's Phase 2b → 2c walker work but Phase 3 (partial translation of pure-structural forms — the phase the sustainabot tracker's exit criterion 3 specifically gates on) remains unstarted. (6) OPEN PRs AT SESSION END: #357 (Phase 2c, ready to merge — author/owner discretion on the baseline-red CI), #360/#365/#366/#367 (T-2/T-3/T-4/T-5, same baseline-red situation; pure-rename / pure-delete / pure-doc-add changes, no behavioural risk). (7) NOT DONE IN THIS SESSION: actual root-cause diagnosis of main's red build/lint; ~20 missing wiki pages (installation, hello-world, expressions, errors, package-manager, lsp, formatter, linter, stdlib subpages, design/*); guix.scm or flake.nix addition; full wiki content refresh beyond README + two banners; sync of wiki/ to the GitHub-wiki upstream repo (separate git repo, owner pushes manually). (8) CROSS-REPO: this session is AffineScript-only — the gitbot-fleet sustainabot tracker that prompted #161/#162/#57 lives in a different repo and was not touched here." typed-wasm-formalisation-2026-05-23 = "AS↔TYPED-WASM INTERFACE FORMALISED + WIDENING ROADMAP + TWO PROPOSED ADRs. (1) docs/specs/TYPED-WASM-INTERFACE.adoc + .a2ml — formal spec of the v1 interface (was previously scattered across ECOSYSTEM.adoc + code comments in lib/codegen.ml, tw_interface.ml, tw_verify.ml). Captures: enforced surface (L7 aliasing + L10 linearity + L13 module isolation negative-form); carrier binary layout (u32 entry_count + per-entry [u32 func_index | u8 param_count | u8[n] param_kind | u8 ret_kind], kind ∈ {0 Unrestricted, 1 Linear, 2 SharedBorrow, 3 ExclBorrow}, all LE, omit-when-empty, no version field in v1); producer machinery file-line pointers (lib/codegen.ml ~110-177 + ctx.ownership_annots ~2312/~2629); consumer machinery (tw_verify.ml 332 LOC, tw_interface.ml 276 LOC, primary entry verify_from_module); CLI surface (verify / verify-boundary / verify-bridge / interface — verify-boundary's pre-2026-04-19 silent-success bug fixed by f6089a2); test coverage (test_tw_isolation.ml 5 cases + E2E Boundary Verify 3 cases + ownership-roundtrip 3 cases; honest gap: no C5.1 cross-compat fixtures shipped); multi-producer responsibilities (AS = ref producer + spec of record until C5.1; ephapax = second producer same format; typed-wasm = spec + Rust verifier + cross-compat target); deliberate non-features NF-001..NF-005 with roadmap anchors; stability promise (v1 frozen; unilateral changes forbidden). (2) docs/specs/TYPED-WASM-ROADMAP.adoc + .a2ml — making typed-wasm a natural + optimal target. Five tranches with unblock graph: A (ergonomics, no ABI change: A1 --typed-wasm gating flag, A2 report-typed-wasm JSON, A3 extract ownership-section to dedicated module, A4 diagnostic span parity) → B (schema hygiene, additive single-byte ABI: B1 = ADR-020) → C (compiler-side foundations for L1–6/L14–16: C1 region inference / CORE-01 Phase 3, C2 session-type+capability tracking, C3 CONV-02/ADR-016 S2..S4 async recogniser, C4 capability-typed externs) → D (multi-producer ABI widening: D1 = ADR-021, D2 affinescript.regions, D3 affinescript.{capabilities,session,choreography}) → E (cross-compat closure: E1 INT-12/CONV-05 fixtures into typed-wasm C5.1, E2 Rust-verifier parity out-of-scope-here). Recommended sequencing: A1→A3→A2→E1→B1→A4→D1→C1..C4→D2/D3→E2. (3) ADR-020 (PROPOSED, META.a2ml): ownership-section schema versioning — v1 unversioned → v2 with 0xAF sentinel + u8 version + entry_count. v1 readers fail cleanly on v2 (bad entry-count parse); v2 readers dispatch on sentinel. Coordinated landing: verifier ships parse first, producers flip emit together. (4) ADR-021 (PROPOSED, META.a2ml): multi-producer ABI coordination model — four axes (spec authority OCaml→Rust on C5.1 closure; coordinated landing protocol; test parity protocol; conflict resolution via serialised queue owned by typed-wasm). ADR-020 is itself the first test of ADR-021's protocol. (5) Cross-links: ECOSYSTEM.adoc §contract paragraph now points at TYPED-WASM-INTERFACE.adoc as authoritative; CAPABILITY-MATRIX.adoc typed-wasm row links to INTERFACE + ROADMAP and notes L13 alongside L7/L10; TECH-DEBT.adoc Stage E section gets header pointer + DOC-13/14/15 ledger entries (interface, roadmap, ADRs); docs/README.adoc + NAVIGATION.adoc list both new specs. (6) Pure documentation work — no compiler code changed, no behaviour change. Both ADRs require owner ratification before they bind." stage-d-batch-2026-05-23 = "INT-01 ::-in-value-expr + BUG-005 deferred fixture + STDLIB-04 audit. (1) INT-01 follow-up: lib/parser.mly line ~835 — added `upper_ident COLONCOLON lower_ident` production emitting `ExprField(ExprVar Mod, lower_ident)`, the same AST shape `Mod.fn` already produces. Disambiguated from the line-above `Type::Variant` rule by lower_ident vs upper_ident. No resolver change required: Resolve.lower_qualified_value_paths handles both `.` and `::` syntaxes identically because the lowering pattern-matches on the ExprField shape, not the source separator. test/e2e/fixtures/cross_caller_qualified_colon{,_alias}.affine + 2 alcotest cases in qualified_value_tests pin both `use Mod; Mod::fn(x)` and `use Mod as M; M::fn(x)`. The remaining INT-01 'parser gap, not resolver' note in the ledger is now closed. (2) BUG-005 deferred regression test landed (test/test_e2e.ml, wasm_gc_loud_fail_tests): `fn main() -> Int { return totally_undefined_callee(42); }` is fed directly to Codegen_gc.generate_gc_module (no resolve step) and the emitted error must contain the unknown name — which UnboundFunction's format string includes verbatim. Closes the deferred-status entry on the [[closed-bug]] BUG-005 record. (3) docs/STDLIB-EXTERN-AUDIT.adoc — full triage of 135 extern fn + 24 extern type across 11 stdlib files into 4 classes (built-in / typed-boundary-bridge / adapter-Deno / adapter-Node); per-row status (done/partial/stub-only) and unblock condition for each module. STDLIB-04's ledger entry now points here. Implementation PRs close one row at a time; the audit doc is the canonical roadmap, not STATE.a2ml. (4) Not yet verified locally — no OCaml toolchain in this remote execution environment. CI is the verification surface; parser change is low-risk (single production, no Menhir conflict — `upper_ident COLONCOLON lower_ident` is unambiguous against the prior `upper_ident COLONCOLON upper_ident` rule by token class)." diff --git a/docs/CAPABILITY-MATRIX.adoc b/docs/CAPABILITY-MATRIX.adoc index 771d409..564e0f5 100644 --- a/docs/CAPABILITY-MATRIX.adoc +++ b/docs/CAPABILITY-MATRIX.adoc @@ -221,8 +221,13 @@ current authoring frontier. A few primitives remain `extern` builtins. Any PR that re-introduces backend-breadth, "production-ready", or stdlib-percentage over-claims must be rejected (DOC-01..09 / issue #176; -Hypatia/gitbot `DOC-FORMAT`/`DOC-DEDUP` rules). Update *this file* in the same -PR as any capability change; `STATE.a2ml` mirrors, it does not lead. +Hypatia/gitbot `DOC-FORMAT`/`DOC-DEDUP` rules). This is enforced +*mechanically* in-repo (wired into `just check` + CI): `tools/check-doc-truthing.sh` +(DOC-16) holds the banner/primacy/mirror invariant, and +`tools/check-doc-overclaims.sh` (DOC-17) ratchets against new over-claim +phrasings beyond the frozen `tools/doc-overclaims.allow` baseline. Update +*this file* in the same PR as any capability change; `STATE.a2ml` mirrors, +it does not lead. == See also diff --git a/docs/TECH-DEBT.adoc b/docs/TECH-DEBT.adoc index 9f9a984..1ec6859 100644 --- a/docs/TECH-DEBT.adoc +++ b/docs/TECH-DEBT.adoc @@ -122,13 +122,28 @@ NOT" section, or if `STATE.a2ml` drops its mirror keys. Wired into `just check` (the `guard` recipe) and CI (`ci.yml` build job). Converts the DOC-08/09 MONITOR posture from external-bot-only to a first-class in-repo gate. |*DONE 2026-05-30* +|DOC-17 |Over-claim ratchet — the *phrase-detection* complement to DOC-16. +`tools/check-doc-overclaims.sh` + `tools/doc-overclaims.allow` baseline: +a frozen-signature ratchet over README + `docs/**` (excluding the two +governance docs that quote the rule — CAPABILITY-MATRIX + this ledger) +fails any *new* backend-breadth / "production-ready" / stdlib-% phrase +beyond the 13-line baseline (future-tense roadmap milestones, dated +history snapshots, the corrective banners — none a live over-claim). +DOC-16 deliberately checks banner *presence* not phrasing (a naive grep +false-positives); the ratchet closes that gap without false positives +because the legitimate set is frozen and only *new* phrases fail. +Re-baseline via `--update` / `just doc-overclaims-bless`; the diff is +the audit trail. Wired into `just check` + CI (toolchain-free bash). +|*DONE 2026-05-30* |=== MONITOR enforcement (DOC-08/09): any PR re-introducing backend-breadth, "production-ready", or stdlib-percentage over-claims must be rejected. -As of DOC-16 (2026-05-30) the banner/mirror half of this is enforced -in-repo by `tools/check-doc-truthing.sh`; the external Hypatia/gitbot -DOC rules remain the catch-all for novel over-claim phrasings. +As of 2026-05-30 this is enforced in-repo on *both* halves: DOC-16 +(`tools/check-doc-truthing.sh`) holds the banner/primacy/mirror presence +invariant, and DOC-17 (`tools/check-doc-overclaims.sh`) ratchets against +new over-claim *phrasings*. The external Hypatia/gitbot DOC rules remain +the estate-level backstop for anything outside both nets. == Section B — CORE (compiler soundness / completeness) diff --git a/justfile b/justfile index e63ddd3..94a234f 100644 --- a/justfile +++ b/justfile @@ -90,11 +90,19 @@ check: lint test guard # Regression guards: # - Issue #35 Phase 3: fails if extension.ts reappears under # editors/vscode/src or any face's vscode extension dir. -# - Issue #176 (DOC-01..09): fails if the status-doc truthing banners +# - Issue #176 (DOC-16): fails if the status-doc truthing banners # re-drift (authoritative matrix pointers + STATE.a2ml mirror keys). +# - Issue #176 (DOC-17): fails if a NEW backend-breadth / "production- +# ready" / stdlib-% over-claim appears beyond the frozen baseline. guard: ./tools/check-no-extension-ts.sh ./tools/check-doc-truthing.sh + ./tools/check-doc-overclaims.sh + +# Re-baseline the over-claim ledger (DOC-17) after a deliberate, legitimate +# change (e.g. a new dated roadmap milestone). Commit the .allow diff. +doc-overclaims-bless: + ./tools/check-doc-overclaims.sh --update # ── Compiler subcommands ────────────────────────────────────────────────────── diff --git a/tools/check-doc-overclaims.sh b/tools/check-doc-overclaims.sh new file mode 100755 index 0000000..b9a51e0 --- /dev/null +++ b/tools/check-doc-overclaims.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2024-2026 hyperpolymath +# +# Over-claim ratchet for issue #176 (DOC-08/09, ledger row DOC-17). +# +# Companion to tools/check-doc-truthing.sh (DOC-16), which enforces the +# *presence* of the corrective banners + matrix primacy + STATE.a2ml mirror +# keys. That guard deliberately does NOT phrase-scan, because "production-ready" +# legitimately appears inside the negating banners and future-roadmap sections, +# so a naive grep false-positives — and it therefore leaves novel over-claim +# *phrasings* (the DOC-08/09 MONITOR) to the external Hypatia/gitbot bots. +# +# This guard closes exactly that gap without the false-positive problem, via a +# ratchet: the current accepted set of over-claim-phrase occurrences (every one +# legitimate today — future-tense roadmap milestones, dated history snapshots, +# the corrective banners) is frozen in tools/doc-overclaims.allow. Any *new* +# occurrence not in that baseline fails the build. The baseline is a sorted, +# signature-keyed (path + normalised line) ledger, robust to line moves, and +# its growth is a reviewable diff — the human-review signal the DOC rules +# describe, now in-repo and automatic. +# +# The two authoritative governance docs that define/quote the rule itself +# (docs/CAPABILITY-MATRIX.adoc, docs/TECH-DEBT.adoc) are excluded — they +# legitimately contain the anti-claims, and editing their rule-text must not +# churn the baseline. The banner docs are covered by check-doc-truthing.sh. +# +# Re-baselining (only when a NEW occurrence is genuinely legitimate — e.g. a +# new dated roadmap milestone): run `./tools/check-doc-overclaims.sh --update` +# (or `just doc-overclaims-bless`) and commit the doc-overclaims.allow diff in +# the same PR. The diff is the audit trail. +# +# Wired into: +# - just check (via the `guard` recipe in justfile) +# - CI (.github/workflows/ci.yml, build job) + +set -euo pipefail + +cd "$(dirname "$0")/.." + +ALLOW="tools/doc-overclaims.allow" + +# Over-claim phrase families (DOC-08 backend-breadth / DOC-09 production-ready +# + stdlib-percentage). Patterns are intentionally broad: the frozen baseline +# gives zero false positives on existing content, so breadth only raises recall +# on genuinely new occurrences. +PATTERN='production[- ]ready|production backends?|[0-9]+[[:space:]]+(production|complete)[[:space:]]+backends?|stdlib[^|]*100%|100%[^|]*stdlib|N production backend' + +# Emit one normalised signature per over-claim hit: "relpathline", with +# the line's internal whitespace collapsed and trimmed (robust to re-indent / +# re-flow; sensitive to the claim text itself). Sorted + de-duplicated. +scan_overclaims() { + # The two authoritative governance docs are excluded: they define and quote + # the banned phrases as the rule itself (anti-claims), so scanning them would + # only re-flag the rule text. Banner presence in these + the over-claiming + # docs is the job of tools/check-doc-truthing.sh (DOC-16). + grep -rniE "$PATTERN" README.adoc docs/ 2>/dev/null \ + --exclude="CAPABILITY-MATRIX.adoc" \ + --exclude="TECH-DEBT.adoc" \ + | sed -E 's/^([^:]+):[0-9]+:/\1\t/' \ + | awk -F'\t' 'BEGIN { OFS = "\t" } + { + line = $2 + gsub(/[[:space:]]+/, " ", line) + sub(/^ /, "", line) + sub(/ $/, "", line) + print $1, line + }' \ + | LC_ALL=C sort -u +} + +# --- --update / --bless mode: regenerate the baseline ----------------------- +if [ "${1:-}" = "--update" ] || [ "${1:-}" = "--bless" ]; then + { + echo "# SPDX-License-Identifier: MPL-2.0" + echo "# SPDX-FileCopyrightText: 2024-2026 hyperpolymath" + echo "# Over-claim baseline (issue #176, DOC-08/09 / ledger DOC-17) — the" + echo "# frozen set of accepted over-claim-phrase occurrences. Regenerate with" + echo "# \`./tools/check-doc-overclaims.sh --update\`. Each line is a" + echo "# \"relpathnormalised-line\" signature. A new signature not listed" + echo "# here fails CI; adding one is a deliberate, reviewable act. Current" + echo "# entries are future-tense roadmap milestones, dated history snapshots," + echo "# and the corrective banners — none is a live over-claim." + scan_overclaims + } > "$ALLOW" + echo "OK: regenerated $ALLOW ($(grep -cvE '^#' "$ALLOW") signatures)." + exit 0 +fi + +if [ ! -f "$ALLOW" ]; then + echo "ERROR: $ALLOW is missing. Run ./tools/check-doc-overclaims.sh --update" >&2 + echo " to create the over-claim baseline." >&2 + exit 1 +fi + +current="$(scan_overclaims)" +allowed="$(grep -vE '^#' "$ALLOW" | LC_ALL=C sort -u || true)" +new_hits="$(LC_ALL=C comm -13 <(printf '%s\n' "$allowed") <(printf '%s\n' "$current") | sed '/^$/d')" + +if [ -n "$new_hits" ]; then + echo "ERROR: new over-claim(s) detected in status docs (issue #176, DOC-08/09)." >&2 + echo "" >&2 + echo "The authoritative readiness source is docs/CAPABILITY-MATRIX.adoc, which" >&2 + echo "forbids re-introducing backend-breadth / \"production-ready\" /" >&2 + echo "stdlib-percentage over-claims. These occurrences are not in the frozen" >&2 + echo "baseline ($ALLOW):" >&2 + echo "" >&2 + printf '%s\n' "$new_hits" | sed 's/\t/ :: /; s/^/ /' >&2 + echo "" >&2 + echo "Fix the over-claim (preferred), or — if it is genuinely legitimate" >&2 + echo "(e.g. a new dated roadmap milestone) — re-baseline with:" >&2 + echo " ./tools/check-doc-overclaims.sh --update # or: just doc-overclaims-bless" >&2 + echo "and commit the tools/doc-overclaims.allow diff in the same PR." >&2 + exit 1 +fi + +echo "OK: no new over-claims beyond the frozen baseline ($ALLOW)." diff --git a/tools/doc-overclaims.allow b/tools/doc-overclaims.allow new file mode 100644 index 0000000..4e4c84a --- /dev/null +++ b/tools/doc-overclaims.allow @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2024-2026 hyperpolymath +# Over-claim baseline (issue #176, DOC-08/09 / ledger DOC-17) — the +# frozen set of accepted over-claim-phrase occurrences. Regenerate with +# `./tools/check-doc-overclaims.sh --update`. Each line is a +# "relpathnormalised-line" signature. A new signature not listed +# here fails CI; adding one is a deliberate, reviewable act. Current +# entries are future-tense roadmap milestones, dated history snapshots, +# and the corrective banners — none is a live over-claim. +docs/ROADMAP.adoc * Production-ready toolchain +docs/ROADMAP.adoc |Production ready +docs/STATE-2026-05-26.adoc |*Phase 3 (Q3 2026)* |Production ready |*1.0* |requires Stage E (typed-wasm contract widening — cross-repo) +docs/architecture/BACKEND-IMPLEMENTATION.md > *production-ready*. One reference target (WASM); Deno-ESM/Node-CJS solid; +docs/bindings-roadmap.adoc |Production backend default; pairs with SQLite for dev. +docs/guides/WHAT-MAKES-IT-BRILLIANT.md **Q: When will it be production-ready?** +docs/history/ALPHA-1-RELEASE-NOTES.md - Production-ready +docs/history/ALPHA-1-RELEASE-NOTES.md - Production-ready compiler +docs/history/PHASE3-ASSESSMENT.md - Row polymorphism is production-ready! ✅ +docs/history/PHASE3-COMPLETE.md - **Production-ready** type system +docs/history/PHASE3-SESSION-SUMMARY.md - ✅ Row polymorphism is production-ready +docs/history/PHASE3-SESSION-SUMMARY.md | Row Polymorphism | 100% ✅ | Production ready | +docs/standards/ROADMAP.md This roadmap outlines the path from current state (lexer + parser) to a complete, production-ready language.