From 537cc3954b9ce4f660d46694b1e704a3ae9a5684 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 8 Sep 2026 06:45:32 +0000 Subject: [PATCH 01/25] Repair text-construction authority and preserve local skill indexes --- .github/workflows/ci.yml | 7 +++ AGENTS.md | 2 +- CLAUDE.md | 8 ++-- ORG_DISTRIBUTION.md | 4 +- README.md | 4 +- char-compress/SKILL.md | 69 +++++++++++++-------------- docs/propagation-checklist.md | 5 ++ gonol-build/SKILL.md | 44 ++++++++++++----- gonol-build/check_edcm_boundary.py | 62 ++++++++++++++++++++++++ skill-lib_msdmd.ts | 9 ++++ skills.json | 4 +- skills/char-compress/SKILL.md | 2 +- skills/gonol-build/SKILL.md | 2 +- tests/test_char_compress_authority.py | 23 +++++++++ tests/test_gonol_build_skill.py | 26 +++++----- tests/test_propagate_skills.py | 18 +++++++ tools/propagate_skills.py | 27 +++++++++-- 17 files changed, 237 insertions(+), 79 deletions(-) create mode 100644 gonol-build/check_edcm_boundary.py create mode 100644 tests/test_char_compress_authority.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa6a5f9..02e1743 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,13 @@ jobs: python-version: "3.x" - name: Unit tests run: python -m unittest discover -s tests + - name: Exact EDCM cross-source construction witness + run: | + EDCM_CHECKOUT=$(mktemp -d) + git -C "$EDCM_CHECKOUT" init + git -C "$EDCM_CHECKOUT" fetch --depth 1 https://github.com/The-Interdependency/edcm.git ddc89a97ebbcf0a5863dad6e633b01b520e9bccf + git -C "$EDCM_CHECKOUT" checkout --detach FETCH_HEAD + python gonol-build/check_edcm_boundary.py "$EDCM_CHECKOUT" - name: Skill library drift run: python tools/check_skill_lib_drift.py --warnings-fail - name: Skill compliance diff --git a/AGENTS.md b/AGENTS.md index 82aa1d3..4dea4a0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -146,7 +146,7 @@ propagate from here. - If you are constructing, reviewing, replaying, or continuing UCNS gonols, including lexical floors, morphology, definitions, punctuation functions, closure, atomic promotion, or recursive relations, load `gonol-build/SKILL.md`. - Resolve current UCNS authority first; never restore historical + Resolve current UCNS geometry and EDCM text/scale authority first; never impose a universal adjacent-scale ladder or restore historical `gonal-morphology` doctrine as current canon. - If you are comparing UCNS options, deciding whether evidence authorizes a winner, or issuing a scoped selection receipt, load diff --git a/CLAUDE.md b/CLAUDE.md index 42d9f77..52eeff3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -49,11 +49,11 @@ llms/ # python -m llms.build reference runner | `canon/` | procedural | — | Canonical-source and doctrine maintenance. Helps agents distinguish source-backed canon, proposed canon, repo-local practice, and `hmmm`. No metadata block. | | `domain-claims/` | procedural | — | Domain-first lexical and semantic governance. Establishes the domain-qualified sense, scope, exclusions, collision result, and standing that must precede a canonical definition, conversational provenance, or structural encoding. No metadata block. | | `visitor-intro/` | procedural | — | Onboarding tour. Lets any agent give a coherent, repo-aware orientation to newcomers at any org repo without inventing org-level facts. No metadata block. | -| `char-compress/` | procedural | — | Unit Circle Number System-derived bone/flesh context compression. Carry flesh, frozen bones, transforms, and `hmmm`; drop only safely regenerable scaffold. Do not claim unearned theorem/status support or edcmbone metric status. | +| `char-compress/` | procedural | — | Skill-lib-owned bone/flesh context compression; historical notation is not current UCNS mathematics. Carry flesh, frozen bones, transforms, and `hmmm`; drop only safely regenerable scaffold. Do not claim unearned theorem/status support or edcmbone metric status. | | `agent-instantiation/` | procedural | — | a0/a0ucns agent lifecycle methodology. Spawn sub-agents via the `sub_agent_spawn` tool → spawn executor; fork/merge `PCNAEngine` instances via `InstanceMerge` (fork/absorb/converge); compose identities per the canonical `username(a0(energy)auditor)` grammar; honor spawn caps + write-route gating. Canonical source is `a0`; `a0-betatest` diverged (per-user native-ZFAE) and is out of scope. Repo-specific runtime doctrine (no theorem transfer). | | `a0p-instancing/` | procedural | — | Peer for a0-betatest (a0p): agents are per-user CRUD `AgentInstance` + `CharacterSheet`, each owning a trained native ZFAE weight bank (three 157-seed cores); no `sub_agent_spawn`/executor/`InstanceMerge` — only volatile `MemoryCore.spawn_sub/merge_sub`. Sequence: create→distill-train→readiness gate→mode inference→sentinel/pending-override→safetensors checkpoint. Canonical source is `a0-betatest`. | | `plain-lens/` | procedural | — | Plain-language, multi-lens companion views of dense canonical text. Build easier on-ramps (domain/audience/role lens selectors, progressive disclosure) that never replace or talk down to the source, keep a static fallback under any dynamic layer, preserve operators/negations/quantifiers, and report an EDCM-style body-vs-footnote tension reading as an illustrative heuristic (not an edcmbone metric runtime). | -| `gonol-build/` | procedural | — | UCNS gonol construction discipline. Resolve current UCNS authority; preserve intrinsic relations, closure, atomic promotion, occurrence identity, explicit punctuation-function plans, full-source receipts, and independent replay. Refuses superseded omega/phi/psi, bone/flesh, and carrier-LCM language doctrine. | +| `gonol-build/` | procedural | — | UCNS geometry / EDCM text construction discipline. Resolve current owning contracts and admissible scale options; preserve closure, atomic participation, occurrence identity, full-source receipts, and protocol-required replay. Refuses superseded omega/phi/psi, bone/flesh, and carrier-LCM language doctrine. | | `ucns-option-selection/` | procedural | — | Fail-closed scoped UCNS option selection. Freezes candidates, authority, gates, evidence, and policies; requires complete evaluation, replay, purpose-relative comparison, explicit ratification, rollback, and non-transfer. Hard-gate failures cannot be compensated by scores. | | `epac-selection-display/` | procedural | — | Evidence-bound EPAC display selection. Resolves an exact provisional source, target, receipt, and available representation; preserves status, nonclaims, sealed-comparison boundaries, and `hmmm`; and keeps WebMCP as a read-only handoff rather than a research-code executor. | | `meta/` | procedural | — | Meta Energy Theory axioms. Extract and preserve Energy Theory axioms from resonances among small network architectures, with formula-backed examples and overlap grids; keep Energy Theory distinct from EDCMBONE flesh/bone and FLAR implementation detail. | @@ -248,9 +248,9 @@ There is a small stdlib Python editorial test suite. There is still no `package. 7. Do not fork parser dialects; propose an `msdmd` extension instead. 8. Do not invent undeclared package/build commands for this repo. 9. Apply `char-compress` when compressing repo context: carry flesh, frozen bones, transforms, and hmmm; drop only safely regenerable scaffold. -10. Treat `char-compress` as Unit Circle Number System-derived compression doctrine, but do not claim unearned theorem/status support or edcmbone metric status. +10. Treat `char-compress` as a skill-lib-owned compression procedure, but do not claim unearned theorem/status support or edcmbone metric status. 11. Before promoting a word into canon, a theorem term, ontology primitive, schema field, encoding label, or cross-domain mapping, apply `domain-claims`: establish the domain-qualified sense and resolve collisions before attaching provenance; then apply `canon` to assess authority. -12. Before constructing, reviewing, replaying, or extending UCNS gonols, apply `gonol-build`: resolve current UCNS authority, preserve closure and atomic promotion, require explicit occurrence-addressed function plans, and keep incomplete constructors visible as `hmmm`. +12. Before constructing, reviewing, replaying, or extending UCNS gonols, apply `gonol-build`: resolve current UCNS geometry and EDCM admissible scale options, preserve closure and atomic participation, require declared occurrence-addressed function plans, and keep incomplete constructors visible as `hmmm`. 13. Before selecting among UCNS options, apply `ucns-option-selection`: freeze the scoped decision boundary, enforce noncompensable eligibility and evidence gates, require explicit ratification, and preserve non-transfer, rollback, negative evidence, and `hmmm`. 14. Before selecting and displaying an EPAC artifact, apply `epac-selection-display`: pin the provisional source, exact target, receipt, and available renderer; preserve status, nonclaims, sealed comparison, and `hmmm`; and keep WebMCP read-only. 15. For LLM instructions, edit `LLMS` source blocks and regenerate `llms.txt` with `python -m llms.build --root . --out llms.txt --apply`. diff --git a/ORG_DISTRIBUTION.md b/ORG_DISTRIBUTION.md index 6b12ed5..7a10e5b 100644 --- a/ORG_DISTRIBUTION.md +++ b/ORG_DISTRIBUTION.md @@ -29,7 +29,7 @@ Propagation PRs should cite this repository and the source commit SHA. * `canon/` — canonical-source and doctrine maintenance * `domain-claims/` — domain-first lexical standing, collision checks, and semantic provenance gating * `visitor-intro/` — onboarding tour for newcomers landing at any org repo -* `char-compress/` — bone/flesh context compression for handoffs and skill writing +* `char-compress/` — skill-lib-owned bone/flesh context compression for handoffs and skill writing; historical notation is not current UCNS mathematics * `agent-instantiation/` — a0/a0ucns agent spawn/fork/merge lifecycle methodology * `a0p-instancing/` — a0-betatest (a0p) per-user CRUD + native-ZFAE instancing methodology * `manifest/` — living-spec generation @@ -38,7 +38,7 @@ Propagation PRs should cite this repository and the source commit SHA. * `plain-lens/` — plain-language, multi-lens companion views of dense canonical text * `thought-lens/` — raw-thought to audience-legible translation with claim-kernel fidelity and back-translation checks * `meta/` — consultation router for current METAPAT authority; no frozen doctrine copy -* `gonol-build/` — UCNS gonol construction, closure, atomic promotion, explicit function application, complete replay, and honest continuation boundaries +* `gonol-build/` — UCNS geometry / EDCM text construction, declared scale options, closure, atomic participation, protocol-required replay, and honest continuation boundaries * `ucns-option-selection/` — fail-closed scoped UCNS option comparison, selection, ratification, non-transfer, rollback, and decision receipts * `epac-selection-display/` — exact provisional EPAC target and representation selection with receipt-backed display, status preservation, and a read-only WebMCP handoff boundary * `the-interdependency/` — org-wide workflow protocol and usage-guidance doctrine for The Interdependency projects diff --git a/README.md b/README.md index 7662458..ebf4ad5 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,13 @@ into [`llms.txt`](llms.txt) from self-declared `LLMS` blocks. | [`canon/`](canon/SKILL.md) | Canonical-source and doctrine maintenance. Helps agents decide what is source-backed canon, proposed canon, or `hmmm` before changing skills or org doctrine. Independent of msdmd. | | [`domain-claims/`](domain-claims/SKILL.md) | Domain-first lexical and semantic governance. Before a word becomes a theorem term, ontology primitive, schema field, encoding label, or other control surface, establish the domain-qualified sense, scope, exclusions, collision status, and standing that later provenance may attach to. Independent of msdmd. | | [`visitor-intro/`](visitor-intro/SKILL.md) | Onboarding tour skill. Lets any agent give a coherent, repo-aware orientation to newcomers landing at any The-Interdependency repo, without inventing org-level facts. Independent of msdmd. | -| [`char-compress/`](char-compress/SKILL.md) | Unit Circle Number System-derived bone/flesh context compression for agent handoff and skill writing. Preserves irreducible flesh, frozen bones, transforms, and `hmmm`; drops only safely regenerable scaffold. Independent of msdmd. | +| [`char-compress/`](char-compress/SKILL.md) | Skill-lib-owned bone/flesh context compression (historical text-stack notation, not current UCNS mathematics) for agent handoff and skill writing. Preserves irreducible flesh, frozen bones, transforms, and `hmmm`; drops only safely regenerable scaffold. Independent of msdmd. | | [`agent-instantiation/`](agent-instantiation/SKILL.md) | Methodology for instantiating, forking, running, merging, and retiring agents in `a0` and its mirror `a0ucns`. Spawn via the `sub_agent_spawn` tool → executor; fork/merge `PCNAEngine` instances via `InstanceMerge`; compose identities; honor spawn caps and write-route gating. `a0-betatest` diverges (per-user native-ZFAE) and is out of scope. Independent of msdmd. | | [`a0p-instancing/`](a0p-instancing/SKILL.md) | Peer of `agent-instantiation` for a0-betatest (a0p), whose model diverges: agents are per-user CRUD `AgentInstance` entities bound to a `CharacterSheet`, each owning a trained native ZFAE weight bank; no spawn/fork/merge — only volatile sub-context memory. Covers create→train→readiness-gate→mode inference→sentinel/override→safetensors checkpoint. Independent of msdmd. | | [`plain-lens/`](plain-lens/SKILL.md) | Plain-language, multi-lens companion views of dense canonical text — easier on-ramps that do not replace or talk down to the source. Domain/audience/role lens selectors, progressive-disclosure reading UX, static fallback for dynamic pages, and EDCM-style body-vs-footnote tension readings. Independent of msdmd. | | [`thought-lens/`](thought-lens/SKILL.md) | Translation compiler for raw, context-heavy thought. Recovers a claim kernel before rendering audience/surface-specific language, preserves claim force and operators, introduces coined terms only after their ordinary meaning lands, and back-checks for fidelity and remaining context debt. Independent of msdmd. | | [`meta/`](meta/SKILL.md) | Consultation router for current METAPAT. Retrieves the authoritative repository when a conceptual relation, distinction, boundary, transformation, scale, or cross-domain correspondence would constrain downstream work; carries no frozen METAPAT doctrine here. Independent of msdmd. | -| [`gonol-build/`](gonol-build/SKILL.md) | UCNS gonol construction, closure, atomic promotion, function application, replay, and continuation discipline. Routes authority to the current UCNS commit; preserves exact source and occurrence identity; requires explicit function plans and complete replay; refuses historical omega/phi/psi, bone/flesh, and carrier-LCM language doctrine. Independent of msdmd. | +| [`gonol-build/`](gonol-build/SKILL.md) | UCNS geometry / EDCM text construction, closure, atomic participation at admissible scales, and scoped replay discipline. Resolves each owning contract; preserves exact source and occurrence identity; imposes no universal scale ladder. Independent of msdmd. | | [`ucns-option-selection/`](ucns-option-selection/SKILL.md) | Fail-closed UCNS option-selection rubric. Freezes scope, candidates, authority, gates, policies, and evidence boundaries; requires complete execution, falsification, replay, purpose-relative comparison, non-transfer, rollback, and explicit ratification; refuses compensating scores and universal promotion from local evidence. Independent of msdmd. | | [`epac-selection-display/`](epac-selection-display/SKILL.md) | Evidence-bound EPAC target selection and display. Resolves an exact provisional source, target, receipt, and available renderer; preserves standing, `selection_effect`, nonclaims, sealed-comparison boundaries, and `hmmm`; and keeps the WebMCP surface a read-only repository-and-skill handoff rather than an EPAC executor. Independent of msdmd. | | [`the-interdependency/`](the-interdependency/SKILL.md) | Workflow and protocol for code building, researching, GitHub maintenance and updates, EDCMBONE transcript assembly for analysis, and anything that touches The Interdependency organization or The Interdependent Way projects. Enforces structure preservation (neurodivergence-compatible), mandatory usage guidance in all artifacts, framework-aligned EDCMBONE analysis, and org-standard GitHub hygiene. Independent of msdmd. | diff --git a/char-compress/SKILL.md b/char-compress/SKILL.md index 5caf1b0..20d3fd2 100644 --- a/char-compress/SKILL.md +++ b/char-compress/SKILL.md @@ -1,18 +1,15 @@ --- name: char-compress -description: Character-based context compression for agent handoff and skill writing, derived from the mathematics of the Unit Circle Number System. Use this when compressing a long thread, document, repo audit, canon handoff, or agent working-memory state; when a context window is filling and operative facts must survive; when writing a SKILL.md that should be flesh-dense and bone-sparse; or when checking whether a compression deleted negation, order, quantifier, operator, named object, value, decision, or unresolved hmmm. This is a procedural skill-level projection of UCNS compression mathematics, not a UCNS-A theorem/status transfer and not an edcmbone metric implementation. +description: Character-based context compression for agent handoff and skill writing, owned as a skill-lib procedure rather than current UCNS mathematics. Use this when compressing a long thread, document, repo audit, canon handoff, or agent working-memory state; when a context window is filling and operative facts must survive; when writing a SKILL.md that should be flesh-dense and bone-sparse; or when checking whether a compression deleted negation, order, quantifier, operator, named object, value, decision, or unresolved hmmm. Historical bone/flesh and text-stack terminology is local compression notation, not a UCNS theorem/status transfer, EDCM constructor, or edcmbone metric implementation. --- -# char-compress — UCNS-derived bone/flesh compression for agent context +# char-compress — bone/flesh compression for agent context -`char-compress` is a procedural skill for applying the compression side of the -Unit Circle Number System to agent context. The mathematics of the Unit Circle -Number System comprises the compression algorithm: preserve the irreducible -content, suppress the regenerable recurrence, and reconstruct only through a -shared grammar/domain. - -This skill is the agent-facing projection of that mathematics. It is not the -full UCNS compression engine. +`char-compress` is a skill-lib-owned procedure: preserve irreducible content, +suppress only safely regenerable recurrence, and reconstruct through an +explicit shared grammar/domain. Its historical bone/flesh and text-stack +vocabulary is retained as local compression notation, not asserted as current +UCNS mathematics. It is not an implemented UCNS compression engine. It separates text into: @@ -45,22 +42,20 @@ this repo remains the canonical source. ### Relation to `ucns` -`ucns` owns the Unit Circle Number System. Its mathematics is the source of the -compression algorithm: inventory, recurrence, carrier position, suppression, -reconstruction, and proof/status boundaries all belong to the UCNS side of the -system. +`ucns` owns current geometry, not lexical classes or this compression procedure. +EDCM owns text-domain gonol construction. Neither repository's authority is +acquired by calling a text inventory a carrier or a separator a twist. -This skill does state that `char-compress` is UCNS-derived. It does not state -that the current skill file or fixture runner is a full implementation of the -UCNS compression engine. +The vocabulary below records this skill's historical model only. An exact +historical UCNS source establishing that model is unresolved (`hmmm`); no current +UCNS mathematical derivation is claimed. Resolve an exact producer contract +before using any actual UCNS operation or EDCM constructor. Allowed relation: -- char inventories and suppressed fingerprints are compression artifacts of - the Unit Circle Number System; -- this skill may define agent behavior for applying those artifacts to context; -- future code may promote the current guardrail runner into a fuller UCNS - compression engine; +- character inventories and suppressed fingerprints are local compression artifacts; +- this skill defines agent behavior for applying those artifacts to context; +- future code needs a separately declared, tested codec contract; - proof/status claims must remain scoped to the specific UCNS theorem or tested implementation that establishes them. @@ -91,9 +86,11 @@ Use edcmbone doctrine as a guardrail: - reconstruction should be checked against F-loss and operator preservation when an edcmbone runner is available. -## UCNS text-stack model +## Optional local text-stack notation -Text is a recursive stack of gonols. +The following is an optional notation for text grouping, not a UCNS construction +law or a mandatory EDCM scale ladder. Here `tensor`, `twist`, `gonol`, `carrier`, +`spiral`, and `chirality` are historical local labels, not constructed geometry. ```text tensors = characters @@ -105,9 +102,9 @@ chapters = paragraph-gonols volumes = chapter-gonols ``` -A space is not absence. A space is a twist seam: it closes one word-gonol and -opens attachment into the next layer. Punctuation is a stronger typed twist. -A paragraph break, chapter break, and volume break are higher-scale twist seams. +Under this notation a meaningful space is recorded as a separator (`twist`), +and punctuation/breaks retain their source-specific attachment role. No geometric +strength, operation, or closure follows from a punctuation class alone. Each higher object is a gonol whose vertices are lower objects: @@ -248,9 +245,9 @@ banana -> ban committee -> comite ``` -The result is an inventory fingerprint. In UCNS terms, it preserves the -first-cycle carrier of the word-gonol and suppresses recurrence into spiral -weight/layer data. For closed-class words in known slots, that fingerprint plus +The result is an inventory fingerprint. In this local notation it preserves the +first-occurrence inventory, with recurrence retained as explicit ordered data +when required. For closed-class words in known slots, that fingerprint plus grammar often recovers the word. For open-class content, the same operation can destroy needed information unless recurrence and position data are carried. @@ -268,9 +265,9 @@ space/twist changes attachment or closure -> twist data must be preserved 1. **Mark the domain.** State the repo, thread, language, and grammar assumed by the reconstruction. Compression is only lossless relative to that grammar. -2. **Build the text stack.** Treat characters as tensors, spaces as twists, - words as character-gonols, sentences as word-gonols, paragraphs as - sentence-gonols, chapters as paragraph-gonols, and volumes as chapter-gonols. +2. **Declare the text grouping.** Use source-appropriate character, word, + sentence, or other boundaries. The optional local text-stack notation above + is not required and does not construct UCNS geometry or EDCM gonols. 3. **Run a suppression sort.** Identify first-cycle carrier vertices, recurrence weights/layers, units that survive as recognizable scaffold, and @@ -310,7 +307,7 @@ Use this shape when compressing a thread or repo audit: char_compress: domain: mode: context-compression | structure-preserving - ucns_relation: skill-level projection of Unit Circle Number System compression mathematics + ucns_relation: no current geometric derivation claimed; local compression notation text_stack: tensor: character twist: space_or_separator @@ -393,7 +390,7 @@ python tools/char_compress_check.py python tools/char_compress_check.py --json ``` -The runner is a guardrail, not the full Unit Circle Number System compression +The runner is a local preservation guardrail, not a UCNS compression engine. It verifies that the fixture skeleton preserves negation, quantifier, order, values, statuses, secrets, `hmmm`, and the theorem/status boundary. @@ -481,7 +478,7 @@ no theorem/proof/status support is transferred beyond the tested UCNS domain. - reconstruction assumes a shared grammar; a different agent grammar may regenerate different bones - `tools/char_compress_check.py` is deterministic fixture support, not a full codec -- the full UCNS compression engine is not implemented in this skill-lib helper yet +- exact historical source for the text-stack model remains unresolved; this helper is not a UCNS codec - whether repeated characters become weights only, ordered recurrence layers only, or both - whether future structure-preserving mode should carry bone fingerprints, diff --git a/docs/propagation-checklist.md b/docs/propagation-checklist.md index 9977aee..239d6a2 100644 --- a/docs/propagation-checklist.md +++ b/docs/propagation-checklist.md @@ -36,6 +36,11 @@ python tools/propagate_skills.py ../target-repo # inspect dry-run python tools/propagate_skills.py ../target-repo --apply # copy skill dirs ``` +A partial `--skills` refresh lists the copied skills under its exact source +commit and keeps every other installed skill in a separate, unrefreshed section. +Owner-written local descriptions are retained. An unrefreshed canonical copy's +prior cited source is retained when known; otherwise it stays `hmmm`. + Then in the target repo: 1. Add or update `.agents/skills/README.md`. diff --git a/gonol-build/SKILL.md b/gonol-build/SKILL.md index 86747c8..0654cc7 100644 --- a/gonol-build/SKILL.md +++ b/gonol-build/SKILL.md @@ -1,6 +1,6 @@ --- name: gonol-build -description: Construction, closure, and replay contract for gonols across UCNS and EDCM. Load this when building or reviewing UCNS geometry used by gonols, or building EDCM character, word, definition, or recursive-relation gonols. UCNS owns geometry; EDCM owns text construction. The required EDCM order is characters -> words -> definitions -> recursive gonol relations. Pronunciation is not required unless an explicitly declared later experiment makes it part of the construction. Do not load for unrelated geometry, ordinary prose editing, or measurement over already-closed gonols. +description: Construction, closure, and replay contract for gonols across UCNS and EDCM. Load this when building or reviewing UCNS geometry used by gonols, or building EDCM character, word, definition, or recursive-relation gonols. UCNS owns geometry; EDCM owns text construction and admissible scale options. Closed gonols participate atomically at any admissible consuming scale; no universal adjacent-scale ladder is required. Pronunciation is not required unless an explicitly declared later experiment makes it part of the construction. Do not load for unrelated geometry, ordinary prose editing, or measurement over already-closed gonols. --- # gonol-build @@ -11,8 +11,8 @@ Use this skill to keep gonol construction on the declared architecture and nothi 1. Resolve the current UCNS and EDCM authorities before building. 2. Before launching construction or replay whose completion materially depends on scarce resources, preflight the resources required to finish the declared scope. -3. Keep the EDCM order load-bearing: characters -> words -> definitions -> recursive gonol relations. -4. Close each completed gonol before it participates atomically at the next declared scale. +3. Resolve the EDCM constructor's declared scale option set and participant eligibility; do not impose a universal adjacent-scale ladder. +4. Close each completed gonol before it participates atomically at an admissible consuming scale. 5. If required UCNS geometry is unresolved, preserve that boundary as `hmmm`. 6. Replay the complete declared scope only where replay is required by the governing protocol. @@ -29,18 +29,25 @@ Resolve the current UCNS and EDCM authorities before building. Do not move text ## EDCM construction contract ```text -characters -> words -> definitions -> recursive gonol relations +declared scale option set + eligible already-closed participants -> construction -> closure ``` -This order is load-bearing. +EDCM owns the admissible scale options. Consult its exact current +`docs/GONOL_LANGUAGE_BOUNDARY.md` and `edcm/gonol.py` contract before selecting +participants. The sequence `characters -> words -> definitions -> recursive +gonol relations` may describe a particular construction, but is not a mandatory +ladder for all EDCM constructions. - Every admitted character is a gonol. -- Ordered character gonols close into a word gonol. -- A closed word gonol is atomic at the consuming scale while its constituent identities, order, multiplicity, source positions, and provenance remain recoverable. -- Definition gonols are constructed from the applicable closed word gonols and exact source definition evidence. +- Ordered character gonols may close into a word gonol under its declared constructor. +- Any closed gonol is atomic at an admissible consuming scale while its constituent identities, order, multiplicity, source positions, and provenance remain recoverable. +- Definition gonols use eligible closed participants and exact source definition evidence; do not require word intermediates when EDCM admits another scale option. - Recursive relations are constructed from already-closed gonols without reopening or erasing their internal structure. -Do not insert another required stage into this sequence unless the governing contract is explicitly changed. +Do not invent participant eligibility or another required stage. A permitted +character-to-definition construction must not be rejected solely because it +omits a word intermediate. Nor does this permit every scale combination: the +owning constructor's option set remains load-bearing. ## Pronunciation boundary @@ -57,7 +64,7 @@ ordered eligible gonols -> authorized UCNS geometric relation/application -> closure -> deterministic identity + provenance receipt --> atomic participation at the next declared scale +-> atomic participation at an admissible consuming scale ``` Preserve exact source identity, occurrence order, multiplicity, and provenance. Do not normalize, deduplicate, infer relations, or substitute tokens, embeddings, hashes, or another representation for gonol identity unless the active contract explicitly authorizes it. @@ -83,19 +90,30 @@ Replay establishes reproducibility of that construction only. It does not by its ## Usage guidance +The executable cross-source witness is `gonol-build/check_edcm_boundary.py`. +Run it against a clean EDCM checkout at the script's exact `EDCM_COMMIT`: + +```bash +python gonol-build/check_edcm_boundary.py /path/to/edcm +``` + +It checks direct character-to-definition construction, replay, candidate standing, +and refusal of an undeclared scale. This pinned witness is not a universal scale +registry; current construction must still resolve its owning EDCM option set. + For text construction, start in EDCM and consume current UCNS geometry. ```text UCNS: geometry -EDCM: characters -> words -> definitions -> recursive gonol relations +EDCM: declared scale options, participant eligibility, text construction ``` -When a word closes, use that word gonol atomically at the next scale. Ignore pronunciation unless a future explicit construction says otherwise. +When a gonol closes, use it atomically at any admissible consuming scale. Ignore pronunciation unless a future explicit construction says otherwise. ## Anti-patterns - Moving text semantics into UCNS or inventing geometry in EDCM. -- Inserting another required EDCM stage without an explicit contract change. +- Imposing an adjacent-scale ladder or inventing an eligible scale option without EDCM authority. - Letting pronunciation alter gonol identity, closure, ordering, or relations unless a later explicitly declared experiment makes phonology part of its construction. - Normalizing, deduplicating, inferring relations, or substituting tokens, embeddings, or hashes for gonol identity unless the active contract explicitly authorizes it. - Adding arbitrary wall-clock limits to a healthy admitted run. diff --git a/gonol-build/check_edcm_boundary.py b/gonol-build/check_edcm_boundary.py new file mode 100644 index 0000000..6a97be7 --- /dev/null +++ b/gonol-build/check_edcm_boundary.py @@ -0,0 +1,62 @@ +# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=12:1 +"""Executable cross-source scale witness; not a geometry or measurement proof. + +Usage: python gonol-build/check_edcm_boundary.py /exact/edcm/checkout +The supplied clean checkout must match EDCM_COMMIT. No package install or network +access is performed by this witness. Refreshing the pin is a reviewed boundary change. +""" + +# === MODULE_BUILD === +# id: gonol_edcm_scale_witness +# module_name: check_edcm_boundary +# module_kind: adapter +# summary: Exercise an exact EDCM constructor's non-adjacent scale and replay contract. +# owner: skill-lib maintainers +# public_surface: check +# internal_surface: none +# auth_boundary: none +# storage_boundary: none +# network_boundary: none +# user_data_boundary: none +# admin_only: false +# tests: explicit CLI against the declared EDCM commit +# rollout: cross-source CI gate +# rollback: retain pin and report boundary as hmmm if unavailable +# === END MODULE_BUILD === + +from pathlib import Path +import subprocess +import sys + +EDCM_COMMIT = "ddc89a97ebbcf0a5863dad6e633b01b520e9bccf" + + +def check(root: Path) -> None: + actual = subprocess.check_output(["git", "-C", str(root), "rev-parse", "HEAD"], text=True).strip() + if actual != EDCM_COMMIT: + raise ValueError(f"expected exact EDCM {EDCM_COMMIT}, got {actual}") + if subprocess.check_output(["git", "-C", str(root), "status", "--porcelain"]): + raise ValueError("EDCM witness requires a clean source checkout") + sys.path.insert(0, str(root.resolve())) + from edcm.gonol import construct_gonol, replay_gonol, GonolConstructionError + + character = construct_gonol(scale="character", source="x", source_id="skill-lib:character") + definition = construct_gonol(scale="definition", source="bounded evidence", + relation="skill-lib:defined-by", participants=(character.gonol,), + source_id="skill-lib:definition") + assert definition.gonol.participants == (character.gonol,) + assert replay_gonol(receipt=definition).receipt_digest == definition.receipt_digest + assert definition.standing == "implemented-candidate" + assert definition.selection_effect == "none" + try: + construct_gonol(scale="undeclared-scale", source="x", source_id="skill-lib:invalid") + except GonolConstructionError: + pass + else: + raise AssertionError("undeclared scale must not become eligible") + print(f"PASS EDCM {actual}: direct character-to-definition, replay, candidate non-transfer, rejected undeclared scale") + + +if __name__ == "__main__": + check(Path(sys.argv[1])) +# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=12:1 diff --git a/skill-lib_msdmd.ts b/skill-lib_msdmd.ts index f985a6b..1a17408 100644 --- a/skill-lib_msdmd.ts +++ b/skill-lib_msdmd.ts @@ -9,6 +9,15 @@ import { defineMsdmdCollection } from "./msdmd/collection"; export default defineMsdmdCollection({ repo: "The-Interdependency/skill-lib", declarations: [ + { + file: "gonol-build/check_edcm_boundary.py", + block: "MODULE_BUILD", + id: "gonol_edcm_scale_witness", + fields: { + source: "gonol-build/check_edcm_boundary.py", + summary: "Exact EDCM cross-source witness for non-adjacent scale construction, replay, and candidate non-transfer; not geometry or measurement proof", + }, + }, { file: "msdmd/SKILL.md", block: "DOCS", diff --git a/skills.json b/skills.json index 26bad31..bce0347 100644 --- a/skills.json +++ b/skills.json @@ -23,14 +23,14 @@ {"name":"domain-claims","path":"domain-claims/SKILL.md","kind":"procedural","description":"Domain-first lexical and semantic governance for canonical terms. Load this when a word or phrase is being promoted into a theorem term, ontology primitive, schema field, encoding label, skill doctrine, cross-domain mapping, or other meaning-bearing control surface; when multiple domains use the same word differently; when an acronym, initialism, symbol, or compact handle is being mistaken for a fixed expansion or definition; or when conversational provenance is about to be attached to a definition. Do not load for ordinary prose, casual wording choices, or simple dictionary explanations that will not control canon or structure."}, {"name":"manifest","path":"manifest/SKILL.md","kind":"metadata-block","depends_on":["msdmd"],"description":"Living-spec generator. Derives the mechanical, observable facts of a repo (package name, version, description, license, authors, repository, build backend, development status, supported Python versions, keywords, runtime dependencies, optional extras, top-level layout, CI workflows) from pyproject.toml + the file tree and splices them into a machine-owned, marked block inside CLAUDE.md — keeping the doc from silently drifting from the code. Ships a stdlib-only generator with --write (refresh), --check (CI drift gate), and --print modes. Load this when: setting up or maintaining a CLAUDE.md / AGENTS.md so its factual half is generated rather than hand-typed; wiring a CI check that fails when docs drift from pyproject/version/deps/layout; deciding which parts of a doc to generate vs. hand-author; or onboarding a new org repo to the living-spec convention."}, {"name":"llms-build","path":"llms-build/SKILL.md","kind":"metadata-block","depends_on":["msdmd"],"description":"Self-declaring LLM instructions file (llms.txt) built on msdmd. Modules or central files declare LLMS blocks with project overview, key definitions, architecture summary, and agent usage rules. A runner aggregates them into a standardized root llms.txt and surfaces drift/gaps. Load this when creating, updating, or maintaining llms.txt for any repo consumed by LLMs or agents."}, - {"name":"char-compress","path":"char-compress/SKILL.md","kind":"procedural","description":"Character-based context compression for agent handoff and skill writing, derived from the mathematics of the Unit Circle Number System. Use this when compressing a long thread, document, repo audit, canon handoff, or agent working-memory state; when a context window is filling and operative facts must survive; when writing a SKILL.md that should be flesh-dense and bone-sparse; or when checking whether a compression deleted negation, order, quantifier, operator, named object, value, decision, or unresolved hmmm. This is a procedural skill-level projection of UCNS compression mathematics, not a UCNS-A theorem/status transfer and not an edcmbone metric implementation."}, + {"name":"char-compress","path":"char-compress/SKILL.md","kind":"procedural","description":"Character-based context compression for agent handoff and skill writing, owned as a skill-lib procedure rather than current UCNS mathematics. Use this when compressing a long thread, document, repo audit, canon handoff, or agent working-memory state; when a context window is filling and operative facts must survive; when writing a SKILL.md that should be flesh-dense and bone-sparse; or when checking whether a compression deleted negation, order, quantifier, operator, named object, value, decision, or unresolved hmmm. Historical bone/flesh and text-stack terminology is local compression notation, not a UCNS theorem/status transfer, EDCM constructor, or edcmbone metric implementation."}, {"name":"visitor-intro","path":"visitor-intro/SKILL.md","kind":"procedural","description":"Onboarding tour for visitors arriving at any The-Interdependency repo. Load this when an unfamiliar user asks \"what is this?\", \"what is The Interdependency?\", \"how do these repos fit together?\", \"where do I start?\", or otherwise signals they are new to the org. Gives the agent a consistent, repo-aware way to orient a newcomer without inventing facts."}, {"name":"agent-instantiation","path":"agent-instantiation/SKILL.md","kind":"procedural","description":"Methodology for instantiating, forking, running, merging, and retiring agents in the a0 platform and its near-identical mirror a0ucns. Load this when adding or changing a sub-agent spawn path, a PCNA instance fork/merge, an agent definition or naming scheme, spawn caps or approval gating, an agent run/log table, a heartbeat-driven agent task, or a checkpoint of agent state. Use it before writing any code that creates, addresses, schedules, or tears down an agent or sub-agent, so the new code follows the platform's existing lifecycle, fork/merge, identity, and gating contracts rather than inventing a parallel one. NOTE: a0-betatest (a0p) has diverged to a different per-user CRUD + native-ZFAE instancing model — this skill's spawn/fork/merge sequence does NOT apply there; see \"a0-betatest divergence\"."}, {"name":"a0p-instancing","path":"a0p-instancing/SKILL.md","kind":"procedural","description":"Methodology for instancing agents in a0-betatest (the a0p research instrument), whose model diverges from canonical a0. Load this when adding or changing an AgentInstance / CharacterSheet CRUD path, a per-instance native ZFAE weight bank or its training/distillation loop, a ZFAE inference mode, a sentinel evaluation or pending-override gate, a per-agent safetensors checkpoint, or volatile sub-context memory — anywhere under a0-betatest `backend/`. Use it before writing code that creates, addresses, trains, runs, governs, or persists an a0p agent, so the code follows a0p's per-user CRUD + native-ZFAE + sentinel model instead of a0's spawn/fork/merge model. For canonical a0 and its mirror a0ucns, use `agent-instantiation` instead — a0p does NOT have `sub_agent_spawn`, a spawn executor, or `InstanceMerge`."}, {"name":"plain-lens","path":"plain-lens/SKILL.md","kind":"procedural","description":"Building a plain-language, multi-lens companion view of dense canonical text — an easier on-ramp that does not replace or talk down to the source. Load this when you are asked to make an informationally dense document (canon, spec, articles, legal/normative text) easier to approach for newcomers; when building an \"explain it through the lens of X\" selector (domain, audience, or role); when designing progressive-disclosure or layered ELI-not-stupid reading UX; when a dynamic, data-driven site must keep its existing static page as a graceful fallback; or when you need an EDCM-style two-speaker tension reading between a body text and its footnotes/caveats. Use this when the risk is either drowning readers in density or insulting them with oversimplification."}, {"name":"thought-lens","path":"thought-lens/SKILL.md","kind":"procedural","description":"Translate raw, context-heavy, recursive, fragmentary, coined, or private-language thought into audience-legible language without changing the underlying claim. Load this when a user says people do not understand what they mean; asks to make a thought understandable to strangers, the public, a specific audience, or a platform; supplies dense notes rather than finished prose; needs jargon or coined terms introduced only after their ordinary-language meaning lands; or wants multiple audience/surface renderings from one thought. Do not load merely to polish finished prose or to simplify an already-stable canonical document; use ordinary editing for the former and plain-lens for the latter."}, {"name":"meta","path":"meta/SKILL.md","kind":"procedural","description":"METAPAT consultation router for The Interdependency. Load this when deciding which distinctions, relations, boundaries, transformations, scales, or cross-domain correspondences should organize downstream work; when examining available observations or metrics to determine which questions and projections are worth measuring; when the-interdependency skill's METAPAT consultation gate triggers; when an unresolved conceptual choice would constrain architecture, semantics, measurement, ontology, or later claims; or when explicitly asked to consult, apply, or interpret current METAPAT. Do not load merely for routine implementation under already-fixed conceptual contracts."}, - {"name":"gonol-build","path":"gonol-build/SKILL.md","kind":"procedural","description":"Construction, closure, and replay contract for gonols across UCNS and EDCM. Load this when building or reviewing UCNS geometry used by gonols, or building EDCM character, word, definition, or recursive-relation gonols. UCNS owns geometry; EDCM owns text construction. The required EDCM order is characters -> words -> definitions -> recursive gonol relations. Pronunciation is not required unless an explicitly declared later experiment makes it part of the construction. Do not load for unrelated geometry, ordinary prose editing, or measurement over already-closed gonols."}, + {"name":"gonol-build","path":"gonol-build/SKILL.md","kind":"procedural","description":"Construction, closure, and replay contract for gonols across UCNS and EDCM. Load this when building or reviewing UCNS geometry used by gonols, or building EDCM character, word, definition, or recursive-relation gonols. UCNS owns geometry; EDCM owns text construction and admissible scale options. Closed gonols participate atomically at any admissible consuming scale; no universal adjacent-scale ladder is required. Pronunciation is not required unless an explicitly declared later experiment makes it part of the construction. Do not load for unrelated geometry, ordinary prose editing, or measurement over already-closed gonols."}, {"name":"ucns-option-selection","path":"ucns-option-selection/SKILL.md","kind":"procedural","description":"Fail-closed rubric for comparing, retaining, rejecting, deprecating, and selecting UCNS options within an explicit scope. Load this when an agent asks which UCNS candidate should win, whether evidence authorizes selection, how an option moves from registered or implemented to selected, how to compare competing gonol constructors, carriers, geometries, policies, projections, or measurement candidates, or how to issue a scoped UCNS decision receipt. Do not load merely to register options, execute one already-selected option, or choose ordinary UI preferences. Never select universal UCNS canon by score, familiarity, implementation order, or EDCM-local evidence."}, {"name":"epac-selection-display","path":"epac-selection-display/SKILL.md","kind":"procedural","description":"Evidence-bound EPAC target selection and display for WebMCP handoffs and other human-facing surfaces. Load this when choosing an EPAC element, molecule, construction receipt, comparison result, or available visualization to present; when preparing a receipt-backed EPAC display packet; when exposing the EPAC workflow as a selectable WebMCP skill; or when a requested EPAC display would require missing or invented geometry so the request can be refused or downgraded to verified source-backed output. Do not load to select EPAC or a UCNS candidate as canon, or for unrelated WebMCP catalogue changes."}, {"name":"the-interdependency","path":"the-interdependency/SKILL.md","kind":"procedural","description":"Protocol and workflow for all tasks involving The Interdependency organization, its repositories, The Interdependent Way projects, EDCMBONE transcript analysis, code building, research, GitHub maintenance and updates. Load this whenever the task or context touches The-Interdependency assets, or on phrases like \"assemble edcmbone transcripts for analysis\", \"write code that...\", or any GitHub/research/build work on org projects."}, diff --git a/skills/char-compress/SKILL.md b/skills/char-compress/SKILL.md index bfe343a..a37f932 100644 --- a/skills/char-compress/SKILL.md +++ b/skills/char-compress/SKILL.md @@ -1,6 +1,6 @@ --- name: char-compress -description: "Character-based context compression for agent handoff and skill writing, derived from the mathematics of the Unit Circle Number System. Use this when compressing a long thread, document, repo audit, canon handoff, or agent working-memory state; when a context window is filling and operative facts must survive; when writing a SKILL.md that should be flesh-dense and bone-sparse; or when checking whether a compression deleted negation, order, quantifier, operator, named object, value, decision, or unresolved hmmm. This is a procedural skill-level projection of UCNS compression mathematics, not a UCNS-A theorem/status transfer and not an edcmbone metric implementation." +description: "Character-based context compression for agent handoff and skill writing, owned as a skill-lib procedure rather than current UCNS mathematics. Use this when compressing a long thread, document, repo audit, canon handoff, or agent working-memory state; when a context window is filling and operative facts must survive; when writing a SKILL.md that should be flesh-dense and bone-sparse; or when checking whether a compression deleted negation, order, quantifier, operator, named object, value, decision, or unresolved hmmm. Historical bone/flesh and text-stack terminology is local compression notation, not a UCNS theorem/status transfer, EDCM constructor, or edcmbone metric implementation." --- diff --git a/skills/gonol-build/SKILL.md b/skills/gonol-build/SKILL.md index 2d1865a..9125b71 100644 --- a/skills/gonol-build/SKILL.md +++ b/skills/gonol-build/SKILL.md @@ -1,6 +1,6 @@ --- name: gonol-build -description: "Construction, closure, and replay contract for gonols across UCNS and EDCM. Load this when building or reviewing UCNS geometry used by gonols, or building EDCM character, word, definition, or recursive-relation gonols. UCNS owns geometry; EDCM owns text construction. The required EDCM order is characters -> words -> definitions -> recursive gonol relations. Pronunciation is not required unless an explicitly declared later experiment makes it part of the construction. Do not load for unrelated geometry, ordinary prose editing, or measurement over already-closed gonols." +description: "Construction, closure, and replay contract for gonols across UCNS and EDCM. Load this when building or reviewing UCNS geometry used by gonols, or building EDCM character, word, definition, or recursive-relation gonols. UCNS owns geometry; EDCM owns text construction and admissible scale options. Closed gonols participate atomically at any admissible consuming scale; no universal adjacent-scale ladder is required. Pronunciation is not required unless an explicitly declared later experiment makes it part of the construction. Do not load for unrelated geometry, ordinary prose editing, or measurement over already-closed gonols." --- diff --git a/tests/test_char_compress_authority.py b/tests/test_char_compress_authority.py new file mode 100644 index 0000000..9c7aeb5 --- /dev/null +++ b/tests/test_char_compress_authority.py @@ -0,0 +1,23 @@ +"""Guard the local-notation boundary separately from preservation fixtures.""" +from pathlib import Path +import unittest + +ROOT = Path(__file__).resolve().parents[1] + + +class CharCompressAuthorityTests(unittest.TestCase): + def test_local_notation_does_not_claim_current_geometry(self): + text = (ROOT / "char-compress/SKILL.md").read_text() + compact = " ".join(text.split()) + self.assertIn("Optional local text-stack notation", text) + self.assertIn("not a UCNS construction law or a mandatory EDCM scale ladder", compact) + self.assertIn("EDCM owns text-domain gonol construction", text) + self.assertIn("no current UCNS mathematical derivation is claimed", compact) + for false_claim in ("Punctuation is a stronger typed twist", "Its mathematics is the source of the compression algorithm"): + self.assertNotIn(false_claim, compact) + + def test_preservation_guards_survive_authority_correction(self): + text = (ROOT / "char-compress/SKILL.md").read_text() + for guard in ("Freeze dangerous bones", "Reconstruct and compare", "Carry hmmm", + "lost recurrence order", "dropped negation", "changed proof/status label"): + self.assertIn(guard, text) diff --git a/tests/test_gonol_build_skill.py b/tests/test_gonol_build_skill.py index 59defc4..5110031 100644 --- a/tests/test_gonol_build_skill.py +++ b/tests/test_gonol_build_skill.py @@ -22,7 +22,7 @@ def test_activation_contract_is_concrete(self) -> None: for phrase in ( "character, word, definition, or recursive-relation gonols", "UCNS owns geometry; EDCM owns text construction", - "characters -> words -> definitions -> recursive gonol relations", + "no universal adjacent-scale ladder is required", "Pronunciation is not required", "Do not load", ): @@ -38,27 +38,25 @@ def test_authority_split_is_minimal(self) -> None: ): self.assertIn(phrase, self.compact) - def test_edcm_skeleton_requires_words(self) -> None: - self.assertIn( - "characters -> words -> definitions -> recursive gonol relations", - self.compact, - ) - self.assertNotIn("characters -> definitions -> recursive gonol relations", self.compact) - self.assertIn("This order is load-bearing", self.compact) - self.assertIn("Ordered character gonols close into a word gonol", self.compact) + def test_scale_options_are_owned_by_edcm(self) -> None: + self.assertIn("`docs/GONOL_LANGUAGE_BOUNDARY.md`", self.text) + self.assertIn("`edcm/gonol.py`", self.text) + self.assertIn("not a mandatory ladder", self.compact) + self.assertIn("character-to-definition construction must not be rejected", self.compact) + self.assertNotIn("This order is load-bearing", self.compact) def test_closed_words_promote_atomically(self) -> None: for phrase in ( - "A closed word gonol is atomic at the consuming scale", + "Any closed gonol is atomic at an admissible consuming scale", "constituent identities, order, multiplicity, source positions, and provenance remain recoverable", - "Definition gonols are constructed from the applicable closed word gonols", + "Definition gonols use eligible closed participants", "Recursive relations are constructed from already-closed gonols", ): self.assertIn(phrase, self.compact) def test_no_undeclared_intermediate_stage(self) -> None: self.assertIn( - "Do not insert another required stage into this sequence unless the governing contract is explicitly changed", + "Do not invent participant eligibility or another required stage", self.compact, ) @@ -108,7 +106,7 @@ def test_workflow_preflights_before_compute_and_replays_conditionally(self) -> N self.assertIn(phrase, workflow) self.assertLess( workflow.index("Before launching construction or replay"), - workflow.index("Keep the EDCM order load-bearing"), + workflow.index("Resolve the EDCM constructor's declared scale option set"), ) self.assertNotIn( "Preflight resources before a completion claim, then replay the complete declared scope", @@ -134,7 +132,7 @@ def test_anti_patterns_preserve_explicit_contract_exceptions(self) -> None: def test_usage_guidance_repeats_operational_contract(self) -> None: self.assertIn("For text construction, start in EDCM and consume current UCNS geometry", self.compact) - self.assertIn("When a word closes, use that word gonol atomically at the next scale", self.compact) + self.assertIn("When a gonol closes, use it atomically at any admissible consuming scale", self.compact) self.assertIn("Ignore pronunciation unless a future explicit construction says otherwise", self.compact) def test_codex_adapter_points_to_canonical_skill(self) -> None: diff --git a/tests/test_propagate_skills.py b/tests/test_propagate_skills.py index 5bb4f7e..1197099 100644 --- a/tests/test_propagate_skills.py +++ b/tests/test_propagate_skills.py @@ -17,6 +17,24 @@ class PropagateDoctrineTest(unittest.TestCase): + def test_partial_refresh_preserves_local_skill_index_and_description(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + target = Path(tmp) + root = target / ".agents/skills" + for name in ("hmmm", "test-build"): + path = root / name / "SKILL.md" + path.parent.mkdir(parents=True) + path.write_text("owner-retained content\n", encoding="utf-8") + local_entry = "- `hmmm/` — mandatory unresolved-constraint boundary object" + (root / "README.md").write_text(local_entry + "\n", encoding="utf-8") + for _ in range(2): + self.assertEqual(ps.main([str(target), "--skills", "msdmd", "--apply"]), 0) + readme = (root / "README.md").read_text(encoding="utf-8") + self.assertEqual(readme.count(local_entry), 1) + self.assertIn("- `test-build/`", readme) + self.assertIn("not refreshed by this propagation", readme) + self.assertEqual((root / "hmmm/SKILL.md").read_text(), "owner-retained content\n") + def test_referenced_doctrine_helper_finds_link(self) -> None: # canonical msdmd/SKILL.md links to ../doctrine/msdmd-checks.md refs = ps.referenced_doctrine([ROOT / "msdmd"]) diff --git a/tools/propagate_skills.py b/tools/propagate_skills.py index b7c033c..14aa245 100644 --- a/tools/propagate_skills.py +++ b/tools/propagate_skills.py @@ -1,4 +1,4 @@ -# ratios: loc_comments=162:12 imports_exports=9:10 calls_definitions=80:10 +# ratios: loc_comments=182:13 imports_exports=9:10 calls_definitions=91:10 """Synchronize canonical skill-lib skills into a target repo working tree. This script is intentionally local-file based. It does not push, commit, open @@ -112,6 +112,19 @@ def referenced_doctrine(skill_srcs: Iterable[Path]) -> List[str]: def write_readme(target_install_root: Path, sha: str, skills: Sequence[str]) -> None: + readme = target_install_root / "README.md" + old_text = readme.read_text(encoding="utf-8") if readme.is_file() else "" + old_entries = dict(re.findall(r"^(- `([^`/]+)/`[^\n]*)$", old_text, re.MULTILINE)) + # Preserve owner-written descriptions for installed but unrefreshed skills. + by_name = {name: line for line, name in old_entries.items()} + others = sorted(path.parent.name for path in target_install_root.glob("*/SKILL.md") + if path.parent.name not in skills) + prior = previous_source_sha(target_install_root) + canonical = set(load_skill_names()) + for name in others: + if name in canonical and "prior source:" not in by_name.get(name, ""): + identity = prior if name in by_name and prior else "hmmm" + by_name[name] = by_name.get(name, f"- `{name}/`") + f" [not refreshed; prior source: `{identity}`]" lines = [ "# Local agent skills", "", @@ -123,11 +136,19 @@ def write_readme(target_install_root: Path, sha: str, skills: Sequence[str]) -> "Repo-local copies are not the source of truth. Edit `skill-lib` first,", "then propagate from the canonical source.", "", - "Installed skills:", + "Skills refreshed from the source commit above:", "", ] lines.extend(f"- `{name}/`" for name in skills) lines.append("") + if others: + lines.extend([ + "Other installed skills (not refreshed by this propagation):", "", + "Their existing files retain their own authority/provenance; the source", + "commit above does not assert that these copies were refreshed.", "", + ]) + lines.extend(by_name.get(name, f"- `{name}/`") for name in others) + lines.append("") target_install_root.mkdir(parents=True, exist_ok=True) (target_install_root / "README.md").write_text("\n".join(lines), encoding="utf-8") @@ -207,4 +228,4 @@ def main(argv: Sequence[str] | None = None) -> int: if __name__ == "__main__": raise SystemExit(main()) -# ratios: loc_comments=162:12 imports_exports=9:10 calls_definitions=80:10 +# ratios: loc_comments=182:13 imports_exports=9:10 calls_definitions=91:10 From bb0b2aedae2c51381fa5274f3d1333a0feaca6ba Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:00:13 -0700 Subject: [PATCH 02/25] fix(char-compress): align generated authority definition --- llms/metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llms/metadata.py b/llms/metadata.py index acadced..b003f97 100644 --- a/llms/metadata.py +++ b/llms/metadata.py @@ -8,7 +8,7 @@ # # id: key_definitions # msdmd: Module Self-Declared Metadata in Markdown — the foundational convention where each source module declares its own structured metadata in a fenced comment block. -# char-compress: Character-based context compression for agent handoff and skill writing, derived from the mathematics of the Unit Circle Number System. +# char-compress: Skill-lib-owned character-based context compression for agent handoff and skill writing; its historical bone/flesh and text-stack notation is not current UCNS mathematics. # llms-build: Self-declaring LLM instructions file generation from LLMS blocks into canonical root llms.txt. # # id: architecture_summary @@ -24,4 +24,4 @@ # - Write unresolved or missing values as hmmm. # - Edit source LLMS blocks before regenerating llms.txt. # === END LLMS === -# ratios: loc_comments=0:24 imports_exports=0:0 calls_definitions=0:0 +# ratios: loc_comments=0:24 imports_exports=0:0 calls_definitions=0:0 \ No newline at end of file From 73d0ca0046e6e94244693f4b25ab90d3fe162213 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:00:22 -0700 Subject: [PATCH 03/25] chore(llms): regenerate char-compress authority text --- llms.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llms.txt b/llms.txt index b52863f..00f21a7 100644 --- a/llms.txt +++ b/llms.txt @@ -6,7 +6,7 @@ It provides msdmd-based metadata skills, procedural skills, pure-stdlib helper t ## Key Definitions (never infer or expand these) - **msdmd** = Module Self-Declared Metadata in Markdown — the foundational convention where each source module declares its own structured metadata in a fenced comment block. -- **char-compress** = Character-based context compression for agent handoff and skill writing, derived from the mathematics of the Unit Circle Number System. +- **char-compress** = Skill-lib-owned character-based context compression for agent handoff and skill writing; its historical bone/flesh and text-stack notation is not current UCNS mathematics. - **llms-build** = Self-declaring LLM instructions file generation from LLMS blocks into canonical root llms.txt. ## Architecture Summary @@ -22,4 +22,4 @@ It provides msdmd-based metadata skills, procedural skills, pure-stdlib helper t - Write unresolved or missing values as hmmm. - Edit source LLMS blocks before regenerating llms.txt. -This file is the single source of truth. If something is not explicitly stated in the files listed above, it does not exist in this repository. +This file is the single source of truth. If something is not explicitly stated in the files listed above, it does not exist in this repository. \ No newline at end of file From b5cd253651074931fa9c447cb90c7b61ddf58367 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:00:48 -0700 Subject: [PATCH 04/25] fix(gonol-build): make cross-source witness optimization-safe --- gonol-build/check_edcm_boundary.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gonol-build/check_edcm_boundary.py b/gonol-build/check_edcm_boundary.py index 6a97be7..3a30564 100644 --- a/gonol-build/check_edcm_boundary.py +++ b/gonol-build/check_edcm_boundary.py @@ -1,4 +1,4 @@ -# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=12:1 +# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=16:1 """Executable cross-source scale witness; not a geometry or measurement proof. Usage: python gonol-build/check_edcm_boundary.py /exact/edcm/checkout @@ -44,10 +44,10 @@ def check(root: Path) -> None: definition = construct_gonol(scale="definition", source="bounded evidence", relation="skill-lib:defined-by", participants=(character.gonol,), source_id="skill-lib:definition") - assert definition.gonol.participants == (character.gonol,) - assert replay_gonol(receipt=definition).receipt_digest == definition.receipt_digest - assert definition.standing == "implemented-candidate" - assert definition.selection_effect == "none" + if definition.gonol.participants != (character.gonol,): raise AssertionError("definition participants changed") + if replay_gonol(receipt=definition).receipt_digest != definition.receipt_digest: raise AssertionError("replay digest changed") + if definition.standing != "implemented-candidate": raise AssertionError("candidate standing changed") + if definition.selection_effect != "none": raise AssertionError("selection effect transferred") try: construct_gonol(scale="undeclared-scale", source="x", source_id="skill-lib:invalid") except GonolConstructionError: @@ -59,4 +59,4 @@ def check(root: Path) -> None: if __name__ == "__main__": check(Path(sys.argv[1])) -# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=12:1 +# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=16:1 \ No newline at end of file From c6f8ac6c5258e1681a38170dc0e7d027d009b783 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:02:38 -0700 Subject: [PATCH 05/25] fix(propagation): honor per-skill prior source pins --- tools/propagate_skills.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tools/propagate_skills.py b/tools/propagate_skills.py index 14aa245..9398e4f 100644 --- a/tools/propagate_skills.py +++ b/tools/propagate_skills.py @@ -1,4 +1,4 @@ -# ratios: loc_comments=182:13 imports_exports=9:10 calls_definitions=91:10 +# ratios: loc_comments=193:14 imports_exports=9:11 calls_definitions=96:11 """Synchronize canonical skill-lib skills into a target repo working tree. This script is intentionally local-file based. It does not push, commit, open @@ -26,6 +26,7 @@ # those must be carried alongside the skills or the vendored links go dead. DOCTRINE_REF_RE = re.compile(r"(?:\.\./)?doctrine/([A-Za-z0-9][\w./-]*\.md)") SOURCE_SHA_RE = re.compile(r"Source commit:[^\n]*`([0-9a-f]{7,40})`") +SKILL_SOURCE_RE = re.compile(r"^- `([^`/]+)/`[^\n]*\[not refreshed; prior source: `([0-9a-f]{7,40}|hmmm)`\]$", re.MULTILINE) _TEXT_SUFFIXES = {".md", ".py", ".ts", ".txt"} @@ -65,6 +66,18 @@ def previous_source_sha(target_install_root: Path) -> str | None: return match.group(1) if match else None +def previous_skill_source_sha(target_install_root: Path, skill_name: str) -> str | None: + """Return a skill-local prior source recorded by an earlier partial refresh.""" + readme = target_install_root / "README.md" + if not readme.is_file(): + return None + text = readme.read_text(encoding="utf-8") + for name, sha in SKILL_SOURCE_RE.findall(text): + if name == skill_name: + return None if sha == "hmmm" else sha + return None + + def previous_canonical_blob(sha: str, skill_name: str, relative_path: Path) -> bytes | None: result = subprocess.run( ["git", "-C", str(ROOT), "show", f"{sha}:{skill_name}/{relative_path.as_posix()}"], @@ -215,7 +228,8 @@ def main(argv: Sequence[str] | None = None) -> int: shutil.rmtree(dst) removed_files: List[tuple[str, Path]] = [] for src, dst in actions: - removed_files.extend((src.name, path) for path in sync_tree(src, dst, prior_sha)) + skill_prior_sha = previous_skill_source_sha(install_root, src.name) or prior_sha + removed_files.extend((src.name, path) for path in sync_tree(src, dst, skill_prior_sha)) for src, dst in doc_actions: dst.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(src, dst) @@ -228,4 +242,4 @@ def main(argv: Sequence[str] | None = None) -> int: if __name__ == "__main__": raise SystemExit(main()) -# ratios: loc_comments=182:13 imports_exports=9:10 calls_definitions=91:10 +# ratios: loc_comments=193:14 imports_exports=9:11 calls_definitions=96:11 \ No newline at end of file From b85ef39c16cb60af21f84c7ab1f99c04b6feba28 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:03:06 -0700 Subject: [PATCH 06/25] test(propagation): cover per-skill prior source refresh --- tests/test_propagate_skills.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/test_propagate_skills.py b/tests/test_propagate_skills.py index 1197099..87bdf79 100644 --- a/tests/test_propagate_skills.py +++ b/tests/test_propagate_skills.py @@ -35,6 +35,26 @@ def test_partial_refresh_preserves_local_skill_index_and_description(self) -> No self.assertIn("not refreshed by this propagation", readme) self.assertEqual((root / "hmmm/SKILL.md").read_text(), "owner-retained content\n") + def test_partial_refresh_uses_annotated_skill_prior_source(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + target = Path(tmp) + root = target / ".agents/skills" + skill = root / "test-build" / "SKILL.md" + skill.parent.mkdir(parents=True) + skill.write_text("older canonical copy\n", encoding="utf-8") + (root / "README.md").write_text( + "# Local agent skills\n\n" + "Source commit: `bbbbbbb`\n\n" + "Other installed skills (not refreshed by this propagation):\n\n" + "- `test-build/` [not refreshed; prior source: `aaaaaaa`]\n", + encoding="utf-8", + ) + with patch.object(ps, "current_sha", return_value="ccccccc"), patch.object( + ps, "sync_tree", return_value=[] + ) as sync: + self.assertEqual(ps.main([str(target), "--skills", "test-build", "--apply"]), 0) + self.assertEqual(sync.call_args.args[2], "aaaaaaa") + def test_referenced_doctrine_helper_finds_link(self) -> None: # canonical msdmd/SKILL.md links to ../doctrine/msdmd-checks.md refs = ps.referenced_doctrine([ROOT / "msdmd"]) @@ -94,4 +114,4 @@ def prior_blob(_sha: str, _skill: str, path: Path) -> bytes | None: if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file From 455f5d26b0290a3acf96768be147e21b1134fe9b Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:05:28 -0700 Subject: [PATCH 07/25] fix(char-compress): keep optional notation out of required workflow --- char-compress/SKILL.md | 88 +++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/char-compress/SKILL.md b/char-compress/SKILL.md index 20d3fd2..04eb0af 100644 --- a/char-compress/SKILL.md +++ b/char-compress/SKILL.md @@ -257,7 +257,7 @@ Use suppression as a classifier, not as the complete codec: survives suppression + grammar can restore it -> candidate bone breaks under suppression or carries operative fact -> flesh looks grammatical but controls polarity/order/scope/status -> frozen bone -space/twist changes attachment or closure -> twist data must be preserved +separator/boundary data that changes attachment or closure must be preserved ``` ## Compression procedure @@ -269,9 +269,11 @@ space/twist changes attachment or closure -> twist data must be preserved sentence, or other boundaries. The optional local text-stack notation above is not required and does not construct UCNS geometry or EDCM gonols. -3. **Run a suppression sort.** Identify first-cycle carrier vertices, - recurrence weights/layers, units that survive as recognizable scaffold, and - units that become ambiguous or lose operative force. +3. **Run a suppression sort.** Identify first-occurrence inventory, + recurrence data required for reconstruction, units that survive as + recognizable scaffold, and units that become ambiguous or lose operative + force. Historical `carrier`/`layer` labels apply only when that optional + notation is explicitly selected. 4. **Extract flesh once.** Record every distinct operative item in resolved form. Do not repeat a flesh item unless the repetition itself is meaningful. @@ -284,9 +286,10 @@ space/twist changes attachment or closure -> twist data must be preserved regenerable. Promote the transform to frozen bone when it changes status, safety, legality, or theorem scope. -7. **Preserve twist data where it changes attachment.** Spaces, punctuation, - paragraph breaks, and other separators are twist seams. Drop only those twist - details that are safe to regenerate. +7. **Preserve boundary data where it changes attachment.** Spaces, punctuation, + paragraph breaks, and other separators must survive when they affect + attachment or closure. Call them `twist` data only when using the optional + historical notation. 8. **Drop regenerable scaffold.** Remove articles, routine connective prose, and repeated explanation that adds no new operative item. @@ -296,35 +299,30 @@ space/twist changes attachment or closure -> twist data must be preserved 10. **Reconstruct and compare.** Regenerate readable prose around the skeleton. Check named objects, values, decisions, negations, operators, order, - statuses, twist closure, and hmmm. If any operative item is missing or - inverted, move it to flesh, frozen bone, or preserved twist data. + statuses, boundary/attachment closure, and hmmm. If any operative item is + missing or inverted, move it to flesh, frozen bone, or preserved boundary + data. ## Output shape for compressed handoffs -Use this shape when compressing a thread or repo audit: +Use this notation-neutral shape when compressing a thread or repo audit. Include +`text_stack` only when the optional historical notation is actually selected. ```yaml char_compress: domain: mode: context-compression | structure-preserving - ucns_relation: no current geometric derivation claimed; local compression notation - text_stack: - tensor: character - twist: space_or_separator - word: character_gonol - sentence: word_gonol - paragraph: sentence_gonol - chapter: paragraph_gonol - volume: chapter_gonol + ucns_relation: no current geometric derivation claimed + local_notation: none | historical-text-stack flesh: - frozen_bones: - - twist_data: + boundary_data: - recurrence: - - carrier: - weights_or_layers: + - unit: + positions_or_weights: transforms: - root: transform: @@ -340,12 +338,25 @@ char_compress: order: pass | fail operators: pass | fail statuses: pass | fail - twist_closure: pass | fail + boundary_closure: pass | fail hmmm: pass | fail hmmm: - ``` +Optional historical extension: + +```yaml +text_stack: + tensor: character + twist: space_or_separator + word: character_gonol + sentence: word_gonol + paragraph: sentence_gonol + chapter: paragraph_gonol + volume: chapter_gonol +``` + ## Skill-writing use A `SKILL.md` should be flesh-dense and bone-sparse. @@ -368,7 +379,7 @@ Do not remove: ```text negation, ordering, scope, proof boundary, security warning, privacy status, -operator semantics, failure criteria, twist closure +operator semantics, failure criteria, attachment/closure boundaries ``` Test a skill by stripping the connective prose. If the operative content still @@ -423,16 +434,16 @@ Minimum fixture set for an implementation: 6. secret_preserved: private carrier material stays private 7. hmmm_preserved: unresolved constraints remain visible 8. no_theorem_transfer: output does not claim unearned theorem/status support -9. twist_preserved: spaces/punctuation/breaks that change attachment survive -10. recurrence_preserved: repeated characters/words/sentences keep required weight or layer data +9. boundary_preserved: spaces/punctuation/breaks that change attachment survive +10. recurrence_preserved: repeated units keep required position/order/weight data ``` ## Security note Compression is not opacity. Bone fingerprints leak structure: clause count, -hinge placement, relation shape, twist placement, and sometimes operator class. -If opacity is required, the inventory-to-position mapping is key material and -must not be published. +hinge placement, relation shape, boundary placement, and sometimes operator +class. If opacity is required, the inventory-to-position mapping is key material +and must not be published. Do not place private carrier arrangements, slot maps, secret alphabets, or cryptographic mappings in public skills, public README files, demos, tests, or @@ -446,23 +457,28 @@ A compression is complete when: all flesh appears once in resolved form; all frozen bones are explicit; transforms are root + transform; -text-stack scale is declared; -twist seams that affect closure/attachment are preserved; -recurrence weights/layers required for reconstruction are preserved; +source grouping and grammar required for reconstruction are declared; +boundary/separator details that affect closure or attachment are preserved; +recurrence position/order/weight data required for reconstruction are preserved; regenerable scaffold is absent or fingerprinted according to mode; hmmm is visible; reconstruction preserves named objects, values, decisions, negation, -quantifiers, order, operators, statuses, twist closure, recurrence, and unresolved constraints; -no theorem/proof/status support is transferred beyond the tested UCNS domain. +quantifiers, order, operators, statuses, boundary closure, recurrence, and unresolved constraints; +no theorem/proof/status support is inferred from this procedure or its optional historical notation. ``` +When `local_notation: historical-text-stack` is selected, additionally record +the chosen text-stack scale and any `twist`/`carrier`/`layer` details required +for reconstruction. Those historical fields are not required in notation-free +compression. + ## Anti-patterns - Carrying full connective prose and calling it compression. - Dropping a named object, value, status, path, repo, URL, or decision. - Dropping `not`, `only`, `unless`, `must`, `cannot`, `before`, or `after`. - Treating a short token as safe because it is common. -- Treating a space as absence instead of a twist seam. +- Treating a meaningful separator as absence when it changes attachment. - Treating recurrence weight as enough when ordered recurrence is required. - Treating the bone channel as opaque. - Compressing an unresolved constraint into silence. @@ -484,4 +500,4 @@ no theorem/proof/status support is transferred beyond the tested UCNS domain. - whether future structure-preserving mode should carry bone fingerprints, dependency slots, twist seams, recurrence layers, or all of them - whether opacity should layer on top of this compression or replace the - inventory boundary with a secret mapping + inventory boundary with a secret mapping \ No newline at end of file From cf493a0e1149a02f9cb8a7d78c89072249a0d5d0 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:05:40 -0700 Subject: [PATCH 08/25] test(char-compress): guard notation-neutral required workflow --- tests/test_char_compress_authority.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_char_compress_authority.py b/tests/test_char_compress_authority.py index 9c7aeb5..beaaa7e 100644 --- a/tests/test_char_compress_authority.py +++ b/tests/test_char_compress_authority.py @@ -21,3 +21,13 @@ def test_preservation_guards_survive_authority_correction(self): for guard in ("Freeze dangerous bones", "Reconstruct and compare", "Carry hmmm", "lost recurrence order", "dropped negation", "changed proof/status label"): self.assertIn(guard, text) + + def test_optional_text_stack_is_not_a_required_completion_gate(self): + text = (ROOT / "char-compress/SKILL.md").read_text() + procedure = text.split("## Compression procedure", 1)[1].split("## Skill-writing use", 1)[0] + completion = text.split("## Completion criteria", 1)[1].split("## Anti-patterns", 1)[0] + self.assertIn("local_notation: none | historical-text-stack", procedure) + self.assertIn("Include\n`text_stack` only when", procedure) + self.assertNotIn("Identify first-cycle carrier vertices", procedure) + self.assertNotIn("text-stack scale is declared;", completion) + self.assertIn("not required in notation-free compression", completion) From 7f3e24662386e86b11cb41f287412a22ae5f5d6f Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:09:03 -0700 Subject: [PATCH 09/25] fix(msdmd): admit digits in snake-case field names --- msdmd/parsers/universal.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/msdmd/parsers/universal.py b/msdmd/parsers/universal.py index 204f533..e6cb88a 100644 --- a/msdmd/parsers/universal.py +++ b/msdmd/parsers/universal.py @@ -100,7 +100,7 @@ def parse_text(text: str, block_name: str, marker: str = "#") -> list[dict]: block_re = _block_regex(block_name, marker) m = re.escape(marker) id_re = re.compile(rf"^\s*{m}\s*id:\s*(?P\S+)\s*$") - field_re = re.compile(rf"^\s*{m}\s+(?P[a-z_]+):\s*(?P.+?)\s*$") + field_re = re.compile(rf"^\s*{m}\s+(?P[a-z_][a-z0-9_]*):\s*(?P.+?)\s*$") entries: list[dict] = [] for block in block_re.finditer(text): @@ -189,7 +189,7 @@ def iter_source_files(path: Path) -> Iterable[Path]: # boundary to literal line 2: # ratios: loc_comments=N:M imports_exports=N:M calls_definitions=N:M RATIO_IDS = ("loc_comments", "imports_exports", "calls_definitions") -_RATIOS_TOKEN_RE = re.compile(r"(?P[a-z_]+)=(?P\S+)") +_RATIOS_TOKEN_RE = re.compile(r"(?P[a-z_][a-z0-9_]*)=(?P\S+)") def _ratios_line_re(marker: str) -> re.Pattern[str]: @@ -253,4 +253,4 @@ def ratios_placement(text: str, marker: str = "#") -> tuple[bool, bool]: last_ok = bool(line_re.match(raw.rstrip())) break return (opening_ok, last_ok) -# ratios: loc_comments=161:57 imports_exports=4:7 calls_definitions=55:10 +# ratios: loc_comments=161:57 imports_exports=4:7 calls_definitions=55:10 \ No newline at end of file From bc04f7384fc51fcdcfaaa4070d7441ad2842f1b7 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:09:42 -0700 Subject: [PATCH 10/25] fix(msdmd): keep TypeScript field grammar in parity --- msdmd/parsers/universal.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/msdmd/parsers/universal.ts b/msdmd/parsers/universal.ts index 141f46c..6e37cb3 100644 --- a/msdmd/parsers/universal.ts +++ b/msdmd/parsers/universal.ts @@ -86,7 +86,7 @@ export function parseText( "gm", ); const idRe = new RegExp(`^\\s*${m}\\s*id:\\s*(\\S+)\\s*$`); - const fieldRe = new RegExp(`^\\s*${m}\\s+([a-z_]+):\\s*(.+?)\\s*$`); + const fieldRe = new RegExp(`^\\s*${m}\\s+([a-z_][a-z0-9_]*):\\s*(.+?)\\s*$`); const entries: Entry[] = []; let match: RegExpExecArray | null; @@ -185,7 +185,7 @@ function ratiosLineRe(marker: string): RegExp { export function parseRatios(text: string, marker: string = "#"): Entry[] { const lineRe = ratiosLineRe(marker); - const tokenRe = /([a-z_]+)=(\S+)/g; + const tokenRe = /([a-z_][a-z0-9_]*)=(\S+)/g; const out: Entry[] = []; for (const raw of text.split("\n")) { const lm = lineRe.exec(raw.replace(/\s+$/, "")); @@ -218,17 +218,15 @@ export function ratiosPlacement(text: string, marker: string = "#"): [boolean, b const openingOk = lines.length > openingIndex && lineRe.test(lines[openingIndex].replace(/\s+$/, "")); - const displacedShebang = - openingIndex === 0 && - lines.length > 1 && - lines[1].startsWith("#!") && - lines[1].slice(2).trim().length > 0; - let lastOk = false; - for (let i = lines.length - 1; i >= 0; i--) { + if (openingIndex === 0 && lines.length > 1) { + const displaced = lines[1].startsWith("#!") && lines[1].slice(2).trim().length > 0; + if (displaced) return [false, false]; + } + let closingOk = false; + for (let i = lines.length - 1; i >= 0; i -= 1) { if (lines[i].trim() === "") continue; - lastOk = lineRe.test(lines[i].replace(/\s+$/, "")); + closingOk = lineRe.test(lines[i].replace(/\s+$/, "")); break; } - return [openingOk && !displacedShebang, lastOk]; + return [openingOk, closingOk]; } -// ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm From 8b164cf4d92f5d27547747d700221faf3ec695a4 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:10:22 -0700 Subject: [PATCH 11/25] docs(msdmd): specify numeric snake-case fields --- msdmd/SKILL.md | 199 +++++++++++-------------------------------------- 1 file changed, 44 insertions(+), 155 deletions(-) diff --git a/msdmd/SKILL.md b/msdmd/SKILL.md index ffa10c4..3e1293e 100644 --- a/msdmd/SKILL.md +++ b/msdmd/SKILL.md @@ -1,36 +1,25 @@ --- name: msdmd -description: Module Self-Declared Metadata in Markdown — the foundational convention where each module declares its own structured metadata in a fenced comment block. Other skills in this lib (doc-build, cap-build, deps-build, owner-build, test-build, meta-module-build, risk-boundary-build, ratios, etc.) are thin applications on top of this convention. Load this when authoring a new metadata-driven skill, when extending the block schema, or when building a parser/executor for a new application. +description: Module Self-Declared Metadata Markdown — a language-agnostic convention where each source module declares its own structured metadata in fenced comment blocks. Load this when creating, parsing, validating, or extending msdmd block syntax; when a repo needs self-declared module metadata; when another msdmd-family skill needs parser behavior or comment-marker rules; or when checking whether a proposed metadata convention belongs in the foundational parser rather than a runner-local dialect. --- -# msdmd — Module Self-Declared Metadata in Markdown +# msdmd — Module Self-Declared Metadata Markdown -## The doctrine +msdmd is a convention for putting small, structured declarations beside the +source that owns them. The declarations are ordinary line comments, so they +remain readable in any editor and require no framework runtime. -Every cross-cutting fact a module owns — its behavior obligations, -public documentation, declared capabilities, dependency edges, owner, -runtime boundaries, or executable evidence — should live **in the same -file as the module that owns that fact**, in a structured comment -block. A meta-runner walks the tree, parses every block, and acts on -it. +The design rule is simple: -Modules without the relevant block surface as visible coverage gaps in -the runner output. Coverage is observable, not implicit. - -This is the inverse of the conventional "keep your docs/tests/configs in -sync with code" approach, which fails because the contract and the -implementation live in different files. Anyone can delete the code and -forget the doc; the lie persists. msdmd makes the lie structurally -visible: when the implementation-owning file disappears, its owned -block disappears in the same diff. +```text +owner module declares local facts -> shared parser reads them -> specialized runner interprets them +``` -For tests, ownership is split rather than flattened: source modules own -`CONTRACTS` obligations; test modules own `CHECKS` evidence that -claims to prove those obligations. See -[`test-build/SKILL.md`](../test-build/SKILL.md) and -[`doctrine/msdmd-checks.md`](../doctrine/msdmd-checks.md). +Do not fork parser syntax in a consumer. If a field shape is generally useful, +extend the canonical parser contract here and keep the Python/TypeScript +reference implementations aligned. -## Block syntax +## Canonical shape ```python # === === @@ -62,8 +51,10 @@ claims to prove those obligations. See unique within its block and stable across refactors (so it can be referenced from external tooling). - **Field lines**: indented one level beneath the id (two spaces of - visible indent inside the comment). Field names are lowercase - snake_case followed by `:` and a value. + visible indent inside the comment). Field names are lowercase snake_case + followed by `:` and a value. Digits are allowed after the first character, + so names such as `evidence_sha256` are valid; the first character must be a + lowercase letter or underscore. - **Multiple blocks per file**: a module may declare more than one block, of the same or different types. The parser concatenates entries. @@ -178,146 +169,44 @@ export default defineMsdmdCollection({ gaps: [ { file: "path/to/module.py", missing: ["CONTRACTS", "DOCS"] }, ], - edges: [ - { from: "module_a", to: "module_b", kind: "requires", source_block: "DEPENDENCIES", source_id: "..." }, - { from: "check_module_a", to: "module_a_contract", kind: "claims_proves", source_block: "CHECKS", source_id: "..." }, - ], }); - -export const declarations = []; -export const gaps = []; ``` -A repo-level msdmd visualizer SHOULD read `_msdmd.ts` and render -relationships between modules using the `MsdmdEdge` shape: -`DEPENDENCIES.requires`, `CAPABILITIES.exposes`, `OWNERS.owner`, -`BOUNDARIES` risk fields, `DOCS.covers`, `CHECKS.call`, -`CHECKS.proves` as `claims_proves`, and any `requires` edges shared -across application skills. The visualizer is a consumer of the -collection point, not a second metadata source. +The collection point is an index, not a second authority. Module-local blocks +remain authoritative for their own declarations. -If a repo has no collection point or visualizer yet, record that as `hmmm` in -repo-local planning rather than pretending the graph exists. - -A small stdlib generator prototype lives at `msdmd/collect.py`. Consuming repos -can run it directly or copy it as a starting point: - -```bash -python -m msdmd.collect --root . --repo --out _msdmd.ts -``` +## Usage guidance -The generator is intentionally conservative: it parses module-local blocks, -emits declarations, optional expected-block gaps, and simple relationship -edges from reserved fields. Repo-specific runners may enrich the output, but -should preserve the `MsdmdCollection` shape. +Use the parser directly when a runner needs multiple block families without +inventing syntax: -A minimal Mermaid visualizer prototype lives at `msdmd/visualize.py` and reads -raw JSON or generated TypeScript collection points: +```python +from msdmd.parsers.universal import parse_file -```bash -python -m msdmd.visualize _msdmd.ts --out _msdmd.mmd +contracts = parse_file(path, "CONTRACTS") +docs = parse_file(path, "DOCS") ``` -The visualizer is deliberately small: it renders declaration nodes, normalized -edge relationships, and visible gap nodes. Rich repo-specific UIs should consume -the same collection shape rather than re-parsing source files. - +To add a new metadata skill: -## The runner protocol +1. define its block name and field semantics in that skill; +2. keep the universal parser generic; +3. write the runner against the shared parser output; +4. surface unannotated modules as visible gaps instead of pretending coverage; +5. propose a canonical parser extension here before accepting any syntax the + shared parser cannot represent. -A msdmd runner combines a parser and an executor: - -``` -walk(root: Path, block_name: str) -> Iterator[(file: Path, entries: list[Entry])] -``` +## Anti-patterns -Implementation rules every runner MUST follow: - -1. **Walk the source tree** under a configurable root, skipping - conventional non-source paths (`__pycache__`, `node_modules`, - `.git`, build outputs, the runner's own test directory). -2. **Detect comment marker by extension**, not by content sniffing. Consume the - parser's `COMMENT_MARKERS` registry rather than maintaining a runner-local - language list. Python and TypeScript registries must remain identical. -3. **Parse all matching blocks** in each file. Multiple blocks of the - same type concatenate; entries from different blocks are - distinguishable only by id, not by source block. -4. **Visit modules without any block of the requested type** and emit - them as a separate "untested" / "undocumented" / "uncapable" gap - list. Truncate noise (e.g. show first 20, count the rest), but - never silently drop. Visibility is the whole point. -5. **Exit non-zero** when any entry fails the executor's check. The - gap list itself is informational unless the application opts in to - strict mode (in which case missing blocks are also a fail). - -## Field naming conventions - -Reserved field names and their canonical meanings (for cross-skill -consistency): - -| Field | Meaning | -|---|---| -| `id` | Unique stable identifier within the block. Required on every entry. | -| `class` | Free-text tag for grouping (`security`, `correctness`, `idempotency`, etc.). The runner counts entries per class in summaries. | -| `call` | Executable target owned by an evidence/check declaration. Source `CONTRACTS` do not use this field for test topology. | -| `proves` | Comma-separated ids this evidence/check entry claims to prove. The collection edge kind is `claims_proves`; mutation sensitivity is a higher verification rung. | -| `summary` | One-sentence human description. | -| `requires` | Comma-separated dependency ids or host capabilities. Exact semantics are application-specific and must be documented by the skill that consumes it. | -| `owner` | Who is responsible (person, agent role, team). | -| `since` | Version or date this declaration was added. | -| `deprecated` | If present, marks the entry as scheduled for removal. | - -Application-specific fields (`given`, `then`, `expects`, `inputs`, -`outputs`, `mutates`, `cleanup`, `timeout`, etc.) are introduced by -individual SKILLs and documented in their own SKILL.md. - -## Authoring a new msdmd application - -1. **Pick a block name** that doesn't collide with an existing - application. Search the lib README for current names. -2. **Define the field schema** — which fields are required, which - optional, what types they carry. Document in your SKILL.md. -3. **Write the executor** — the function that takes parsed entries - and acts on them. Use the universal parser; do not write a new - one unless your block needs syntax the universal parser can't - express. -4. **Implement the visibility report** — your runner must list - modules without your block type as gaps, and the gap list must - be visible in normal output (not buried behind a flag). -5. **Author a SKILL.md** in this lib with the convention spec, the - executor's behavior, and at least one worked example. - -`test-build/` is the canonical reference application for paired source -`CONTRACTS` and test `CHECKS`. Read its SKILL.md alongside this one to -see the pattern fully realized; read `doc-build/`, `cap-build/`, -`deps-build/`, `owner-build/`, `risk-boundary-build/`, and `ratios/` -for additional applications over the same parser contract. +- Creating a runner-local parser dialect. +- Treating absence of a block as evidence that the module has no obligation. +- Inferring a comment marker from content when the extension is ambiguous. +- Adding block-specific semantic validation to the universal parser. +- Hiding parse or coverage gaps to make a report look complete. -## Anti-patterns +## hmmm -- **Don't define an owned declaration in a detached side file.** The - whole point is that the declaration lives next to the module that - owns that fact. Source obligations belong in source; test evidence - belongs in the test module that owns the evidence. -- **Don't put `call:` in source `CONTRACTS`.** Source modules own - obligations, not test topology. Put executable targets in `CHECKS`. -- **Don't make ids reflect implementation details.** `chat_returns_200` - tells future-you nothing; `chat_get_other_owner_404` tells you what's - protected. Ids are part of the documentation. -- **Don't silently drop modules without blocks.** Coverage gaps must be - visible. If your runner doesn't emit the gap list, it's not a msdmd - runner; it's a test discovery tool with extra steps. -- **Don't introduce parser dialects.** If you need richer syntax than - the universal parser handles, propose an extension to msdmd, not a - fork. The portability of the convention depends on the parser - contract being one thing. - -## Versioning - -- **Block syntax is stable.** Breaking changes (renaming the fence, - changing field-line indentation rules, etc.) go through a major - version bump and a migration note in the lib README. -- **Reserved field names** above are stable. New reserved names are - additive only. -- **Application SKILLs** version independently in their own SKILL.md - files. +- block schema/version negotiation across independently evolving consumers +- a canonical escape/multiline-value syntax beyond the current flat line form +- whether ids should receive a stricter lexical grammar than the current + non-whitespace stable-identity rule \ No newline at end of file From f36454b6d3320afdda83d8ae776992886152a291 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:11:02 -0700 Subject: [PATCH 12/25] test(msdmd): cover numeric snake-case fields --- tests/test_universal_parser.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/test_universal_parser.py b/tests/test_universal_parser.py index ca30ed8..9cf62bd 100644 --- a/tests/test_universal_parser.py +++ b/tests/test_universal_parser.py @@ -57,6 +57,17 @@ def test_parse_all_matching_blocks_not_just_first(self) -> None: parse_text(text, "DOCS"), ) + def test_parse_numeric_snake_case_field(self) -> None: + text = """# === NARRATIVE === +# id: source_bound_narrative +# evidence_sha256: abc123 +# === END NARRATIVE === +""" + self.assertEqual( + [{"id": "source_bound_narrative", "evidence_sha256": "abc123"}], + parse_text(text, "NARRATIVE"), + ) + def test_parse_typescript_comment_marker(self) -> None: text = """// === CAPABILITIES === // id: browser_opens_page @@ -237,4 +248,4 @@ def test_parse_ratios_detects_misplacement(self) -> None: if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file From a450a9c72192ee5ba1c88900b8fdedfe22fe6c84 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:11:21 -0700 Subject: [PATCH 13/25] refactor(gonol-build): keep EDCM witness out of propagated skill --- tools/check_edcm_boundary.py | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 tools/check_edcm_boundary.py diff --git a/tools/check_edcm_boundary.py b/tools/check_edcm_boundary.py new file mode 100644 index 0000000..fcb9330 --- /dev/null +++ b/tools/check_edcm_boundary.py @@ -0,0 +1,66 @@ +# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=16:1 +"""Executable cross-source scale witness; not a geometry or measurement proof. + +Usage: python tools/check_edcm_boundary.py /exact/edcm/checkout +The supplied clean checkout must match EDCM_COMMIT. No package install or network +access is performed by this witness. Refreshing the pin is a reviewed boundary change. +""" + +# === MODULE_BUILD === +# id: gonol_edcm_scale_witness +# module_name: check_edcm_boundary +# module_kind: adapter +# summary: Exercise an exact EDCM constructor's non-adjacent scale and replay contract. +# owner: skill-lib maintainers +# public_surface: check +# internal_surface: none +# auth_boundary: none +# storage_boundary: none +# network_boundary: none +# user_data_boundary: none +# admin_only: false +# tests: explicit CLI against the declared EDCM commit +# rollout: cross-source CI gate +# rollback: retain pin and report boundary as hmmm if unavailable +# === END MODULE_BUILD === + +from pathlib import Path +import subprocess +import sys + +EDCM_COMMIT = "ddc89a97ebbcf0a5863dad6e633b01b520e9bccf" + + +def check(root: Path) -> None: + actual = subprocess.check_output(["git", "-C", str(root), "rev-parse", "HEAD"], text=True).strip() + if actual != EDCM_COMMIT: + raise ValueError(f"expected exact EDCM {EDCM_COMMIT}, got {actual}") + if subprocess.check_output(["git", "-C", str(root), "status", "--porcelain"]): + raise ValueError("EDCM witness requires a clean source checkout") + sys.path.insert(0, str(root.resolve())) + from edcm.gonol import construct_gonol, replay_gonol, GonolConstructionError + + character = construct_gonol(scale="character", source="x", source_id="skill-lib:character") + definition = construct_gonol(scale="definition", source="bounded evidence", + relation="skill-lib:defined-by", participants=(character.gonol,), + source_id="skill-lib:definition") + if definition.gonol.participants != (character.gonol,): + raise AssertionError("definition participants changed") + if replay_gonol(receipt=definition).receipt_digest != definition.receipt_digest: + raise AssertionError("replay digest changed") + if definition.standing != "implemented-candidate": + raise AssertionError("candidate standing changed") + if definition.selection_effect != "none": + raise AssertionError("selection effect transferred") + try: + construct_gonol(scale="undeclared-scale", source="x", source_id="skill-lib:invalid") + except GonolConstructionError: + pass + else: + raise AssertionError("undeclared scale must not become eligible") + print(f"PASS EDCM {actual}: direct character-to-definition, replay, candidate non-transfer, rejected undeclared scale") + + +if __name__ == "__main__": + check(Path(sys.argv[1])) +# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=16:1 \ No newline at end of file From 03c95ae67b8407eadc76402586f8d4bc2c0fa262 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:11:34 -0700 Subject: [PATCH 14/25] refactor(gonol-build): stop propagating EDCM executable into UCNS --- gonol-build/check_edcm_boundary.py | 62 ------------------------------ 1 file changed, 62 deletions(-) delete mode 100644 gonol-build/check_edcm_boundary.py diff --git a/gonol-build/check_edcm_boundary.py b/gonol-build/check_edcm_boundary.py deleted file mode 100644 index 3a30564..0000000 --- a/gonol-build/check_edcm_boundary.py +++ /dev/null @@ -1,62 +0,0 @@ -# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=16:1 -"""Executable cross-source scale witness; not a geometry or measurement proof. - -Usage: python gonol-build/check_edcm_boundary.py /exact/edcm/checkout -The supplied clean checkout must match EDCM_COMMIT. No package install or network -access is performed by this witness. Refreshing the pin is a reviewed boundary change. -""" - -# === MODULE_BUILD === -# id: gonol_edcm_scale_witness -# module_name: check_edcm_boundary -# module_kind: adapter -# summary: Exercise an exact EDCM constructor's non-adjacent scale and replay contract. -# owner: skill-lib maintainers -# public_surface: check -# internal_surface: none -# auth_boundary: none -# storage_boundary: none -# network_boundary: none -# user_data_boundary: none -# admin_only: false -# tests: explicit CLI against the declared EDCM commit -# rollout: cross-source CI gate -# rollback: retain pin and report boundary as hmmm if unavailable -# === END MODULE_BUILD === - -from pathlib import Path -import subprocess -import sys - -EDCM_COMMIT = "ddc89a97ebbcf0a5863dad6e633b01b520e9bccf" - - -def check(root: Path) -> None: - actual = subprocess.check_output(["git", "-C", str(root), "rev-parse", "HEAD"], text=True).strip() - if actual != EDCM_COMMIT: - raise ValueError(f"expected exact EDCM {EDCM_COMMIT}, got {actual}") - if subprocess.check_output(["git", "-C", str(root), "status", "--porcelain"]): - raise ValueError("EDCM witness requires a clean source checkout") - sys.path.insert(0, str(root.resolve())) - from edcm.gonol import construct_gonol, replay_gonol, GonolConstructionError - - character = construct_gonol(scale="character", source="x", source_id="skill-lib:character") - definition = construct_gonol(scale="definition", source="bounded evidence", - relation="skill-lib:defined-by", participants=(character.gonol,), - source_id="skill-lib:definition") - if definition.gonol.participants != (character.gonol,): raise AssertionError("definition participants changed") - if replay_gonol(receipt=definition).receipt_digest != definition.receipt_digest: raise AssertionError("replay digest changed") - if definition.standing != "implemented-candidate": raise AssertionError("candidate standing changed") - if definition.selection_effect != "none": raise AssertionError("selection effect transferred") - try: - construct_gonol(scale="undeclared-scale", source="x", source_id="skill-lib:invalid") - except GonolConstructionError: - pass - else: - raise AssertionError("undeclared scale must not become eligible") - print(f"PASS EDCM {actual}: direct character-to-definition, replay, candidate non-transfer, rejected undeclared scale") - - -if __name__ == "__main__": - check(Path(sys.argv[1])) -# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=16:1 \ No newline at end of file From 676f5d676b82eca0f9c92eb951f466ff790cfd09 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:11:44 -0700 Subject: [PATCH 15/25] ci: run cross-source witness from owning tools boundary --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02e1743..de4d41b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: git -C "$EDCM_CHECKOUT" init git -C "$EDCM_CHECKOUT" fetch --depth 1 https://github.com/The-Interdependency/edcm.git ddc89a97ebbcf0a5863dad6e633b01b520e9bccf git -C "$EDCM_CHECKOUT" checkout --detach FETCH_HEAD - python gonol-build/check_edcm_boundary.py "$EDCM_CHECKOUT" + python tools/check_edcm_boundary.py "$EDCM_CHECKOUT" - name: Skill library drift run: python tools/check_skill_lib_drift.py --warnings-fail - name: Skill compliance @@ -38,4 +38,4 @@ jobs: - name: RepoLOTO audit run: python tests/test_repo_loto.py --audit - name: RepoLOTO checks - run: python tests/test_repo_loto.py + run: python tests/test_repo_loto.py \ No newline at end of file From 50481031de7de0408663f3ce87d36a8fec6cb50d Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:12:10 -0700 Subject: [PATCH 16/25] docs(gonol-build): keep executable witness at skill-lib tools boundary --- gonol-build/SKILL.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/gonol-build/SKILL.md b/gonol-build/SKILL.md index 0654cc7..6e0e97d 100644 --- a/gonol-build/SKILL.md +++ b/gonol-build/SKILL.md @@ -90,16 +90,19 @@ Replay establishes reproducibility of that construction only. It does not by its ## Usage guidance -The executable cross-source witness is `gonol-build/check_edcm_boundary.py`. -Run it against a clean EDCM checkout at the script's exact `EDCM_COMMIT`: +The executable cross-source witness is owned by skill-lib at +`tools/check_edcm_boundary.py`, outside the propagated skill directory. In a +skill-lib checkout, run it against a clean EDCM checkout at the script's exact +`EDCM_COMMIT`: ```bash -python gonol-build/check_edcm_boundary.py /path/to/edcm +python tools/check_edcm_boundary.py /path/to/edcm ``` It checks direct character-to-definition construction, replay, candidate standing, -and refusal of an undeclared scale. This pinned witness is not a universal scale -registry; current construction must still resolve its owning EDCM option set. +and refusal of an undeclared scale. It is deliberately not vendored into UCNS or +other geometry consumers. This pinned witness is not a universal scale registry; +current construction must still resolve its owning EDCM option set. For text construction, start in EDCM and consume current UCNS geometry. @@ -113,9 +116,10 @@ When a gonol closes, use it atomically at any admissible consuming scale. Ignore ## Anti-patterns - Moving text semantics into UCNS or inventing geometry in EDCM. +- Vendoring the EDCM executable witness into a UCNS geometry repository. - Imposing an adjacent-scale ladder or inventing an eligible scale option without EDCM authority. - Letting pronunciation alter gonol identity, closure, ordering, or relations unless a later explicitly declared experiment makes phonology part of its construction. -- Normalizing, deduplicating, inferring relations, or substituting tokens, embeddings, or hashes for gonol identity unless the active contract explicitly authorizes it. +- Normalizing, deduplicating, inferring relations, or substituting tokens, embeddings, hashes for gonol identity unless the active contract explicitly authorizes it. - Adding arbitrary wall-clock limits to a healthy admitted run. - Treating replay as semantic quality, measurement validity, cognition, or extra-scope canon. @@ -123,4 +127,4 @@ When a gonol closes, use it atomically at any admissible consuming scale. Ignore - exact UCNS geometric operations that remain unresolved in current implementation; - any future construction that explicitly adds phonology or another stage; -- any recursive relation whose governing source or geometry is not yet established. +- any recursive relation whose governing source or geometry is not yet established. \ No newline at end of file From 67f05c105656d92ad1ef691583c33d5c530d313a Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:12:50 -0700 Subject: [PATCH 17/25] chore(ratios): refresh EDCM witness seal --- tools/check_edcm_boundary.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/check_edcm_boundary.py b/tools/check_edcm_boundary.py index fcb9330..a9948ae 100644 --- a/tools/check_edcm_boundary.py +++ b/tools/check_edcm_boundary.py @@ -1,4 +1,4 @@ -# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=16:1 +# ratios: loc_comments=33:22 imports_exports=4:1 calls_definitions=16:1 """Executable cross-source scale witness; not a geometry or measurement proof. Usage: python tools/check_edcm_boundary.py /exact/edcm/checkout @@ -63,4 +63,4 @@ def check(root: Path) -> None: if __name__ == "__main__": check(Path(sys.argv[1])) -# ratios: loc_comments=29:22 imports_exports=4:1 calls_definitions=16:1 \ No newline at end of file +# ratios: loc_comments=33:22 imports_exports=4:1 calls_definitions=16:1 \ No newline at end of file From 593332fea56c6122972d7640f79606464d9f0cdf Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:13:17 -0700 Subject: [PATCH 18/25] test(gonol-build): enforce cross-source witness placement --- tests/test_gonol_build_skill.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/test_gonol_build_skill.py b/tests/test_gonol_build_skill.py index 5110031..d8d4460 100644 --- a/tests/test_gonol_build_skill.py +++ b/tests/test_gonol_build_skill.py @@ -9,6 +9,7 @@ ROOT = Path(__file__).resolve().parents[1] SKILL = ROOT / "gonol-build" / "SKILL.md" ADAPTER = ROOT / "skills" / "gonol-build" / "SKILL.md" +WITNESS = ROOT / "tools" / "check_edcm_boundary.py" class GonolBuildSkillTest(unittest.TestCase): @@ -45,6 +46,12 @@ def test_scale_options_are_owned_by_edcm(self) -> None: self.assertIn("character-to-definition construction must not be rejected", self.compact) self.assertNotIn("This order is load-bearing", self.compact) + def test_cross_source_witness_stays_out_of_propagated_skill(self) -> None: + self.assertTrue(WITNESS.is_file()) + self.assertFalse((ROOT / "gonol-build" / "check_edcm_boundary.py").exists()) + self.assertIn("`tools/check_edcm_boundary.py`", self.text) + self.assertIn("deliberately not vendored into UCNS", self.compact) + def test_closed_words_promote_atomically(self) -> None: for phrase in ( "Any closed gonol is atomic at an admissible consuming scale", @@ -142,4 +149,4 @@ def test_codex_adapter_points_to_canonical_skill(self) -> None: if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file From e6efae7000753ebfceb8ae4bde45e89c1ef06921 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:14:54 -0700 Subject: [PATCH 19/25] fix(msdmd): preserve foundation spec while extending field grammar --- msdmd/SKILL.md | 199 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 156 insertions(+), 43 deletions(-) diff --git a/msdmd/SKILL.md b/msdmd/SKILL.md index 3e1293e..1a6f0be 100644 --- a/msdmd/SKILL.md +++ b/msdmd/SKILL.md @@ -1,25 +1,36 @@ --- name: msdmd -description: Module Self-Declared Metadata Markdown — a language-agnostic convention where each source module declares its own structured metadata in fenced comment blocks. Load this when creating, parsing, validating, or extending msdmd block syntax; when a repo needs self-declared module metadata; when another msdmd-family skill needs parser behavior or comment-marker rules; or when checking whether a proposed metadata convention belongs in the foundational parser rather than a runner-local dialect. +description: Module Self-Declared Metadata in Markdown — the foundational convention where each module declares its own structured metadata in a fenced comment block. Other skills in this lib (doc-build, cap-build, deps-build, owner-build, test-build, meta-module-build, risk-boundary-build, ratios, etc.) are thin applications on top of this convention. Load this when authoring a new metadata-driven skill, when extending the block schema, or when building a parser/executor for a new application. --- -# msdmd — Module Self-Declared Metadata Markdown +# msdmd — Module Self-Declared Metadata in Markdown -msdmd is a convention for putting small, structured declarations beside the -source that owns them. The declarations are ordinary line comments, so they -remain readable in any editor and require no framework runtime. +## The doctrine -The design rule is simple: +Every cross-cutting fact a module owns — its behavior obligations, +public documentation, declared capabilities, dependency edges, owner, +runtime boundaries, or executable evidence — should live **in the same +file as the module that owns that fact**, in a structured comment +block. A meta-runner walks the tree, parses every block, and acts on +it. -```text -owner module declares local facts -> shared parser reads them -> specialized runner interprets them -``` +Modules without the relevant block surface as visible coverage gaps in +the runner output. Coverage is observable, not implicit. + +This is the inverse of the conventional "keep your docs/tests/configs in +sync with code" approach, which fails because the contract and the +implementation live in different files. Anyone can delete the code and +forget the doc; the lie persists. msdmd makes the lie structurally +visible: when the implementation-owning file disappears, its owned +block disappears in the same diff. -Do not fork parser syntax in a consumer. If a field shape is generally useful, -extend the canonical parser contract here and keep the Python/TypeScript -reference implementations aligned. +For tests, ownership is split rather than flattened: source modules own +`CONTRACTS` obligations; test modules own `CHECKS` evidence that +claims to prove those obligations. See +[`test-build/SKILL.md`](../test-build/SKILL.md) and +[`doctrine/msdmd-checks.md`](../doctrine/msdmd-checks.md). -## Canonical shape +## Block syntax ```python # === === @@ -51,9 +62,9 @@ reference implementations aligned. unique within its block and stable across refactors (so it can be referenced from external tooling). - **Field lines**: indented one level beneath the id (two spaces of - visible indent inside the comment). Field names are lowercase snake_case - followed by `:` and a value. Digits are allowed after the first character, - so names such as `evidence_sha256` are valid; the first character must be a + visible indent inside the comment). Field names are lowercase + snake_case followed by `:` and a value. Digits are allowed after the first + character, so `evidence_sha256` is valid; the first character must be a lowercase letter or underscore. - **Multiple blocks per file**: a module may declare more than one block, of the same or different types. The parser concatenates @@ -169,44 +180,146 @@ export default defineMsdmdCollection({ gaps: [ { file: "path/to/module.py", missing: ["CONTRACTS", "DOCS"] }, ], + edges: [ + { from: "module_a", to: "module_b", kind: "requires", source_block: "DEPENDENCIES", source_id: "..." }, + { from: "check_module_a", to: "module_a_contract", kind: "claims_proves", source_block: "CHECKS", source_id: "..." }, + ], }); + +export const declarations = []; +export const gaps = []; ``` -The collection point is an index, not a second authority. Module-local blocks -remain authoritative for their own declarations. +A repo-level msdmd visualizer SHOULD read `_msdmd.ts` and render +relationships between modules using the `MsdmdEdge` shape: +`DEPENDENCIES.requires`, `CAPABILITIES.exposes`, `OWNERS.owner`, +`BOUNDARIES` risk fields, `DOCS.covers`, `CHECKS.call`, +`CHECKS.proves` as `claims_proves`, and any `requires` edges shared +across application skills. The visualizer is a consumer of the +collection point, not a second metadata source. -## Usage guidance +If a repo has no collection point or visualizer yet, record that as `hmmm` in +repo-local planning rather than pretending the graph exists. -Use the parser directly when a runner needs multiple block families without -inventing syntax: +A small stdlib generator prototype lives at `msdmd/collect.py`. Consuming repos +can run it directly or copy it as a starting point: -```python -from msdmd.parsers.universal import parse_file +```bash +python -m msdmd.collect --root . --repo --out _msdmd.ts +``` + +The generator is intentionally conservative: it parses module-local blocks, +emits declarations, optional expected-block gaps, and simple relationship +edges from reserved fields. Repo-specific runners may enrich the output, but +should preserve the `MsdmdCollection` shape. -contracts = parse_file(path, "CONTRACTS") -docs = parse_file(path, "DOCS") +A minimal Mermaid visualizer prototype lives at `msdmd/visualize.py` and reads +raw JSON or generated TypeScript collection points: + +```bash +python -m msdmd.visualize _msdmd.ts --out _msdmd.mmd ``` -To add a new metadata skill: +The visualizer is deliberately small: it renders declaration nodes, normalized +edge relationships, and visible gap nodes. Rich repo-specific UIs should consume +the same collection shape rather than re-parsing source files. -1. define its block name and field semantics in that skill; -2. keep the universal parser generic; -3. write the runner against the shared parser output; -4. surface unannotated modules as visible gaps instead of pretending coverage; -5. propose a canonical parser extension here before accepting any syntax the - shared parser cannot represent. -## Anti-patterns +## The runner protocol -- Creating a runner-local parser dialect. -- Treating absence of a block as evidence that the module has no obligation. -- Inferring a comment marker from content when the extension is ambiguous. -- Adding block-specific semantic validation to the universal parser. -- Hiding parse or coverage gaps to make a report look complete. +A msdmd runner combines a parser and an executor: -## hmmm +``` +walk(root: Path, block_name: str) -> Iterator[(file: Path, entries: list[Entry])] +``` + +Implementation rules every runner MUST follow: + +1. **Walk the source tree** under a configurable root, skipping + conventional non-source paths (`__pycache__`, `node_modules`, + `.git`, build outputs, the runner's own test directory). +2. **Detect comment marker by extension**, not by content sniffing. Consume the + parser's `COMMENT_MARKERS` registry rather than maintaining a runner-local + language list. Python and TypeScript registries must remain identical. +3. **Parse all matching blocks** in each file. Multiple blocks of the + same type concatenate; entries from different blocks are + distinguishable only by id, not by source block. +4. **Visit modules without any block of the requested type** and emit + them as a separate "untested" / "undocumented" / "uncapable" gap + list. Truncate noise (e.g. show first 20, count the rest), but + never silently drop. Visibility is the whole point. +5. **Exit non-zero** when any entry fails the executor's check. The + gap list itself is informational unless the application opts in to + strict mode (in which case missing blocks are also a fail). + +## Field naming conventions + +Reserved field names and their canonical meanings (for cross-skill +consistency): + +| Field | Meaning | +|---|---| +| `id` | Unique stable identifier within the block. Required on every entry. | +| `class` | Free-text tag for grouping (`security`, `correctness`, `idempotency`, etc.). The runner counts entries per class in summaries. | +| `call` | Executable target owned by an evidence/check declaration. Source `CONTRACTS` do not use this field for test topology. | +| `proves` | Comma-separated ids this evidence/check entry claims to prove. The collection edge kind is `claims_proves`; mutation sensitivity is a higher verification rung. | +| `summary` | One-sentence human description. | +| `requires` | Comma-separated dependency ids or host capabilities. Exact semantics are application-specific and must be documented by the skill that consumes it. | +| `owner` | Who is responsible (person, agent role, team). | +| `since` | Version or date this declaration was added. | +| `deprecated` | If present, marks the entry as scheduled for removal. | + +Application-specific fields (`given`, `then`, `expects`, `inputs`, +`outputs`, `mutates`, `cleanup`, `timeout`, etc.) are introduced by +individual SKILLs and documented in their own SKILL.md. + +## Authoring a new msdmd application + +1. **Pick a block name** that doesn't collide with an existing + application. Search the lib README for current names. +2. **Define the field schema** — which fields are required, which + optional, what types they carry. Document in your SKILL.md. +3. **Write the executor** — the function that takes parsed entries + and acts on them. Use the universal parser; do not write a new + one unless your block needs syntax the universal parser can't + express. +4. **Implement the visibility report** — your runner must list + modules without your block type as gaps, and the gap list must + be visible in normal output (not buried behind a flag). +5. **Author a SKILL.md** in this lib with the convention spec, the + executor's behavior, and at least one worked example. + +`test-build/` is the canonical reference application for paired source +`CONTRACTS` and test `CHECKS`. Read its SKILL.md alongside this one to +see the pattern fully realized; read `doc-build/`, `cap-build/`, +`deps-build/`, `owner-build/`, `risk-boundary-build/`, and `ratios/` +for additional applications over the same parser contract. + +## Anti-patterns -- block schema/version negotiation across independently evolving consumers -- a canonical escape/multiline-value syntax beyond the current flat line form -- whether ids should receive a stricter lexical grammar than the current - non-whitespace stable-identity rule \ No newline at end of file +- **Don't define an owned declaration in a detached side file.** The + whole point is that the declaration lives next to the module that + owns that fact. Source obligations belong in source; test evidence + belongs in the test module that owns the evidence. +- **Don't put `call:` in source `CONTRACTS`.** Source modules own + obligations, not test topology. Put executable targets in `CHECKS`. +- **Don't make ids reflect implementation details.** `chat_returns_200` + tells future-you nothing; `chat_get_other_owner_404` tells you what's + protected. Ids are part of the documentation. +- **Don't silently drop modules without blocks.** Coverage gaps must be + visible. If your runner doesn't emit the gap list, it's not a msdmd + runner; it's a test discovery tool with extra steps. +- **Don't introduce parser dialects.** If you need richer syntax than + the universal parser handles, propose an extension to msdmd, not a + fork. The portability of the convention depends on the parser + contract being one thing. + +## Versioning + +- **Block syntax is stable.** Breaking changes (renaming the fence, + changing field-line indentation rules, etc.) go through a major + version bump and a migration note in the lib README. +- **Reserved field names** above are stable. New reserved names are + additive only. +- **Application SKILLs** version independently in their own SKILL.md + files. From 8803596fc0b42eac56dbfdda662aa4dd789615b3 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:15:41 -0700 Subject: [PATCH 20/25] fix(msdmd): restore TypeScript parser bookend and numeric fields --- msdmd/parsers/universal.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/msdmd/parsers/universal.ts b/msdmd/parsers/universal.ts index 6e37cb3..67b7b21 100644 --- a/msdmd/parsers/universal.ts +++ b/msdmd/parsers/universal.ts @@ -218,15 +218,17 @@ export function ratiosPlacement(text: string, marker: string = "#"): [boolean, b const openingOk = lines.length > openingIndex && lineRe.test(lines[openingIndex].replace(/\s+$/, "")); - if (openingIndex === 0 && lines.length > 1) { - const displaced = lines[1].startsWith("#!") && lines[1].slice(2).trim().length > 0; - if (displaced) return [false, false]; - } - let closingOk = false; - for (let i = lines.length - 1; i >= 0; i -= 1) { + const displacedShebang = + openingIndex === 0 && + lines.length > 1 && + lines[1].startsWith("#!") && + lines[1].slice(2).trim().length > 0; + let lastOk = false; + for (let i = lines.length - 1; i >= 0; i--) { if (lines[i].trim() === "") continue; - closingOk = lineRe.test(lines[i].replace(/\s+$/, "")); + lastOk = lineRe.test(lines[i].replace(/\s+$/, "")); break; } - return [openingOk, closingOk]; + return [openingOk && !displacedShebang, lastOk]; } +// ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm From af79278e873ce81a0f4b43a8606fc764079aae7b Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:16:05 -0700 Subject: [PATCH 21/25] test(char-compress): ignore prose line wrapping --- tests/test_char_compress_authority.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_char_compress_authority.py b/tests/test_char_compress_authority.py index beaaa7e..6bda9c1 100644 --- a/tests/test_char_compress_authority.py +++ b/tests/test_char_compress_authority.py @@ -30,4 +30,4 @@ def test_optional_text_stack_is_not_a_required_completion_gate(self): self.assertIn("Include\n`text_stack` only when", procedure) self.assertNotIn("Identify first-cycle carrier vertices", procedure) self.assertNotIn("text-stack scale is declared;", completion) - self.assertIn("not required in notation-free compression", completion) + self.assertIn("not required in notation-free compression", " ".join(completion.split())) From 92f4342b7f1f1ff42c3188691350eb92957c026b Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:17:49 -0700 Subject: [PATCH 22/25] chore(llms): match generated output exactly --- llms.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llms.txt b/llms.txt index 00f21a7..64a5c94 100644 --- a/llms.txt +++ b/llms.txt @@ -22,4 +22,4 @@ It provides msdmd-based metadata skills, procedural skills, pure-stdlib helper t - Write unresolved or missing values as hmmm. - Edit source LLMS blocks before regenerating llms.txt. -This file is the single source of truth. If something is not explicitly stated in the files listed above, it does not exist in this repository. \ No newline at end of file +This file is the single source of truth. If something is not explicitly stated in the files listed above, it does not exist in this repository. From 33fac587d52dbf4fb772f12ecb31601ad62ee74c Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:29:43 -0700 Subject: [PATCH 23/25] fix: preserve unknown per-skill provenance --- tools/propagate_skills.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/propagate_skills.py b/tools/propagate_skills.py index 9398e4f..0451ab3 100644 --- a/tools/propagate_skills.py +++ b/tools/propagate_skills.py @@ -1,4 +1,4 @@ -# ratios: loc_comments=193:14 imports_exports=9:11 calls_definitions=96:11 +# ratios: loc_comments=197:14 imports_exports=9:11 calls_definitions=96:11 """Synchronize canonical skill-lib skills into a target repo working tree. This script is intentionally local-file based. It does not push, commit, open @@ -74,7 +74,7 @@ def previous_skill_source_sha(target_install_root: Path, skill_name: str) -> str text = readme.read_text(encoding="utf-8") for name, sha in SKILL_SOURCE_RE.findall(text): if name == skill_name: - return None if sha == "hmmm" else sha + return sha return None @@ -228,7 +228,11 @@ def main(argv: Sequence[str] | None = None) -> int: shutil.rmtree(dst) removed_files: List[tuple[str, Path]] = [] for src, dst in actions: - skill_prior_sha = previous_skill_source_sha(install_root, src.name) or prior_sha + skill_prior_sha = previous_skill_source_sha(install_root, src.name) + if skill_prior_sha is None: + skill_prior_sha = prior_sha + elif skill_prior_sha == "hmmm": + skill_prior_sha = None removed_files.extend((src.name, path) for path in sync_tree(src, dst, skill_prior_sha)) for src, dst in doc_actions: dst.parent.mkdir(parents=True, exist_ok=True) @@ -242,4 +246,4 @@ def main(argv: Sequence[str] | None = None) -> int: if __name__ == "__main__": raise SystemExit(main()) -# ratios: loc_comments=193:14 imports_exports=9:11 calls_definitions=96:11 \ No newline at end of file +# ratios: loc_comments=197:14 imports_exports=9:11 calls_definitions=96:11 \ No newline at end of file From 65adabd29d0d2f18079166c41639d972bf12584e Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:30:15 -0700 Subject: [PATCH 24/25] test: keep unknown skill source fail-closed --- tests/test_propagate_skills.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_propagate_skills.py b/tests/test_propagate_skills.py index 87bdf79..7e2e212 100644 --- a/tests/test_propagate_skills.py +++ b/tests/test_propagate_skills.py @@ -55,6 +55,26 @@ def test_partial_refresh_uses_annotated_skill_prior_source(self) -> None: self.assertEqual(ps.main([str(target), "--skills", "test-build", "--apply"]), 0) self.assertEqual(sync.call_args.args[2], "aaaaaaa") + def test_partial_refresh_preserves_explicitly_unknown_skill_source(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + target = Path(tmp) + root = target / ".agents/skills" + skill = root / "test-build" / "SKILL.md" + skill.parent.mkdir(parents=True) + skill.write_text("unknown-origin copy\n", encoding="utf-8") + (root / "README.md").write_text( + "# Local agent skills\n\n" + "Source commit: `bbbbbbb`\n\n" + "Other installed skills (not refreshed by this propagation):\n\n" + "- `test-build/` [not refreshed; prior source: `hmmm`]\n", + encoding="utf-8", + ) + with patch.object(ps, "current_sha", return_value="ccccccc"), patch.object( + ps, "sync_tree", return_value=[] + ) as sync: + self.assertEqual(ps.main([str(target), "--skills", "test-build", "--apply"]), 0) + self.assertIsNone(sync.call_args.args[2]) + def test_referenced_doctrine_helper_finds_link(self) -> None: # canonical msdmd/SKILL.md links to ../doctrine/msdmd-checks.md refs = ps.referenced_doctrine([ROOT / "msdmd"]) From 0273d3f2a143cec8a2f9874bb46e97aa359d5318 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Fri, 11 Sep 2026 05:30:48 -0700 Subject: [PATCH 25/25] fix: point collection witness to tools module --- skill-lib_msdmd.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skill-lib_msdmd.ts b/skill-lib_msdmd.ts index 1a17408..09ea7e1 100644 --- a/skill-lib_msdmd.ts +++ b/skill-lib_msdmd.ts @@ -10,11 +10,11 @@ export default defineMsdmdCollection({ repo: "The-Interdependency/skill-lib", declarations: [ { - file: "gonol-build/check_edcm_boundary.py", + file: "tools/check_edcm_boundary.py", block: "MODULE_BUILD", id: "gonol_edcm_scale_witness", fields: { - source: "gonol-build/check_edcm_boundary.py", + source: "tools/check_edcm_boundary.py", summary: "Exact EDCM cross-source witness for non-adjacent scale construction, replay, and candidate non-transfer; not geometry or measurement proof", }, },