From 878d0caa70cde04ce9ff0d69b096c14eabe892f6 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 20:53:29 -0700 Subject: [PATCH 01/36] fix: move gonol construction authority out of EDCM --- gonol-build/SKILL.md | 114 +++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/gonol-build/SKILL.md b/gonol-build/SKILL.md index 6e0e97d..44dc5f0 100644 --- a/gonol-build/SKILL.md +++ b/gonol-build/SKILL.md @@ -1,87 +1,91 @@ --- 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 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. +description: Construction, closure, and replay discipline for active gonol-language research. Load this when building or reviewing language constructions made from UCNS gonol objects in The-Interdependency/stack, or when checking closure, atomic participation, provenance, replay, and unresolved geometry boundaries. UCNS owns gonol objects, constructors, and geometry; Stack owns active construction research; EDCM owns measurement/evaluation only. Closed gonols participate atomically at admissible consuming scales; no universal adjacent-scale ladder is required. Pronunciation is not required unless an explicitly declared construction makes it part of the build. Do not load for unrelated geometry, ordinary prose editing, or measurement over already-closed gonols. --- # gonol-build -Use this skill to keep gonol construction on the declared architecture and nothing else. +Use this skill to keep gonol-language construction on the declared architecture and nothing else. ## Workflow -1. Resolve the current UCNS and EDCM authorities before building. +1. Resolve the exact UCNS authority and the exact owning Stack research workspace 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. 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. +3. Resolve the owning Stack workspace's declared source/admission profile, participant eligibility, relations, and closure rules; do not impose a universal adjacent-scale ladder. +4. Consume UCNS gonol constructors and geometry rather than defining a competing gonol object in the language layer. +5. Close each completed gonol before it participates atomically at an admissible consuming scale. +6. If required UCNS geometry is unresolved, preserve that boundary as `hmmm`. +7. Replay the complete declared scope only where replay is required by the governing protocol. ## Authority ```text -UCNS = geometry -EDCM = text-domain gonol construction +UCNS = gonol objects, constructors, and underlying geometry +Stack = active language-gonol construction research workspaces +EDCM = measurement and evaluation of constructed outputs skill-lib = construction/replay discipline ``` -Resolve the current UCNS and EDCM authorities before building. Do not move text semantics into UCNS or invent geometry in EDCM. +Repository placement does not transfer authority. A Stack workspace may construct English, Python, French, TypeScript, or another domain from UCNS gonol objects without thereby owning UCNS geometry. EDCM may measure a completed construction without defining that construction. -## EDCM construction contract +Historical EDCM constructor names and sealed artifacts remain valid historical identities for replay. They do not restore active construction authority to EDCM. + +## Active construction contract ```text -declared scale option set + eligible already-closed participants -> construction -> closure +declared source/admission profile ++ eligible already-closed participants ++ constitutive relation ++ UCNS gonol construction +-> closure ``` -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. +The active constructor contract belongs to the owning Stack research workspace. Resolve its exact files and commit before selecting participants. For the current English research workspace this includes `research/english-gonol/`; for current Python research this includes `research/python-gonol/`. These paths are workspace locations, not universal language canon. -- Every admitted character is a gonol. -- 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. +The sequence `characters -> words -> definitions -> recursive relations` may describe a particular construction, but it is not a mandatory ladder for every language or every admitted construction. -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. +- Every admitted primitive occurrence required by the active profile remains individually addressable. +- Ordered closed gonols may close into a higher construction when the owning workspace authorizes that relation. +- Any closed gonol is atomic at an admissible consuming scale while constituent identities, order, multiplicity, source positions, relations, and provenance remain recoverable. +- Constitutive relationships belong inside the construction. Sidecars may index or cache them but must not replace them. +- Recursive relations consume already-closed gonols without reopening or erasing their internal structure. + +Do not invent participant eligibility, a required intermediate stage, semantic axes, or a geometry law merely to complete a pipeline. ## Pronunciation boundary -Pronunciation is not required for this construction. Pronunciation, phonetic spelling, IPA, audio, or other sound representations must not alter gonol identity, closure, ordering, or relations unless a later explicitly declared experiment makes phonology part of its construction. +Pronunciation is not required by default. Pronunciation, phonetic spelling, IPA, audio, or other sound representations must not alter gonol identity, closure, ordering, or relations unless the owning construction explicitly admits phonology. -Source pronunciation data may remain source metadata. It is not a dependency of the current build. +Source pronunciation data may remain evidence or metadata. It becomes construction only under an explicit source/admission contract. ## Construction invariant -At every scale: +At every admitted scale: ```text -ordered eligible gonols --> authorized UCNS geometric relation/application +ordered eligible closed gonols +-> constitutive relation declared by the owning workspace +-> UCNS gonol construction / authorized geometric application -> closure -> deterministic identity + provenance receipt -> 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. +Preserve exact source identity, occurrence order, multiplicity, relation identity, and provenance. Do not normalize, deduplicate, infer relations, or substitute tokens, AST nodes, compiler objects, embeddings, hashes, or metadata for gonol construction unless the active contract explicitly authorizes their role. If required UCNS geometry is unresolved, preserve that boundary as `hmmm`; do not fill it with an invented rule. ## Candidate boundary -An unresolved constructor is permission to construct a named, bounded candidate; it does not block declared experimentation. It blocks promotion beyond the evidence, not construction or testing. +An unresolved constructor or geometry operation is permission to construct a named, bounded candidate only where the declared evidence permits it. It blocks promotion beyond the evidence, not honest experimentation. ## Completion and replay -Before launching a construction or replay run whose completion materially depends on scarce resources, preflight the resources required to finish it. If the preflight cannot establish enough resource confidence to finish the declared scope, do not start the compute run; record the unresolved resource boundary as `hmmm` or narrow the declared scope under the governing protocol. Once a healthy admitted run begins, let it reach its natural terminal condition unless a genuine safety/resource boundary or preregistered load-bearing stop condition fires. Do not add arbitrary wall-clock limits. +Before launching a construction or replay run whose completion materially depends on scarce resources, preflight the resources required to finish it. If the preflight cannot establish enough resource confidence to finish the declared scope, do not start the compute run; record the resource boundary as `hmmm` or narrow the declared scope under the governing protocol. Once a healthy admitted run begins, let it reach its natural terminal condition unless a genuine safety/resource boundary or preregistered load-bearing stop condition fires. Do not add arbitrary wall-clock limits. A completion claim requires: -1. exact UCNS, EDCM, source/profile, and constructor identities; +1. exact UCNS, Stack workspace, source/profile, and constructor identities; 2. the complete declared source scope; 3. deterministic construction receipts; and 4. independent complete replay where replay is required by the governing protocol. @@ -90,41 +94,37 @@ Replay establishes reproducibility of that construction only. It does not by its ## Usage guidance -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`: +For active gonol-language construction, start in the owning research workspace inside `The-Interdependency/stack` and consume current UCNS gonol constructors/geometry. Do not start in EDCM. -```bash -python tools/check_edcm_boundary.py /path/to/edcm +```text +UCNS: gonol objects + constructors + geometry +Stack: active construction research +EDCM: measurement/evaluation only ``` -It checks direct character-to-definition construction, replay, candidate standing, -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. +Use `stack-update` when ownership, placement, authority, lifecycle, or promotion changes. Use `interdependent-work-graph` whenever the task crosses repository boundaries. -For text construction, start in EDCM and consume current UCNS geometry. +Run skill-lib's local authority regression gate after changing this boundary: -```text -UCNS: geometry -EDCM: declared scale options, participant eligibility, text construction +```bash +python tools/check_gonol_authority.py ``` -When a gonol closes, use it atomically at any admissible consuming scale. Ignore pronunciation unless a future explicit construction says otherwise. +When a gonol closes, use it atomically at an admissible consuming scale. Ignore pronunciation unless an explicit construction says otherwise. ## 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, hashes for gonol identity unless the active contract explicitly authorizes it. +- Assigning active gonol or language construction authority to EDCM. +- Defining a competing gonol object in an English, Python, or other language workspace instead of consuming UCNS construction authority. +- Treating Stack placement as transfer of UCNS geometry authority. +- Imposing an adjacent-scale ladder or inventing an eligible relation without the owning workspace's authority. +- Letting pronunciation alter gonol identity, closure, ordering, or relations unless an explicit construction admits it. +- Normalizing, deduplicating, inferring relations, or substituting tokens, AST nodes, embeddings, hashes, or metadata for gonol identity unless explicitly authorized. - Adding arbitrary wall-clock limits to a healthy admitted run. - Treating replay as semantic quality, measurement validity, cognition, or extra-scope canon. ## hmmm - 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. \ No newline at end of file +- future repository/package placement for graduated language-gonol artifacts where no repository presently exists; +- any recursive relation whose governing source or geometry is not yet established. From 30ed2a1a26ea55fe2739cce766cb6f111da39c9e Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 20:53:37 -0700 Subject: [PATCH 02/36] fix: regenerate gonol-build adapter authority --- skills/gonol-build/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/gonol-build/SKILL.md b/skills/gonol-build/SKILL.md index 9125b71..c16b8e4 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 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." +description: "Construction, closure, and replay discipline for active gonol-language research. Load this when building or reviewing language constructions made from UCNS gonol objects in The-Interdependency/stack, or when checking closure, atomic participation, provenance, replay, and unresolved geometry boundaries. UCNS owns gonol objects, constructors, and geometry; Stack owns active construction research; EDCM owns measurement/evaluation only. Closed gonols participate atomically at admissible consuming scales; no universal adjacent-scale ladder is required. Pronunciation is not required unless an explicitly declared construction makes it part of the build. Do not load for unrelated geometry, ordinary prose editing, or measurement over already-closed gonols." --- From e576635d0ae8051feb7efcf59fc5b30b249f84e6 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 20:53:52 -0700 Subject: [PATCH 03/36] test: enforce corrected gonol authority --- tests/test_gonol_build_skill.py | 124 +++++++++----------------------- 1 file changed, 35 insertions(+), 89 deletions(-) diff --git a/tests/test_gonol_build_skill.py b/tests/test_gonol_build_skill.py index d8d4460..32c7961 100644 --- a/tests/test_gonol_build_skill.py +++ b/tests/test_gonol_build_skill.py @@ -9,7 +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" +WITNESS = ROOT / "tools" / "check_gonol_authority.py" class GonolBuildSkillTest(unittest.TestCase): @@ -21,132 +21,78 @@ def setUp(self) -> None: def test_activation_contract_is_concrete(self) -> None: description = self.frontmatter["description"] for phrase in ( - "character, word, definition, or recursive-relation gonols", - "UCNS owns geometry; EDCM owns text construction", + "UCNS gonol objects", + "Stack owns active construction research", + "EDCM owns measurement/evaluation only", "no universal adjacent-scale ladder is required", "Pronunciation is not required", - "Do not load", ): self.assertIn(phrase, description) - def test_authority_split_is_minimal(self) -> None: + def test_authority_split_is_current(self) -> None: for phrase in ( - "UCNS = geometry", - "EDCM = text-domain gonol construction", + "UCNS = gonol objects, constructors, and underlying geometry", + "Stack = active language-gonol construction research workspaces", + "EDCM = measurement and evaluation of constructed outputs", "skill-lib = construction/replay discipline", - "Do not move text semantics into UCNS", - "invent geometry in EDCM", ): self.assertIn(phrase, self.compact) + self.assertNotIn("EDCM = text-domain gonol construction", self.compact) + self.assertNotIn("EDCM owns the admissible scale options", 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_active_construction_resolves_stack_workspace(self) -> None: + self.assertIn("research/english-gonol/", self.text) + self.assertIn("research/python-gonol/", self.text) + self.assertIn("Do not start in EDCM", self.text) + self.assertIn("Historical EDCM constructor names", self.text) - 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: + def test_gonol_object_authority_remains_ucns(self) -> None: for phrase in ( - "Any closed gonol is atomic at an admissible consuming scale", - "constituent identities, order, multiplicity, source positions, and provenance remain recoverable", - "Definition gonols use eligible closed participants", - "Recursive relations are constructed from already-closed gonols", + "Consume UCNS gonol constructors and geometry", + "Defining a competing gonol object", + "consume UCNS construction authority", ): self.assertIn(phrase, self.compact) - def test_no_undeclared_intermediate_stage(self) -> None: - self.assertIn( - "Do not invent participant eligibility or another required stage", - self.compact, - ) - - def test_pronunciation_is_inert_by_default(self) -> None: + def test_closed_gonols_participate_atomically(self) -> None: for phrase in ( - "Pronunciation is not required for this construction", - "must not alter gonol identity, closure, ordering, or relations", - "Source pronunciation data may remain source metadata", - "It is not a dependency of the current build", + "Any closed gonol is atomic at an admissible consuming scale", + "constituent identities, order, multiplicity, source positions, relations, and provenance remain recoverable", + "Constitutive relationships belong inside the construction", + "Recursive relations consume already-closed gonols", ): self.assertIn(phrase, self.compact) - def test_construction_invariant_preserves_identity_and_provenance(self) -> None: + def test_no_substitute_representation(self) -> None: for phrase in ( - "ordered eligible gonols", - "authorized UCNS geometric relation/application", - "deterministic identity + provenance receipt", - "Preserve exact source identity, occurrence order, multiplicity, and provenance", "Do not normalize, deduplicate, infer relations", + "tokens, AST nodes, compiler objects, embeddings, hashes, or metadata", + "do not fill it with an invented rule", ): self.assertIn(phrase, self.compact) - def test_unresolved_geometry_stays_hmmm(self) -> None: - self.assertIn("preserve that boundary as `hmmm`", self.text) - self.assertIn("do not fill it with an invented rule", self.compact) + def test_local_authority_gate_is_named(self) -> None: + self.assertTrue(WITNESS.is_file()) + self.assertIn("python tools/check_gonol_authority.py", self.text) - def test_completion_requires_full_scope_and_replay(self) -> None: + def test_completion_preserves_replay_boundary(self) -> None: for phrase in ( - "Before launching a construction or replay run whose completion materially depends on scarce resources", "preflight the resources required to finish it", - "do not start the compute run", "Do not add arbitrary wall-clock limits", "the complete declared source scope", "deterministic construction receipts", - "independent complete replay where replay is required by the governing protocol", + "independent complete replay where replay is required", "Replay establishes reproducibility of that construction only", ): self.assertIn(phrase, self.compact) - def test_workflow_preflights_before_compute_and_replays_conditionally(self) -> None: - workflow = self.text.split("## Workflow", 1)[1].split("## Authority", 1)[0] - for phrase in ( - "Before launching construction or replay whose completion materially depends on scarce resources", - "preflight the resources required to finish the declared scope", - "Replay the complete declared scope only where replay is required by the governing protocol", - ): - self.assertIn(phrase, workflow) - self.assertLess( - workflow.index("Before launching construction or replay"), - 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", - workflow, - ) - - def test_workflow_and_anti_patterns_are_named(self) -> None: - self.assertIn("## Workflow", self.text) - self.assertIn("## Anti-patterns", self.text) - self.assertIn("Resolve the current UCNS and EDCM authorities before building", self.compact) - self.assertIn("Moving text semantics into UCNS or inventing geometry in EDCM", self.compact) - - def test_anti_patterns_preserve_explicit_contract_exceptions(self) -> None: - anti_patterns = self.text.split("## Anti-patterns", 1)[1].split("## hmmm", 1)[0] - self.assertIn( - "unless a later explicitly declared experiment makes phonology part of its construction", - anti_patterns, - ) - self.assertIn( - "unless the active contract explicitly authorizes it", - anti_patterns, - ) - - 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 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: text = ADAPTER.read_text(encoding="utf-8") self.assertIn("Generated by tools/build_codex_plugin_skills.py", text) self.assertIn("../../gonol-build/SKILL.md", text) + self.assertIn("EDCM owns measurement/evaluation only", text) + self.assertNotIn("EDCM owns text construction", text) if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() From c719db5597f9e85aeae104f5c2d2ba9b77cb5733 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 20:57:16 -0700 Subject: [PATCH 04/36] test: remove stale EDCM construction authority --- tests/test_char_compress_authority.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/test_char_compress_authority.py b/tests/test_char_compress_authority.py index 6bda9c1..a036e8b 100644 --- a/tests/test_char_compress_authority.py +++ b/tests/test_char_compress_authority.py @@ -10,9 +10,12 @@ 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("not a UCNS construction law or a mandatory Stack language-construction ladder", compact) + self.assertIn("EDCM owns measurement/evaluation only", text) + self.assertIn("Active language-gonol construction", text) + self.assertIn("research workspace in `The-Interdependency/stack`", text) self.assertIn("no current UCNS mathematical derivation is claimed", compact) + self.assertNotIn("EDCM owns text-domain gonol construction", text) for false_claim in ("Punctuation is a stronger typed twist", "Its mathematics is the source of the compression algorithm"): self.assertNotIn(false_claim, compact) From 8e8a9f71eb13e49c95c9543d107ff5d3a6c4db8d Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 20:58:44 -0700 Subject: [PATCH 05/36] fix: point gonol authority guidance at local gate --- gonol-build/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gonol-build/SKILL.md b/gonol-build/SKILL.md index 44dc5f0..02e5f63 100644 --- a/gonol-build/SKILL.md +++ b/gonol-build/SKILL.md @@ -107,7 +107,7 @@ Use `stack-update` when ownership, placement, authority, lifecycle, or promotion Run skill-lib's local authority regression gate after changing this boundary: ```bash -python tools/check_gonol_authority.py +bash tools/check_gonol_authority.sh ``` When a gonol closes, use it atomically at an admissible consuming scale. Ignore pronunciation unless an explicit construction says otherwise. From f26ef84df2266890e39eba2dfd5a548f7dc06f7f Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 20:58:57 -0700 Subject: [PATCH 06/36] test: point gonol authority gate at shell checker --- tests/test_gonol_build_skill.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_gonol_build_skill.py b/tests/test_gonol_build_skill.py index 32c7961..d857287 100644 --- a/tests/test_gonol_build_skill.py +++ b/tests/test_gonol_build_skill.py @@ -9,7 +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_gonol_authority.py" +WITNESS = ROOT / "tools" / "check_gonol_authority.sh" class GonolBuildSkillTest(unittest.TestCase): @@ -73,7 +73,7 @@ def test_no_substitute_representation(self) -> None: def test_local_authority_gate_is_named(self) -> None: self.assertTrue(WITNESS.is_file()) - self.assertIn("python tools/check_gonol_authority.py", self.text) + self.assertIn("bash tools/check_gonol_authority.sh", self.text) def test_completion_preserves_replay_boundary(self) -> None: for phrase in ( From 67db39ebb03e585081a284ecda764938a7e4cd23 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 20:59:58 -0700 Subject: [PATCH 07/36] fix: repair gonol authority and add canonical ai launcher --- ORG_DISTRIBUTION.md | 2 +- char-compress/SKILL.md | 20 ++-- tools/ai.sh | 182 +++++++++++++++++++++++++++++++++ tools/check_gonol_authority.sh | 15 +++ tools/install_ai.sh | 57 +++++++++++ 5 files changed, 267 insertions(+), 9 deletions(-) create mode 100755 tools/ai.sh create mode 100755 tools/check_gonol_authority.sh create mode 100755 tools/install_ai.sh diff --git a/ORG_DISTRIBUTION.md b/ORG_DISTRIBUTION.md index 658c6e7..a3b703d 100644 --- a/ORG_DISTRIBUTION.md +++ b/ORG_DISTRIBUTION.md @@ -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 geometry / EDCM text construction, declared scale options, closure, atomic participation, protocol-required replay, and honest continuation boundaries +* `gonol-build/` — UCNS gonol objects/constructors/geometry + Stack language-construction research, closure, atomic participation, replay, and honest continuation boundaries; EDCM is measurement/evaluation only * `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/char-compress/SKILL.md b/char-compress/SKILL.md index 04eb0af..e0dc795 100644 --- a/char-compress/SKILL.md +++ b/char-compress/SKILL.md @@ -1,6 +1,6 @@ --- name: char-compress -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. +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, active language-construction authority, or edcmbone metric implementation. --- # char-compress — bone/flesh compression for agent context @@ -42,14 +42,16 @@ this repo remains the canonical source. ### Relation to `ucns` -`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. +`ucns` owns current gonol objects, constructors, and geometry, not lexical +classes or this compression procedure. Active language-gonol construction is +owned by the applicable research workspace in `The-Interdependency/stack`; +EDCM owns measurement/evaluation only. None of those authorities is acquired +by calling a text inventory a carrier or a separator a twist. 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. +before using any actual UCNS operation or active Stack construction contract. Allowed relation: @@ -89,8 +91,9 @@ Use edcmbone doctrine as a guardrail: ## Optional local text-stack notation 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. +law or a mandatory Stack language-construction ladder. Here `tensor`, `twist`, +`gonol`, `carrier`, `spiral`, and `chirality` are historical local labels, not +constructed geometry. ```text tensors = characters @@ -267,7 +270,8 @@ separator/boundary data that changes attachment or closure must be preserved 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. + is not required and does not authorize UCNS geometry or active Stack + construction. 3. **Run a suppression sort.** Identify first-occurrence inventory, recurrence data required for reconstruction, units that survive as diff --git a/tools/ai.sh b/tools/ai.sh new file mode 100755 index 0000000..6b86ea3 --- /dev/null +++ b/tools/ai.sh @@ -0,0 +1,182 @@ +#!/usr/bin/env bash +# ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm +set -euo pipefail + +# === MODULE_BUILD === +# id: skill_lib_ai_launcher +# module_name: ai +# module_kind: cli +# summary: canonical tmux launcher for coding-agent CLIs on the development VM with pane health, restart, and persistent pane logs +# owner: skill-lib +# public_surface: ai start|attach|status|restart|logs|grok|codex|deepcode|shell +# internal_surface: tmux session/window lifecycle helpers +# auth_boundary: launched CLIs own their authentication +# storage_boundary: writes logs under ~/.local/state/a0/logs only +# network_boundary: none directly +# user_data_boundary: does not read or print provider credentials +# admin_only: false +# tests: tests/test_ai_launcher.py +# rollout: explicit install via tools/install_ai.sh +# rollback: remove ~/.local/bin/ai wrapper +# requires: bash, tmux; optional grok/codex/deepcode CLIs +# since: 2026-09-12 +# unresolved: host-local third-party CLI command names may change +# === END MODULE_BUILD === + +SESSION="${A0_AI_SESSION:-a0}" +STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" +LOG_DIR="${A0_AI_LOG_DIR:-$STATE_HOME/a0/logs}" +SHELL_CMD="${A0_SHELL_CMD:-${SHELL:-/bin/bash} -l}" +GROK_CMD="${A0_GROK_CMD:-grok}" +CODEX_CMD="${A0_CODEX_CMD:-codex --yolo}" +DEEPCODE_CMD="${A0_DEEPCODE_CMD:-deepcode}" +mkdir -p "$LOG_DIR" + +usage() { + cat <<'EOF' +usage: ai [start|attach|status|restart [agent|all]|logs [agent]|grok|codex|deepcode|shell|menu] +EOF +} + +require_tmux() { command -v tmux >/dev/null 2>&1 || { echo 'tmux is required' >&2; exit 127; }; } +has_session() { tmux has-session -t "$SESSION" 2>/dev/null; } +window_exists() { has_session && tmux list-windows -t "$SESSION" -F '#W' | grep -Fxq "$1"; } + +ensure_session() { + require_tmux + has_session || tmux new-session -d -s "$SESSION" -n bash +} + +ensure_window() { + local index="$1" name="$2" + ensure_session + if ! window_exists "$name"; then + if tmux list-windows -t "$SESSION" -F '#I' | grep -Fxq "$index"; then + tmux new-window -d -t "$SESSION" -n "$name" + else + tmux new-window -d -t "$SESSION:$index" -n "$name" + fi + fi + tmux set-option -w -t "$SESSION:$name" remain-on-exit on >/dev/null +} + +pipe_log() { + local name="$1" file="$LOG_DIR/$1.log" quoted + quoted="$(printf '%q' "$file")" + tmux pipe-pane -o -t "$SESSION:$name.0" "cat >> $quoted" +} + +launch() { + local index="$1" name="$2" command_line="$3" binary quoted + ensure_window "$index" "$name" + binary="${command_line%% *}" + pipe_log "$name" + if ! command -v "$binary" >/dev/null 2>&1; then + printf 'command unavailable: %s\n' "$binary" >&2 + return 127 + fi + quoted="$(printf '%q' "$command_line")" + tmux respawn-pane -k -t "$SESSION:$name.0" "exec bash -lc $quoted" + pipe_log "$name" +} + +ensure_shell() { + ensure_window 2 bash + pipe_log bash +} + +start_all() { + ensure_session + launch 0 grok-4-fast "$GROK_CMD" || true + launch 1 codex "$CODEX_CMD" || true + ensure_shell + launch 3 deepcode "$DEEPCODE_CMD" || true +} + +status() { + require_tmux + has_session || { printf 'session %s missing\n' "$SESSION"; return 1; } + tmux list-panes -a -t "$SESSION" -F '#{window_index}\t#{window_name}\tdead=#{pane_dead}\tpid=#{pane_pid}\tcommand=#{pane_current_command}' | sort -n +} + +restart_one() { + case "$1" in + grok|grok-4-fast) launch 0 grok-4-fast "$GROK_CMD" ;; + codex) launch 1 codex "$CODEX_CMD" ;; + deepcode) launch 3 deepcode "$DEEPCODE_CMD" ;; + shell|bash) launch 2 bash "$SHELL_CMD" ;; + *) printf 'unknown target: %s\n' "$1" >&2; return 2 ;; + esac +} + +restart() { + local target="${1:-all}" + if [[ "$target" == all ]]; then + restart_one grok || true + restart_one codex || true + restart_one shell || true + restart_one deepcode || true + else + restart_one "$target" + fi +} + +attach_window() { + local name="$1" + if [[ -n "${TMUX-}" ]]; then + tmux switch-client -t "$SESSION:$name" + else + tmux select-window -t "$SESSION:$name" + exec tmux attach-session -t "$SESSION" + fi +} + +open_agent() { + local name="$1" + case "$name" in + grok|grok-4-fast) window_exists grok-4-fast || restart_one grok || true; attach_window grok-4-fast ;; + codex) window_exists codex || restart_one codex || true; attach_window codex ;; + deepcode) window_exists deepcode || restart_one deepcode || true; attach_window deepcode ;; + shell|bash) window_exists bash || ensure_shell; attach_window bash ;; + esac +} + +logs() { + local name="${1:-deepcode}" file="$LOG_DIR/${1:-deepcode}.log" + [[ -f "$file" ]] || { printf 'no log yet: %s\n' "$file"; return 1; } + tail -n "${A0_AI_LOG_LINES:-200}" "$file" +} + +menu() { + ensure_session + while true; do + printf '\n1 Grok 2 Codex 3 DeepCode 4 Shell 5 Status 6 Restart 7 Logs 8 Start/repair all 0 Exit\n' + read -r -p '> ' choice + case "$choice" in + 1) open_agent grok ;; + 2) open_agent codex ;; + 3) open_agent deepcode ;; + 4) open_agent shell ;; + 5) status || true ;; + 6) read -r -p 'restart [grok/codex/deepcode/shell/all]: ' target; restart "${target:-all}" || true ;; + 7) read -r -p 'log [deepcode/codex/grok-4-fast/bash]: ' target; logs "${target:-deepcode}" || true ;; + 8) start_all ;; + 0) return ;; + *) echo 'unknown choice' ;; + esac + done +} + +case "${1:-menu}" in + start) start_all ;; + attach) ensure_session; exec tmux attach-session -t "$SESSION" ;; + status) status ;; + restart) shift; restart "${1:-all}" ;; + logs) shift; logs "${1:-deepcode}" ;; + grok|grok-4-fast|codex|deepcode|shell|bash) ensure_session; open_agent "$1" ;; + menu) menu ;; + -h|--help|help) usage ;; + *) usage >&2; exit 2 ;; +esac + +# ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm diff --git a/tools/check_gonol_authority.sh b/tools/check_gonol_authority.sh new file mode 100755 index 0000000..5396367 --- /dev/null +++ b/tools/check_gonol_authority.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" + +grep -Fq 'UCNS = gonol objects, constructors, and underlying geometry' gonol-build/SKILL.md +grep -Fq 'Stack = active language-gonol construction research workspaces' gonol-build/SKILL.md +grep -Fq 'EDCM = measurement and evaluation of constructed outputs' gonol-build/SKILL.md +! grep -Fq 'EDCM = text-domain gonol construction' gonol-build/SKILL.md +! grep -Fq 'EDCM owns text-domain gonol construction' char-compress/SKILL.md + +echo 'gonol authority: OK' +# ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm diff --git a/tools/install_ai.sh b/tools/install_ai.sh new file mode 100755 index 0000000..1ca741c --- /dev/null +++ b/tools/install_ai.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm +set -euo pipefail + +# === MODULE_BUILD === +# id: skill_lib_ai_installer +# module_name: install_ai +# module_kind: installer +# summary: installs a stable PATH wrapper that executes the canonical skill-lib tools/ai.sh in place +# owner: skill-lib +# public_surface: bash tools/install_ai.sh +# internal_surface: none +# auth_boundary: none +# storage_boundary: writes ~/.local/bin/ai and an idempotent ~/.profile PATH line +# network_boundary: none +# user_data_boundary: no credentials read or written +# admin_only: false +# tests: tests/test_ai_launcher.py +# rollout: explicit user invocation +# rollback: rm ~/.local/bin/ai and remove the marked PATH line if undesired +# requires: bash +# since: 2026-09-12 +# unresolved: current shell cannot inherit PATH changes from a child process; reopen shell or source ~/.profile +# === END MODULE_BUILD === + +SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SOURCE="$SOURCE_DIR/ai.sh" +BIN_DIR="${A0_AI_BIN_DIR:-$HOME/.local/bin}" +TARGET="$BIN_DIR/ai" +PROFILE="${A0_AI_PROFILE:-$HOME/.profile}" +PATH_LINE='export PATH="$HOME/.local/bin:$PATH" # skill-lib ai launcher' + +[[ -f "$SOURCE" ]] || { printf 'ERROR: canonical launcher missing: %s\n' "$SOURCE" >&2; exit 2; } +mkdir -p "$BIN_DIR" "${XDG_STATE_HOME:-$HOME/.local/state}/a0/logs" + +cat > "$TARGET" <> "$PROFILE" + fi +fi + +printf 'installed: %s\n' "$TARGET" +printf 'source: %s\n' "$SOURCE" +if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then + printf 'PATH updated for future login shells in %s\n' "$PROFILE" + printf 'for this shell: export PATH="$HOME/.local/bin:$PATH"\n' +fi +"$TARGET" --help + +# ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm From 5e73acb0fc7462b4fcdb5fbdff31b204bf6e5132 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:00:33 -0700 Subject: [PATCH 08/36] ci: replace active EDCM witness with gonol authority gate --- .github/workflows/ci.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 684beef..e992379 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,13 +21,8 @@ jobs: node-version: "24.15.0" - 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 tools/check_edcm_boundary.py "$EDCM_CHECKOUT" + - name: Gonol authority gate + run: bash tools/check_gonol_authority.sh - name: Skill library drift run: python tools/check_skill_lib_drift.py --warnings-fail - name: Skill compliance @@ -41,4 +36,4 @@ jobs: - name: RepoLOTO audit run: python tests/test_repo_loto.py --audit - name: RepoLOTO checks - run: python tests/test_repo_loto.py \ No newline at end of file + run: python tests/test_repo_loto.py From 54a9043170ecbb9d0c962d8c09330e47b5d89db2 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:00:42 -0700 Subject: [PATCH 09/36] test: cover canonical ai launcher and installer --- tests/test_ai_launcher.py | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 tests/test_ai_launcher.py diff --git a/tests/test_ai_launcher.py b/tests/test_ai_launcher.py new file mode 100644 index 0000000..853e448 --- /dev/null +++ b/tests/test_ai_launcher.py @@ -0,0 +1,56 @@ +from __future__ import annotations + +from pathlib import Path +import unittest + + +ROOT = Path(__file__).resolve().parents[1] +LAUNCHER = ROOT / "tools" / "ai.sh" +INSTALLER = ROOT / "tools" / "install_ai.sh" + + +class AILauncherTests(unittest.TestCase): + def test_launcher_is_canonical_tmux_surface(self) -> None: + text = LAUNCHER.read_text(encoding="utf-8") + for phrase in ( + 'SESSION="${A0_AI_SESSION:-a0}"', + 'CODEX_CMD="${A0_CODEX_CMD:-codex --yolo}"', + 'DEEPCODE_CMD="${A0_DEEPCODE_CMD:-deepcode}"', + "remain-on-exit on", + "tmux pipe-pane", + "#{pane_dead}", + "#{pane_current_command}", + "tmux respawn-pane -k", + '.local/state}/a0/logs', + ): + self.assertIn(phrase, text) + + def test_launcher_does_not_manage_provider_secrets(self) -> None: + text = LAUNCHER.read_text(encoding="utf-8") + for secret_name in ( + "OPENAI_API_KEY", + "DEEPSEEK_API_KEY", + "ANTHROPIC_API_KEY", + "XAI_API_KEY", + ): + self.assertNotIn(secret_name, text) + + def test_installer_places_stable_ai_command_on_user_path(self) -> None: + text = INSTALLER.read_text(encoding="utf-8") + for phrase in ( + '$HOME/.local/bin', + 'TARGET="$BIN_DIR/ai"', + 'exec bash', + 'skill-lib ai launcher', + 'chmod 0755 "$TARGET"', + ): + self.assertIn(phrase, text) + + def test_installer_executes_repo_source_instead_of_copying_it(self) -> None: + text = INSTALLER.read_text(encoding="utf-8") + self.assertIn('SOURCE="$SOURCE_DIR/ai.sh"', text) + self.assertNotIn('cp "$SOURCE" "$TARGET"', text) + + +if __name__ == "__main__": + unittest.main() From 31040dcb366d4f5a10c1416e089cdf8cc3b5a2ea Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:00:54 -0700 Subject: [PATCH 10/36] test: correct ai log path assertion --- tests/test_ai_launcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_ai_launcher.py b/tests/test_ai_launcher.py index 853e448..09827ea 100644 --- a/tests/test_ai_launcher.py +++ b/tests/test_ai_launcher.py @@ -21,7 +21,7 @@ def test_launcher_is_canonical_tmux_surface(self) -> None: "#{pane_dead}", "#{pane_current_command}", "tmux respawn-pane -k", - '.local/state}/a0/logs', + 'LOG_DIR="${A0_AI_LOG_DIR:-$STATE_HOME/a0/logs}"', ): self.assertIn(phrase, text) From 5e4c031bea4a19ad9dc7bb54ef488cd543ef091f Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:02:06 -0700 Subject: [PATCH 11/36] fix: synchronize corrected skill authority metadata --- skills.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skills.json b/skills.json index 12931d6..46b0893 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, 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":"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, active language-construction authority, 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 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":"gonol-build","path":"gonol-build/SKILL.md","kind":"procedural","description":"Construction, closure, and replay discipline for active gonol-language research. Load this when building or reviewing language constructions made from UCNS gonol objects in The-Interdependency/stack, or when checking closure, atomic participation, provenance, replay, and unresolved geometry boundaries. UCNS owns gonol objects, constructors, and geometry; Stack owns active construction research; EDCM owns measurement/evaluation only. Closed gonols participate atomically at admissible consuming scales; no universal adjacent-scale ladder is required. Pronunciation is not required unless an explicitly declared construction makes it part of the build. 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."}, From 6647737e40f79acf93b93eb07bb79dac1f26f7e4 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:02:50 -0700 Subject: [PATCH 12/36] fix: refresh skill-lib collection for authority gate and ai launcher --- skill-lib_msdmd.ts | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/skill-lib_msdmd.ts b/skill-lib_msdmd.ts index 09ea7e1..c608938 100644 --- a/skill-lib_msdmd.ts +++ b/skill-lib_msdmd.ts @@ -10,12 +10,30 @@ export default defineMsdmdCollection({ repo: "The-Interdependency/skill-lib", declarations: [ { - file: "tools/check_edcm_boundary.py", + file: "tools/check_gonol_authority.sh", block: "MODULE_BUILD", - id: "gonol_edcm_scale_witness", + id: "gonol_authority_gate", fields: { - 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", + source: "tools/check_gonol_authority.sh", + summary: "Guards active gonol authority: UCNS owns gonol objects/constructors/geometry, Stack owns active construction research, EDCM owns measurement/evaluation only", + }, + }, + { + file: "tools/ai.sh", + block: "MODULE_BUILD", + id: "skill_lib_ai_launcher", + fields: { + source: "tools/ai.sh", + summary: "Canonical tmux launcher for coding-agent CLIs with pane health, restart, remain-on-exit, and persistent logs", + }, + }, + { + file: "tools/install_ai.sh", + block: "MODULE_BUILD", + id: "skill_lib_ai_installer", + fields: { + source: "tools/install_ai.sh", + summary: "Installs the skill-lib ai launcher as ~/.local/bin/ai and ensures the user PATH contains ~/.local/bin", }, }, { From 8fa7ce3e7af1bbe561d63b5fec205c5933862c5c Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:03:00 -0700 Subject: [PATCH 13/36] remove: retire stale active EDCM construction witness --- tools/check_edcm_boundary.py | 66 ------------------------------------ 1 file changed, 66 deletions(-) delete mode 100644 tools/check_edcm_boundary.py diff --git a/tools/check_edcm_boundary.py b/tools/check_edcm_boundary.py deleted file mode 100644 index a9948ae..0000000 --- a/tools/check_edcm_boundary.py +++ /dev/null @@ -1,66 +0,0 @@ -# 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 -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=33:22 imports_exports=4:1 calls_definitions=16:1 \ No newline at end of file From 0801c0e24eec97fab6884962fecb1fef304ed3c1 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:04:02 -0700 Subject: [PATCH 14/36] docs: document gonol authority gate and canonical ai launcher --- tools/README.md | 57 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/tools/README.md b/tools/README.md index c97a06b..75d1157 100644 --- a/tools/README.md +++ b/tools/README.md @@ -3,8 +3,53 @@ Small pure-stdlib helpers for maintaining this content repository. These tools do not introduce an external build system. They are local editorial -checks, copy helpers, and generated-file drift gates. The small `llms/` package -exists only to expose `python -m llms.build`. +checks, copy helpers, launchers, installers, and generated-file drift gates. The +small `llms/` package exists only to expose `python -m llms.build`. + +## Gonol authority gate + +```bash +bash tools/check_gonol_authority.sh +``` + +Fails if active skill-lib doctrine drifts back to assigning gonol/text +construction authority to EDCM. The active split is: + +```text +UCNS = gonol objects, constructors, geometry +Stack = active language-gonol construction research +EDCM = measurement/evaluation only +``` + +## Canonical `ai` launcher + +`tools/ai.sh` is the canonical VM coding-agent launcher. It owns the `a0` tmux +session layout, real pane/process status, restart, `remain-on-exit`, and +persistent pane logs under `~/.local/state/a0/logs`. + +Install the stable `ai` command into the user PATH: + +```bash +bash tools/install_ai.sh +``` + +The installer creates `~/.local/bin/ai` as a wrapper pointing back to the +canonical `tools/ai.sh`; it does not copy a second implementation. If +`~/.local/bin` is absent from PATH it adds one idempotent login-shell line to +`~/.profile`. + +Examples: + +```bash +ai +ai status +ai restart deepcode +ai logs deepcode +ai codex +``` + +Provider credentials remain the responsibility of the installed provider CLIs +and VM environment. The launcher does not read, print, or become a key vault. ## Drift checker @@ -146,8 +191,9 @@ secrets, `hmmm`, and no UCNS-A / edcmbone status leakage. ## CI `.github/workflows/ci.yml` runs the repo verification stack on pull requests and -pushes to `main`: unit tests, skill drift, skill compliance, ratios strict gate, -llms-build drift, RepoLOTO audit, and RepoLOTO checks. +pushes to `main`: unit tests, gonol-authority gate, skill drift, skill +compliance, ratios strict gate, llms-build drift, RepoLOTO audit, and RepoLOTO +checks. `.github/workflows/consumer-drift.yml` runs `check_consumer_drift.py` against every consumer repo on a weekly schedule (and on demand) to detect vendored-copy @@ -159,3 +205,6 @@ extra secret required. - `consumer-drift.yml` only *detects* drift; re-propagation still requires a human or agent to run `propagate_skills.py --apply`, review, commit, and open PRs - `char_compress_check.py` verifies preservation fixtures but is not yet a complete codec +- third-party coding CLI command names and authentication methods can change; + `tools/ai.sh` exposes command overrides rather than pretending those interfaces + are permanent From 97aca608a3938742497786e47b9bb3fde8f47564 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:04:17 -0700 Subject: [PATCH 15/36] chore: add one-shot derived authority repair --- .../workflows/repair-derived-authority.yml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/repair-derived-authority.yml diff --git a/.github/workflows/repair-derived-authority.yml b/.github/workflows/repair-derived-authority.yml new file mode 100644 index 0000000..810cc5f --- /dev/null +++ b/.github/workflows/repair-derived-authority.yml @@ -0,0 +1,66 @@ +name: repair-derived-authority + +on: + push: + branches: [repair/authority-and-ai-launcher] + paths: [.github/workflows/repair-derived-authority.yml] + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7.0.1 + with: + ref: repair/authority-and-ai-launcher + - name: Repair derived authority prose + shell: bash + run: | + python - <<'PY' + from pathlib import Path + + changes = { + "README.md": [ + ( + "| [`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. |", + "| [`gonol-build/`](gonol-build/SKILL.md) | UCNS gonol objects/constructors/geometry + Stack language-construction research discipline. Preserves closure, atomic participation, exact source/occurrence identity, provenance, honest `hmmm`, and scoped replay; EDCM is measurement/evaluation only. Independent of msdmd. |", + ), + ( + "## Maintenance tools\n\nPure-stdlib helper scripts live in [`tools/`](tools/README.md). The small\n`llms/` package exists only to provide the `python -m llms.build` command.\n", + "## VM coding-agent launcher\n\nThe canonical `ai` tmux launcher lives at `tools/ai.sh`. Install a stable command in the user PATH without copying the implementation:\n\n```bash\nbash tools/install_ai.sh\n```\n\nThe installer creates `~/.local/bin/ai` pointing back to this checkout. `ai status` reports actual pane state, `ai restart deepcode` recreates/restarts DeepCode, and pane output persists under `~/.local/state/a0/logs`. Provider credentials remain owned by the provider CLIs/environment.\n\n## Maintenance tools\n\nPure-stdlib helper scripts live in [`tools/`](tools/README.md). The small\n`llms/` package exists only to provide the `python -m llms.build` command.\n", + ), + ], + "CLAUDE.md": [ + ( + "| `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. |", + "| `gonol-build/` | procedural | — | UCNS gonol objects/constructors/geometry + Stack language-construction research discipline. Resolve the owning Stack workspace, preserve closure, atomic participation, occurrence identity, constitutive relations, provenance, and required replay; EDCM is measurement/evaluation only. |", + ), + ( + "- Validation here is editorial plus pure-stdlib helper scripts in `tools/`, `ratios/`, `llms/`, and the RepoLOTO check module.\n", + "- Validation here is editorial plus pure-stdlib helper scripts in `tools/`, `ratios/`, `llms/`, and the RepoLOTO check module.\n- `tools/ai.sh` is the canonical VM coding-agent tmux launcher; `tools/install_ai.sh` installs the stable `~/.local/bin/ai` PATH wrapper.\n", + ), + ], + } + + for filename, replacements in changes.items(): + path = Path(filename) + text = path.read_text(encoding="utf-8") + for old, new in replacements: + if old not in text: + raise SystemExit(f"expected text missing in {filename}: {old[:80]!r}") + text = text.replace(old, new, 1) + path.write_text(text, encoding="utf-8") + PY + - name: Commit derived repair + shell: bash + run: | + if git diff --quiet; then + exit 0 + fi + git config user.name "skill-lib repair" + git config user.email "actions@users.noreply.github.com" + git add README.md CLAUDE.md + git commit -m "docs: repair derived gonol authority and ai launcher [skip ci]" + git push origin HEAD:repair/authority-and-ai-launcher From 3227fb5da402000b371febf1e1003ea51686dad9 Mon Sep 17 00:00:00 2001 From: skill-lib repair Date: Sun, 13 Sep 2026 04:04:26 +0000 Subject: [PATCH 16/36] docs: repair derived gonol authority and ai launcher [skip ci] --- CLAUDE.md | 3 ++- README.md | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 67e2aff..82ca5bf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,6 +11,7 @@ AI-assistant guidance for `The-Interdependency/skill-lib`. - Entry points: `README.md`, `AGENTS.md`, `skills.json`, `ORG_DISTRIBUTION.md`, `llms.txt`, each `/SKILL.md`. - CI workflows: `.github/workflows/hygiene.yml` guards against tracked Python bytecode, `.github/workflows/ci.yml` runs the editorial/helper verification stack, and `.github/workflows/consumer-drift.yml` is a scheduled/dispatch detector that runs `tools/check_consumer_drift.py` against each consumer repo (the consumer repos are public, so it uses the default `GITHUB_TOKEN`). - Validation here is editorial plus pure-stdlib helper scripts in `tools/`, `ratios/`, `llms/`, and the RepoLOTO check module. +- `tools/ai.sh` is the canonical VM coding-agent tmux launcher; `tools/install_ai.sh` installs the stable `~/.local/bin/ai` PATH wrapper. - The `llms/` package exists only to expose the stdlib `python -m llms.build` runner for `llms-build`. ## Layout @@ -53,7 +54,7 @@ llms/ # python -m llms.build reference runner | `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 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. | +| `gonol-build/` | procedural | — | UCNS gonol objects/constructors/geometry + Stack language-construction research discipline. Resolve the owning Stack workspace, preserve closure, atomic participation, occurrence identity, constitutive relations, provenance, and required replay; EDCM is measurement/evaluation only. | | `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. | diff --git a/README.md b/README.md index 5904a61..3b50f9f 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ into [`llms.txt`](llms.txt) from self-declared `LLMS` blocks. | [`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 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. | +| [`gonol-build/`](gonol-build/SKILL.md) | UCNS gonol objects/constructors/geometry + Stack language-construction research discipline. Preserves closure, atomic participation, exact source/occurrence identity, provenance, honest `hmmm`, and scoped replay; EDCM is measurement/evaluation only. 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. | @@ -133,6 +133,16 @@ python tools/build_codex_plugin_skills.py --apply python tools/build_codex_plugin_skills.py --check ``` +## VM coding-agent launcher + +The canonical `ai` tmux launcher lives at `tools/ai.sh`. Install a stable command in the user PATH without copying the implementation: + +```bash +bash tools/install_ai.sh +``` + +The installer creates `~/.local/bin/ai` pointing back to this checkout. `ai status` reports actual pane state, `ai restart deepcode` recreates/restarts DeepCode, and pane output persists under `~/.local/state/a0/logs`. Provider credentials remain owned by the provider CLIs/environment. + ## Maintenance tools Pure-stdlib helper scripts live in [`tools/`](tools/README.md). The small From 85e52ddf999d7b6b012a116573bba958d1cd85a0 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:04:49 -0700 Subject: [PATCH 17/36] chore: remove one-shot derived authority workflow --- .../workflows/repair-derived-authority.yml | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 .github/workflows/repair-derived-authority.yml diff --git a/.github/workflows/repair-derived-authority.yml b/.github/workflows/repair-derived-authority.yml deleted file mode 100644 index 810cc5f..0000000 --- a/.github/workflows/repair-derived-authority.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: repair-derived-authority - -on: - push: - branches: [repair/authority-and-ai-launcher] - paths: [.github/workflows/repair-derived-authority.yml] - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7.0.1 - with: - ref: repair/authority-and-ai-launcher - - name: Repair derived authority prose - shell: bash - run: | - python - <<'PY' - from pathlib import Path - - changes = { - "README.md": [ - ( - "| [`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. |", - "| [`gonol-build/`](gonol-build/SKILL.md) | UCNS gonol objects/constructors/geometry + Stack language-construction research discipline. Preserves closure, atomic participation, exact source/occurrence identity, provenance, honest `hmmm`, and scoped replay; EDCM is measurement/evaluation only. Independent of msdmd. |", - ), - ( - "## Maintenance tools\n\nPure-stdlib helper scripts live in [`tools/`](tools/README.md). The small\n`llms/` package exists only to provide the `python -m llms.build` command.\n", - "## VM coding-agent launcher\n\nThe canonical `ai` tmux launcher lives at `tools/ai.sh`. Install a stable command in the user PATH without copying the implementation:\n\n```bash\nbash tools/install_ai.sh\n```\n\nThe installer creates `~/.local/bin/ai` pointing back to this checkout. `ai status` reports actual pane state, `ai restart deepcode` recreates/restarts DeepCode, and pane output persists under `~/.local/state/a0/logs`. Provider credentials remain owned by the provider CLIs/environment.\n\n## Maintenance tools\n\nPure-stdlib helper scripts live in [`tools/`](tools/README.md). The small\n`llms/` package exists only to provide the `python -m llms.build` command.\n", - ), - ], - "CLAUDE.md": [ - ( - "| `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. |", - "| `gonol-build/` | procedural | — | UCNS gonol objects/constructors/geometry + Stack language-construction research discipline. Resolve the owning Stack workspace, preserve closure, atomic participation, occurrence identity, constitutive relations, provenance, and required replay; EDCM is measurement/evaluation only. |", - ), - ( - "- Validation here is editorial plus pure-stdlib helper scripts in `tools/`, `ratios/`, `llms/`, and the RepoLOTO check module.\n", - "- Validation here is editorial plus pure-stdlib helper scripts in `tools/`, `ratios/`, `llms/`, and the RepoLOTO check module.\n- `tools/ai.sh` is the canonical VM coding-agent tmux launcher; `tools/install_ai.sh` installs the stable `~/.local/bin/ai` PATH wrapper.\n", - ), - ], - } - - for filename, replacements in changes.items(): - path = Path(filename) - text = path.read_text(encoding="utf-8") - for old, new in replacements: - if old not in text: - raise SystemExit(f"expected text missing in {filename}: {old[:80]!r}") - text = text.replace(old, new, 1) - path.write_text(text, encoding="utf-8") - PY - - name: Commit derived repair - shell: bash - run: | - if git diff --quiet; then - exit 0 - fi - git config user.name "skill-lib repair" - git config user.email "actions@users.noreply.github.com" - git add README.md CLAUDE.md - git commit -m "docs: repair derived gonol authority and ai launcher [skip ci]" - git push origin HEAD:repair/authority-and-ai-launcher From b05bec3d61f69bba78aa6e4f20bb8b5dd5f8dd41 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:05:24 -0700 Subject: [PATCH 18/36] docs: repair gonol authority in agent entrypoint --- AGENTS.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 714cbc5..a17420d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,6 +51,8 @@ Read [`RESOURCE_RUN_INVARIANT.md`](RESOURCE_RUN_INVARIANT.md) before any compute /SKILL.md # required: the skill itself /... # optional: parsers, executors, examples llms/ # stdlib module for python -m llms.build +tools/ai.sh # canonical VM coding-agent tmux launcher +tools/install_ai.sh # installs ~/.local/bin/ai PATH wrapper ``` Every skill is a directory at the repo root containing at least a @@ -143,11 +145,13 @@ propagate from here. - If you are translating raw, recursive, fragmentary, coined, or private-language thought for strangers or a specific audience, load `thought-lens/SKILL.md`; freeze the claim kernel before changing vocabulary and back-check the result. -- 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 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 constructing, reviewing, replaying, or continuing language-gonol + research, including lexical floors, morphology, definitions, punctuation + functions, closure, atomic promotion, or recursive relations, load + `gonol-build/SKILL.md`. Resolve current UCNS gonol-object/constructor/geometry + authority and the exact owning Stack research workspace first. EDCM is + measurement/evaluation only; 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 `ucns-option-selection/SKILL.md`. Hard eligibility and evidence gates cannot @@ -189,3 +193,5 @@ propagate from here. - `llms.txt` — generated LLM-facing root instructions. - Each `/SKILL.md` — the authoritative skill spec. - `llms/build.py` — reference runner for `llms-build`. +- `tools/ai.sh` — canonical VM coding-agent launcher. +- `tools/install_ai.sh` — PATH installer for `~/.local/bin/ai`. From df1e0c37d8ef5b4b59e325d7e2a75ef149236b9c Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:05:44 -0700 Subject: [PATCH 19/36] test: widen gonol authority regression coverage --- tools/check_gonol_authority.sh | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/tools/check_gonol_authority.sh b/tools/check_gonol_authority.sh index 5396367..1b99042 100755 --- a/tools/check_gonol_authority.sh +++ b/tools/check_gonol_authority.sh @@ -5,11 +5,41 @@ set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" +active_files=( + gonol-build/SKILL.md + skills/gonol-build/SKILL.md + char-compress/SKILL.md + README.md + AGENTS.md + CLAUDE.md + ORG_DISTRIBUTION.md + skills.json + tests/test_gonol_build_skill.py + tests/test_char_compress_authority.py +) + grep -Fq 'UCNS = gonol objects, constructors, and underlying geometry' gonol-build/SKILL.md grep -Fq 'Stack = active language-gonol construction research workspaces' gonol-build/SKILL.md grep -Fq 'EDCM = measurement and evaluation of constructed outputs' gonol-build/SKILL.md -! grep -Fq 'EDCM = text-domain gonol construction' gonol-build/SKILL.md -! grep -Fq 'EDCM owns text-domain gonol construction' char-compress/SKILL.md +grep -Fq 'EDCM owns measurement/evaluation only' gonol-build/SKILL.md +grep -Fq 'research workspace in `The-Interdependency/stack`' char-compress/SKILL.md +grep -Fq 'EDCM owns measurement/evaluation only' char-compress/SKILL.md + +grep -Fq 'Stack language-construction research discipline' README.md +grep -Fq 'Stack language-construction research discipline' CLAUDE.md +grep -Fq 'exact owning Stack research workspace' AGENTS.md +grep -Fq 'Stack language-construction research' ORG_DISTRIBUTION.md + +for file in "${active_files[@]}"; do + if grep -Fq 'EDCM owns text-domain gonol construction' "$file"; then + printf 'FAIL: stale EDCM construction authority in %s\n' "$file" >&2 + exit 1 + fi + if grep -Fq 'UCNS geometry / EDCM text construction' "$file"; then + printf 'FAIL: stale UCNS/EDCM authority split in %s\n' "$file" >&2 + exit 1 + fi +done echo 'gonol authority: OK' # ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm From e70cbd206c28e10e7d8bb091f1fef013f3a47b91 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:08:27 -0700 Subject: [PATCH 20/36] fix: make ai.sh the canonical Termux-to-VM tmux launcher --- tools/ai.sh | 313 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 214 insertions(+), 99 deletions(-) diff --git a/tools/ai.sh b/tools/ai.sh index 6b86ea3..b13b608 100755 --- a/tools/ai.sh +++ b/tools/ai.sh @@ -1,4 +1,3 @@ -#!/usr/bin/env bash # ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm set -euo pipefail @@ -6,177 +5,293 @@ set -euo pipefail # id: skill_lib_ai_launcher # module_name: ai # module_kind: cli -# summary: canonical tmux launcher for coding-agent CLIs on the development VM with pane health, restart, and persistent pane logs +# summary: canonical Termux-side SSH/tmux launcher for coding-agent CLIs on the a0 development VM with health, restart, key propagation, and persistent remote pane logs # owner: skill-lib -# public_surface: ai start|attach|status|restart|logs|grok|codex|deepcode|shell -# internal_surface: tmux session/window lifecycle helpers -# auth_boundary: launched CLIs own their authentication -# storage_boundary: writes logs under ~/.local/state/a0/logs only -# network_boundary: none directly -# user_data_boundary: does not read or print provider credentials +# public_surface: ai.sh start|attach|status|restart|logs|keys|grok|codex|deepcode|shell +# internal_surface: remote bash quoting, tmux session/window lifecycle, key-to-tmux propagation +# auth_boundary: SSH host alias and third-party CLIs own authentication; launcher never prints key values +# storage_boundary: remote pane logs under ~/.local/state/a0/logs; no secret persistence +# network_boundary: SSH to configured VM host only +# user_data_boundary: provider key values are only copied from the VM login environment into the VM tmux server environment # admin_only: false # tests: tests/test_ai_launcher.py # rollout: explicit install via tools/install_ai.sh -# rollback: remove ~/.local/bin/ai wrapper -# requires: bash, tmux; optional grok/codex/deepcode CLIs +# rollback: remove installed ai.sh symlink; canonical source remains in skill-lib +# requires: local bash + ssh; remote bash + tmux; optional remote grok/codex/deepcodei CLIs # since: 2026-09-12 -# unresolved: host-local third-party CLI command names may change +# unresolved: third-party CLI executable names and provider authentication methods may change # === END MODULE_BUILD === +HOST="${A0_AI_HOST:-a0}" SESSION="${A0_AI_SESSION:-a0}" -STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}" -LOG_DIR="${A0_AI_LOG_DIR:-$STATE_HOME/a0/logs}" -SHELL_CMD="${A0_SHELL_CMD:-${SHELL:-/bin/bash} -l}" +REMOTE_LOG_SUBDIR="${A0_AI_REMOTE_LOG_SUBDIR:-.local/state/a0/logs}" GROK_CMD="${A0_GROK_CMD:-grok}" CODEX_CMD="${A0_CODEX_CMD:-codex --yolo}" -DEEPCODE_CMD="${A0_DEEPCODE_CMD:-deepcode}" -mkdir -p "$LOG_DIR" +DEEPCODE_CMD="${A0_DEEPCODE_CMD:-deepcodei}" +SHELL_CMD="${A0_SHELL_CMD:-exec \"\${SHELL:-/bin/bash}\" -l}" +KEY_VARS="${A0_AI_KEY_VARS:-OPENAI_API_KEY XAI_API_KEY DEEPSEEK_API_KEY ANTHROPIC_API_KEY}" usage() { cat <<'EOF' -usage: ai [start|attach|status|restart [agent|all]|logs [agent]|grok|codex|deepcode|shell|menu] +usage: ai.sh [command] + +commands: + start ensure a0 tmux session and expected windows exist + attach attach to the a0 tmux session + status | -list show expected windows and actual pane/process state + restart NAME restart grok, codex, deepcode, shell, or all + -restart NAME compatibility alias for restart + logs [NAME] tail persistent remote pane log (default: deepcode) + keys propagate VM login-shell provider keys into tmux; print presence only + grok | -grok ensure/select Grok and attach + codex | -codex ensure/select Codex and attach + deepcode|-deepcode|-deepcodei + ensure/select DeepCode and attach + shell ensure/select VM shell and attach + menu interactive selector (default) + +configuration: + A0_AI_HOST, A0_AI_SESSION, A0_GROK_CMD, A0_CODEX_CMD, + A0_DEEPCODE_CMD, A0_SHELL_CMD, A0_AI_KEY_VARS EOF } -require_tmux() { command -v tmux >/dev/null 2>&1 || { echo 'tmux is required' >&2; exit 127; }; } -has_session() { tmux has-session -t "$SESSION" 2>/dev/null; } -window_exists() { has_session && tmux list-windows -t "$SESSION" -F '#W' | grep -Fxq "$1"; } +q() { printf '%q' "$1"; } + +remote() { + local script="$1" + ssh "$HOST" "bash -lc $(q "$script")" +} + +remote_tty() { + local script="$1" + ssh -tt "$HOST" "bash -lc $(q "$script")" +} + +require_remote() { + if ! ssh -o BatchMode=yes -o ConnectTimeout=8 "$HOST" 'command -v tmux >/dev/null 2>&1'; then + printf 'ERROR: cannot reach %s non-interactively with remote tmux available\n' "$HOST" >&2 + return 1 + fi +} + +session_exists() { + remote "tmux has-session -t $(q "$SESSION") 2>/dev/null" +} + +window_exists() { + local name="$1" + session_exists && remote "tmux list-windows -t $(q "$SESSION") -F '#W' | grep -Fxq $(q "$name")" +} + +pane_dead() { + local name="$1" + remote "tmux display-message -p -t $(q "$SESSION:$name.0") '#{pane_dead}'" +} + +pipe_log() { + local name="$1" target="$SESSION:$1.0" command + command="cat >> \"\$HOME/$REMOTE_LOG_SUBDIR/$name.log\"" + remote "mkdir -p \"\$HOME/$REMOTE_LOG_SUBDIR\"; tmux pipe-pane -o -t $(q "$target") $(q "$command")" +} + +sync_keys() { + session_exists || return 0 + local script + script="for key in $KEY_VARS; do value=\"\${!key-}\"; if [[ -n \"\$value\" ]]; then tmux set-environment -t $(q "$SESSION") \"\$key\" \"\$value\"; fi; done" + remote "$script" +} + +keys_status() { + ensure_session + sync_keys + local script + script="for key in $KEY_VARS; do if tmux show-environment -t $(q "$SESSION") \"\$key\" >/dev/null 2>&1; then printf '%-18s present\\n' \"\$key\"; else printf '%-18s missing\\n' \"\$key\"; fi; done" + remote "$script" +} ensure_session() { - require_tmux - has_session || tmux new-session -d -s "$SESSION" -n bash + require_remote + if ! session_exists; then + remote "tmux new-session -d -s $(q "$SESSION") -n shell" + fi + remote "tmux set-option -w -t $(q "$SESSION:shell") remain-on-exit on 2>/dev/null || true; mkdir -p \"\$HOME/$REMOTE_LOG_SUBDIR\"" + pipe_log shell || true + sync_keys || true +} + +spec() { + case "$1" in + shell) printf '0|shell|%s\n' "$SHELL_CMD" ;; + grok) printf '1|grok|%s\n' "$GROK_CMD" ;; + codex) printf '2|codex|%s\n' "$CODEX_CMD" ;; + deepcode) printf '3|deepcode|%s\n' "$DEEPCODE_CMD" ;; + *) return 2 ;; + esac } -ensure_window() { +ensure_window_shell() { local index="$1" name="$2" ensure_session - if ! window_exists "$name"; then - if tmux list-windows -t "$SESSION" -F '#I' | grep -Fxq "$index"; then - tmux new-window -d -t "$SESSION" -n "$name" - else - tmux new-window -d -t "$SESSION:$index" -n "$name" - fi + if window_exists "$name"; then + remote "tmux set-option -w -t $(q "$SESSION:$name") remain-on-exit on" + pipe_log "$name" || true + return 0 fi - tmux set-option -w -t "$SESSION:$name" remain-on-exit on >/dev/null -} -pipe_log() { - local name="$1" file="$LOG_DIR/$1.log" quoted - quoted="$(printf '%q' "$file")" - tmux pipe-pane -o -t "$SESSION:$name.0" "cat >> $quoted" + local occupied + occupied="$(remote "tmux list-windows -t $(q "$SESSION") -F '#I:#W' | grep '^${index}:' || true")" + if [[ -n "$occupied" ]]; then + printf 'ERROR: expected window %s at index %s, but %s occupies it\n' "$name" "$index" "$occupied" >&2 + return 3 + fi + remote "tmux new-window -d -t $(q "$SESSION:$index") -n $(q "$name")" + remote "tmux set-option -w -t $(q "$SESSION:$name") remain-on-exit on" + pipe_log "$name" || true } -launch() { - local index="$1" name="$2" command_line="$3" binary quoted - ensure_window "$index" "$name" +respawn() { + local name="$1" command_line="$2" binary pane_command binary="${command_line%% *}" - pipe_log "$name" - if ! command -v "$binary" >/dev/null 2>&1; then - printf 'command unavailable: %s\n' "$binary" >&2 + if ! remote "command -v $(q "$binary") >/dev/null 2>&1"; then + printf 'ERROR: %s is not installed on %s\n' "$binary" "$HOST" >&2 return 127 fi - quoted="$(printf '%q' "$command_line")" - tmux respawn-pane -k -t "$SESSION:$name.0" "exec bash -lc $quoted" - pipe_log "$name" + sync_keys || true + pane_command="exec bash -lc $(q "$command_line")" + remote "tmux respawn-pane -k -t $(q "$SESSION:$name.0") $(q "$pane_command")" + pipe_log "$name" || true } -ensure_shell() { - ensure_window 2 bash - pipe_log bash +ensure_agent() { + local agent="$1" row index name command_line dead + row="$(spec "$agent")" + IFS='|' read -r index name command_line <<<"$row" + ensure_window_shell "$index" "$name" + dead="$(pane_dead "$name")" + if [[ "$agent" != shell && "$dead" == 1 ]]; then + respawn "$name" "$command_line" + fi } start_all() { - ensure_session - launch 0 grok-4-fast "$GROK_CMD" || true - launch 1 codex "$CODEX_CMD" || true - ensure_shell - launch 3 deepcode "$DEEPCODE_CMD" || true -} - -status() { - require_tmux - has_session || { printf 'session %s missing\n' "$SESSION"; return 1; } - tmux list-panes -a -t "$SESSION" -F '#{window_index}\t#{window_name}\tdead=#{pane_dead}\tpid=#{pane_pid}\tcommand=#{pane_current_command}' | sort -n + ensure_window_shell 0 shell + ensure_agent grok || true + ensure_agent codex || true + ensure_agent deepcode || true } restart_one() { - case "$1" in - grok|grok-4-fast) launch 0 grok-4-fast "$GROK_CMD" ;; - codex) launch 1 codex "$CODEX_CMD" ;; - deepcode) launch 3 deepcode "$DEEPCODE_CMD" ;; - shell|bash) launch 2 bash "$SHELL_CMD" ;; - *) printf 'unknown target: %s\n' "$1" >&2; return 2 ;; - esac + local agent="$1" row index name command_line + row="$(spec "$agent")" || { + printf 'ERROR: unknown restart target: %s\n' "$agent" >&2 + return 2 + } + IFS='|' read -r index name command_line <<<"$row" + ensure_window_shell "$index" "$name" + if [[ "$agent" == shell ]]; then + local pane_command + pane_command="exec bash -lc $(q "$command_line")" + remote "tmux respawn-pane -k -t $(q "$SESSION:$name.0") $(q "$pane_command")" + pipe_log "$name" || true + else + respawn "$name" "$command_line" + fi } restart() { local target="${1:-all}" - if [[ "$target" == all ]]; then - restart_one grok || true - restart_one codex || true - restart_one shell || true - restart_one deepcode || true - else - restart_one "$target" + case "$target" in + all) + restart_one shell || true + restart_one grok || true + restart_one codex || true + restart_one deepcode || true + ;; + grok|codex|deepcode|shell) restart_one "$target" ;; + *) printf 'ERROR: restart target must be grok, codex, deepcode, shell, or all\n' >&2; return 2 ;; + esac +} + +status() { + require_remote + if ! session_exists; then + printf 'session %-12s missing on %s\n' "$SESSION" "$HOST" + return 1 fi + remote "tmux list-panes -s -t $(q "$SESSION") -F '#{window_index}\\t#{window_name}\\tdead=#{pane_dead}\\tpid=#{pane_pid}\\tcommand=#{pane_current_command}' | sort -n" } attach_window() { local name="$1" - if [[ -n "${TMUX-}" ]]; then - tmux switch-client -t "$SESSION:$name" - else - tmux select-window -t "$SESSION:$name" - exec tmux attach-session -t "$SESSION" - fi + remote_tty "tmux select-window -t $(q "$SESSION:$name") && exec tmux attach-session -t $(q "$SESSION")" } open_agent() { - local name="$1" - case "$name" in - grok|grok-4-fast) window_exists grok-4-fast || restart_one grok || true; attach_window grok-4-fast ;; - codex) window_exists codex || restart_one codex || true; attach_window codex ;; - deepcode) window_exists deepcode || restart_one deepcode || true; attach_window deepcode ;; - shell|bash) window_exists bash || ensure_shell; attach_window bash ;; - esac + local agent="$1" row index name command_line dead + row="$(spec "$agent")" + IFS='|' read -r index name command_line <<<"$row" + ensure_window_shell "$index" "$name" + dead="$(pane_dead "$name")" + if [[ "$agent" != shell && "$dead" == 1 ]]; then + respawn "$name" "$command_line" + fi + attach_window "$name" } logs() { - local name="${1:-deepcode}" file="$LOG_DIR/${1:-deepcode}.log" - [[ -f "$file" ]] || { printf 'no log yet: %s\n' "$file"; return 1; } - tail -n "${A0_AI_LOG_LINES:-200}" "$file" + local name="${1:-deepcode}" + case "$name" in shell|grok|codex|deepcode) ;; *) printf 'ERROR: unknown log: %s\n' "$name" >&2; return 2 ;; esac + ensure_session + remote "file=\"\$HOME/$REMOTE_LOG_SUBDIR/$name.log\"; if [[ -f \"\$file\" ]]; then tail -n ${A0_AI_LOG_LINES:-200} \"\$file\"; else printf 'no log yet: %s\\n' \"\$file\"; exit 1; fi" } menu() { ensure_session while true; do - printf '\n1 Grok 2 Codex 3 DeepCode 4 Shell 5 Status 6 Restart 7 Logs 8 Start/repair all 0 Exit\n' + cat <<'EOF' + +AI on a0: + 1) Grok + 2) Codex + 3) DeepCode + 4) Shell + 5) Keys + 6) Status + 7) Restart + 8) Logs + 0) Quit +EOF read -r -p '> ' choice case "$choice" in 1) open_agent grok ;; 2) open_agent codex ;; 3) open_agent deepcode ;; 4) open_agent shell ;; - 5) status || true ;; - 6) read -r -p 'restart [grok/codex/deepcode/shell/all]: ' target; restart "${target:-all}" || true ;; - 7) read -r -p 'log [deepcode/codex/grok-4-fast/bash]: ' target; logs "${target:-deepcode}" || true ;; - 8) start_all ;; - 0) return ;; - *) echo 'unknown choice' ;; + 5) keys_status ;; + 6) status || true ;; + 7) read -r -p 'restart [grok/codex/deepcode/shell/all]: ' target; restart "${target:-all}" || true ;; + 8) read -r -p 'log [deepcode/codex/grok/shell]: ' target; logs "${target:-deepcode}" || true ;; + 0) return 0 ;; + *) printf 'unknown choice\n' ;; esac done } case "${1:-menu}" in start) start_all ;; - attach) ensure_session; exec tmux attach-session -t "$SESSION" ;; - status) status ;; + attach) ensure_session; remote_tty "exec tmux attach-session -t $(q "$SESSION")" ;; + status|-list) status ;; restart) shift; restart "${1:-all}" ;; + -restart) shift; restart "${1:-all}" ;; logs) shift; logs "${1:-deepcode}" ;; - grok|grok-4-fast|codex|deepcode|shell|bash) ensure_session; open_agent "$1" ;; + keys) keys_status ;; + grok|-grok) open_agent grok ;; + codex|-codex) open_agent codex ;; + deepcode|-deepcode|-deepcodei) open_agent deepcode ;; + shell) open_agent shell ;; menu) menu ;; -h|--help|help) usage ;; *) usage >&2; exit 2 ;; esac - # ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm From 7672022437668a1cd6b2311f0e30d2d96e672e2c Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:09:08 -0700 Subject: [PATCH 21/36] fix: launch missing agent windows and harden key propagation --- tools/ai.sh | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/ai.sh b/tools/ai.sh index b13b608..136523a 100755 --- a/tools/ai.sh +++ b/tools/ai.sh @@ -98,7 +98,7 @@ pipe_log() { sync_keys() { session_exists || return 0 local script - script="for key in $KEY_VARS; do value=\"\${!key-}\"; if [[ -n \"\$value\" ]]; then tmux set-environment -t $(q "$SESSION") \"\$key\" \"\$value\"; fi; done" + script="for key in $KEY_VARS; do value=\"\$(printenv \"\$key\" 2>/dev/null || true)\"; if [[ -n \"\$value\" ]]; then tmux set-environment -t $(q "$SESSION") \"\$key\" \"\$value\"; fi; done" remote "$script" } @@ -164,12 +164,15 @@ respawn() { } ensure_agent() { - local agent="$1" row index name command_line dead + local agent="$1" row index name command_line dead existed=0 row="$(spec "$agent")" IFS='|' read -r index name command_line <<<"$row" + if window_exists "$name"; then + existed=1 + fi ensure_window_shell "$index" "$name" dead="$(pane_dead "$name")" - if [[ "$agent" != shell && "$dead" == 1 ]]; then + if [[ "$existed" == 0 || "$dead" == 1 ]]; then respawn "$name" "$command_line" fi } @@ -228,12 +231,15 @@ attach_window() { } open_agent() { - local agent="$1" row index name command_line dead + local agent="$1" row index name command_line dead existed=0 row="$(spec "$agent")" IFS='|' read -r index name command_line <<<"$row" + if window_exists "$name"; then + existed=1 + fi ensure_window_shell "$index" "$name" dead="$(pane_dead "$name")" - if [[ "$agent" != shell && "$dead" == 1 ]]; then + if [[ "$agent" != shell && ( "$existed" == 0 || "$dead" == 1 ) ]]; then respawn "$name" "$command_line" fi attach_window "$name" From 807f7d0a03b91a184cc3f1fcd26068b63c9b6f65 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:09:28 -0700 Subject: [PATCH 22/36] fix: install canonical ai.sh directly into the Termux PATH --- tools/install_ai.sh | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/tools/install_ai.sh b/tools/install_ai.sh index 1ca741c..3b6a788 100755 --- a/tools/install_ai.sh +++ b/tools/install_ai.sh @@ -6,52 +6,53 @@ set -euo pipefail # id: skill_lib_ai_installer # module_name: install_ai # module_kind: installer -# summary: installs a stable PATH wrapper that executes the canonical skill-lib tools/ai.sh in place +# summary: installs the canonical skill-lib tools/ai.sh into the caller's PATH, preferring Termux $PREFIX/bin and otherwise ~/.local/bin # owner: skill-lib # public_surface: bash tools/install_ai.sh -# internal_surface: none +# internal_surface: PATH target selection and symlink installation # auth_boundary: none -# storage_boundary: writes ~/.local/bin/ai and an idempotent ~/.profile PATH line +# storage_boundary: writes one ai.sh symlink and, outside an already-on-PATH bin directory, one idempotent ~/.profile PATH line # network_boundary: none # user_data_boundary: no credentials read or written # admin_only: false # tests: tests/test_ai_launcher.py # rollout: explicit user invocation -# rollback: rm ~/.local/bin/ai and remove the marked PATH line if undesired +# rollback: remove the installed ai.sh symlink and marked PATH line if one was added # requires: bash # since: 2026-09-12 -# unresolved: current shell cannot inherit PATH changes from a child process; reopen shell or source ~/.profile +# unresolved: a current shell cannot inherit a newly appended PATH line from a child process # === END MODULE_BUILD === SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SOURCE="$SOURCE_DIR/ai.sh" -BIN_DIR="${A0_AI_BIN_DIR:-$HOME/.local/bin}" -TARGET="$BIN_DIR/ai" PROFILE="${A0_AI_PROFILE:-$HOME/.profile}" -PATH_LINE='export PATH="$HOME/.local/bin:$PATH" # skill-lib ai launcher' -[[ -f "$SOURCE" ]] || { printf 'ERROR: canonical launcher missing: %s\n' "$SOURCE" >&2; exit 2; } -mkdir -p "$BIN_DIR" "${XDG_STATE_HOME:-$HOME/.local/state}/a0/logs" +if [[ -n "${A0_AI_BIN_DIR:-}" ]]; then + BIN_DIR="$A0_AI_BIN_DIR" +elif [[ -n "${PREFIX:-}" && -d "$PREFIX/bin" && -w "$PREFIX/bin" ]]; then + BIN_DIR="$PREFIX/bin" +else + BIN_DIR="$HOME/.local/bin" +fi -cat > "$TARGET" <&2; exit 2; } +mkdir -p "$BIN_DIR" +chmod 0755 "$SOURCE" +ln -sfn "$SOURCE" "$TARGET" if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then + mkdir -p "$(dirname "$PROFILE")" touch "$PROFILE" - if ! grep -Fqx "$PATH_LINE" "$PROFILE"; then - printf '\n%s\n' "$PATH_LINE" >> "$PROFILE" + path_line="export PATH=\"$BIN_DIR:\$PATH\" # skill-lib ai launcher" + if ! grep -Fqx "$path_line" "$PROFILE"; then + printf '\n%s\n' "$path_line" >> "$PROFILE" fi -fi - -printf 'installed: %s\n' "$TARGET" -printf 'source: %s\n' "$SOURCE" -if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then printf 'PATH updated for future login shells in %s\n' "$PROFILE" - printf 'for this shell: export PATH="$HOME/.local/bin:$PATH"\n' + printf 'for this shell: export PATH=%q:\$PATH\n' "$BIN_DIR" fi -"$TARGET" --help + +printf 'installed: %s -> %s\n' "$TARGET" "$SOURCE" +bash "$TARGET" --help # ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm From 957cb2550e93cd6eaeaf98c5b8cee10d5f598c34 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:09:48 -0700 Subject: [PATCH 23/36] test: pin Termux-to-VM ai launcher contract --- tests/test_ai_launcher.py | 63 ++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/tests/test_ai_launcher.py b/tests/test_ai_launcher.py index 09827ea..9c5810d 100644 --- a/tests/test_ai_launcher.py +++ b/tests/test_ai_launcher.py @@ -7,48 +7,77 @@ ROOT = Path(__file__).resolve().parents[1] LAUNCHER = ROOT / "tools" / "ai.sh" INSTALLER = ROOT / "tools" / "install_ai.sh" +RATIO = "# ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm" class AILauncherTests(unittest.TestCase): - def test_launcher_is_canonical_tmux_surface(self) -> None: + def test_launcher_keeps_ratio_seals_as_literal_boundaries(self) -> None: + lines = LAUNCHER.read_text(encoding="utf-8").splitlines() + self.assertEqual(lines[0], RATIO) + self.assertEqual(lines[-1], RATIO) + self.assertFalse(lines[0].startswith("#!")) + + def test_launcher_is_termux_side_remote_tmux_controller(self) -> None: text = LAUNCHER.read_text(encoding="utf-8") for phrase in ( + 'HOST="${A0_AI_HOST:-a0}"', 'SESSION="${A0_AI_SESSION:-a0}"', - 'CODEX_CMD="${A0_CODEX_CMD:-codex --yolo}"', - 'DEEPCODE_CMD="${A0_DEEPCODE_CMD:-deepcode}"', + 'ssh "$HOST"', + 'ssh -tt "$HOST"', "remain-on-exit on", "tmux pipe-pane", "#{pane_dead}", "#{pane_current_command}", "tmux respawn-pane -k", - 'LOG_DIR="${A0_AI_LOG_DIR:-$STATE_HOME/a0/logs}"', + ".local/state/a0/logs", + ): + self.assertIn(phrase, text) + + def test_expected_vm_window_layout_and_commands_are_pinned(self) -> None: + text = LAUNCHER.read_text(encoding="utf-8") + for phrase in ( + "shell) printf '0|shell|%s", + "grok) printf '1|grok|%s", + "codex) printf '2|codex|%s", + "deepcode) printf '3|deepcode|%s", + 'GROK_CMD="${A0_GROK_CMD:-grok}"', + 'CODEX_CMD="${A0_CODEX_CMD:-codex --yolo}"', + 'DEEPCODE_CMD="${A0_DEEPCODE_CMD:-deepcodei}"', ): self.assertIn(phrase, text) - def test_launcher_does_not_manage_provider_secrets(self) -> None: + def test_start_repairs_missing_or_dead_agents_without_restarting_healthy_ones(self) -> None: text = LAUNCHER.read_text(encoding="utf-8") - for secret_name in ( + self.assertIn('if window_exists "$name"; then', text) + self.assertIn('if [[ "$existed" == 0 || "$dead" == 1 ]]; then', text) + self.assertIn('respawn "$name" "$command_line"', text) + + def test_keys_only_propagate_existing_vm_environment_into_tmux(self) -> None: + text = LAUNCHER.read_text(encoding="utf-8") + for phrase in ( "OPENAI_API_KEY", + "XAI_API_KEY", "DEEPSEEK_API_KEY", "ANTHROPIC_API_KEY", - "XAI_API_KEY", + "printenv", + "tmux set-environment", + "present", + "missing", ): - self.assertNotIn(secret_name, text) + self.assertIn(phrase, text) + self.assertNotIn("read -s", text) + self.assertNotIn("KEY=", text) - def test_installer_places_stable_ai_command_on_user_path(self) -> None: + def test_installer_places_ai_sh_on_termux_path_without_copying(self) -> None: text = INSTALLER.read_text(encoding="utf-8") for phrase in ( - '$HOME/.local/bin', - 'TARGET="$BIN_DIR/ai"', - 'exec bash', + '$PREFIX/bin', + 'TARGET="$BIN_DIR/ai.sh"', + 'SOURCE="$SOURCE_DIR/ai.sh"', + 'ln -sfn "$SOURCE" "$TARGET"', 'skill-lib ai launcher', - 'chmod 0755 "$TARGET"', ): self.assertIn(phrase, text) - - def test_installer_executes_repo_source_instead_of_copying_it(self) -> None: - text = INSTALLER.read_text(encoding="utf-8") - self.assertIn('SOURCE="$SOURCE_DIR/ai.sh"', text) self.assertNotIn('cp "$SOURCE" "$TARGET"', text) From cd26f53a2774219d94d4579f5f831606bd25cd94 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:10:11 -0700 Subject: [PATCH 24/36] test: syntax-check ai launcher scripts --- tests/test_ai_launcher.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_ai_launcher.py b/tests/test_ai_launcher.py index 9c5810d..e507be5 100644 --- a/tests/test_ai_launcher.py +++ b/tests/test_ai_launcher.py @@ -1,6 +1,7 @@ from __future__ import annotations from pathlib import Path +import subprocess import unittest @@ -11,6 +12,10 @@ class AILauncherTests(unittest.TestCase): + def test_shell_syntax(self) -> None: + for script in (LAUNCHER, INSTALLER): + subprocess.run(["bash", "-n", str(script)], check=True) + def test_launcher_keeps_ratio_seals_as_literal_boundaries(self) -> None: lines = LAUNCHER.read_text(encoding="utf-8").splitlines() self.assertEqual(lines[0], RATIO) From ddee738ca1cd47c0a7850516a37380b65fec42e7 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:11:09 -0700 Subject: [PATCH 25/36] chore: add one-shot ai launcher documentation repair --- .github/workflows/repair-ai-docs.yml | 97 ++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 .github/workflows/repair-ai-docs.yml diff --git a/.github/workflows/repair-ai-docs.yml b/.github/workflows/repair-ai-docs.yml new file mode 100644 index 0000000..e42f48d --- /dev/null +++ b/.github/workflows/repair-ai-docs.yml @@ -0,0 +1,97 @@ +name: repair-ai-docs + +on: + push: + branches: [repair/authority-and-ai-launcher] + paths: [.github/workflows/repair-ai-docs.yml] + +permissions: + contents: write + +jobs: + repair: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7.0.1 + with: + ref: repair/authority-and-ai-launcher + - name: Repair ai launcher documentation + shell: bash + run: | + python - <<'PY' + from pathlib import Path + + replacements = { + "README.md": [ + ( + "The canonical `ai` tmux launcher lives at `tools/ai.sh`. Install a stable command in the user PATH without copying the implementation:", + "The canonical `ai.sh` launcher lives at `tools/ai.sh`. It runs on Termux, reaches the `a0` VM through the SSH host alias `a0`, and manages the remote `a0` tmux session. Install it into the caller's PATH without copying the implementation:", + ), + ( + "The installer creates `~/.local/bin/ai` pointing back to this checkout. `ai status` reports actual pane state, `ai restart deepcode` recreates/restarts DeepCode, and pane output persists under `~/.local/state/a0/logs`. Provider credentials remain owned by the provider CLIs/environment.", + "On Termux the installer symlinks `ai.sh` into `$PREFIX/bin`; elsewhere it falls back to `~/.local/bin/ai.sh`. `ai.sh status` reports remote pane state, `ai.sh restart deepcode` repairs a missing/dead DeepCode window, and pane output persists on the VM under `~/.local/state/a0/logs`. `ai.sh keys` only propagates already-present VM login-environment keys into tmux and reports presence/missing, never values.", + ), + ], + "CLAUDE.md": [ + ( + "- `tools/ai.sh` is the canonical VM coding-agent tmux launcher; `tools/install_ai.sh` installs the stable `~/.local/bin/ai` PATH wrapper.", + "- `tools/ai.sh` is the canonical Termux-side SSH/tmux launcher for the `a0` VM; `tools/install_ai.sh` installs `ai.sh` into the caller's PATH (Termux `$PREFIX/bin`, otherwise `~/.local/bin`).", + ), + ], + "AGENTS.md": [ + ( + "tools/ai.sh # canonical VM coding-agent tmux launcher\ntools/install_ai.sh # installs ~/.local/bin/ai PATH wrapper", + "tools/ai.sh # canonical Termux -> a0 SSH/tmux coding-agent launcher\ntools/install_ai.sh # installs ai.sh into caller PATH (Termux $PREFIX/bin first)", + ), + ( + "- `tools/ai.sh` — canonical VM coding-agent launcher.\n- `tools/install_ai.sh` — PATH installer for `~/.local/bin/ai`.", + "- `tools/ai.sh` — canonical Termux-side launcher for the remote a0 tmux coding-agent session.\n- `tools/install_ai.sh` — installs `ai.sh` into caller PATH, preferring Termux `$PREFIX/bin`.", + ), + ], + "tools/README.md": [ + ("## Canonical `ai` launcher", "## Canonical `ai.sh` launcher"), + ( + "`tools/ai.sh` is the canonical VM coding-agent launcher. It owns the `a0` tmux\nsession layout, real pane/process status, restart, `remain-on-exit`, and\npersistent pane logs under `~/.local/state/a0/logs`.", + "`tools/ai.sh` is the canonical Termux-side launcher for the coding-agent CLIs on the `a0` VM. It uses the SSH host alias `a0` and owns the remote tmux session layout (`0:shell`, `1:grok`, `2:codex`, `3:deepcode`), real pane/process status, restart, `remain-on-exit`, and persistent VM logs under `~/.local/state/a0/logs`.", + ), + ("Install the stable `ai` command into the user PATH:", "Install the stable `ai.sh` command into the caller PATH:"), + ( + "The installer creates `~/.local/bin/ai` as a wrapper pointing back to the\ncanonical `tools/ai.sh`; it does not copy a second implementation. If\n`~/.local/bin` is absent from PATH it adds one idempotent login-shell line to\n`~/.profile`.", + "On Termux the installer symlinks the canonical source to `$PREFIX/bin/ai.sh`, which is already on PATH. Elsewhere it uses `~/.local/bin/ai.sh` and adds one idempotent login-shell PATH line only when required. No second launcher implementation is copied.", + ), + ("ai\nai status\nai restart deepcode\nai logs deepcode\nai codex", "ai.sh\nai.sh status\nai.sh restart deepcode\nai.sh logs deepcode\nai.sh codex"), + ( + "Provider credentials remain the responsibility of the installed provider CLIs\nand VM environment. The launcher does not read, print, or become a key vault.", + "Provider credentials remain the responsibility of the VM/provider CLIs. `ai.sh keys` only copies already-present VM login-environment values into the remote tmux environment so restarted CLIs can see them; it prints only `present`/`missing` and never stores or displays key values.", + ), + ], + "skill-lib_msdmd.ts": [ + ( + 'summary: "Canonical tmux launcher for coding-agent CLIs with pane health, restart, remain-on-exit, and persistent logs",', + 'summary: "Canonical Termux-side SSH/tmux launcher for a0 VM coding-agent CLIs with pane health, restart, key propagation, remain-on-exit, and persistent remote logs",', + ), + ( + 'summary: "Installs the skill-lib ai launcher as ~/.local/bin/ai and ensures the user PATH contains ~/.local/bin",', + 'summary: "Installs canonical ai.sh into caller PATH, preferring Termux $PREFIX/bin and otherwise ~/.local/bin",', + ), + ], + } + + for filename, pairs in replacements.items(): + path = Path(filename) + text = path.read_text(encoding="utf-8") + for old, new in pairs: + if old not in text: + raise SystemExit(f"expected text missing in {filename}: {old[:100]!r}") + text = text.replace(old, new, 1) + path.write_text(text, encoding="utf-8") + PY + - name: Commit docs repair + shell: bash + run: | + if git diff --quiet; then exit 0; fi + git config user.name "skill-lib repair" + git config user.email "actions@users.noreply.github.com" + git add README.md CLAUDE.md AGENTS.md tools/README.md skill-lib_msdmd.ts + git commit -m "docs: align ai.sh with Termux-to-VM launcher [skip ci]" + git push origin HEAD:repair/authority-and-ai-launcher From 9e92b4e2d488426b38c9c680276cd72e46581611 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:12:33 -0700 Subject: [PATCH 26/36] docs: declare gonol authority checker module --- tools/check_gonol_authority.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/check_gonol_authority.sh b/tools/check_gonol_authority.sh index 1b99042..b7727e7 100755 --- a/tools/check_gonol_authority.sh +++ b/tools/check_gonol_authority.sh @@ -2,6 +2,27 @@ # ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm set -euo pipefail +# === MODULE_BUILD === +# id: gonol_authority_gate +# module_name: check_gonol_authority +# module_kind: checker +# summary: fail-closed local regression gate for UCNS/Stack/EDCM gonol authority across active skill-lib surfaces +# owner: skill-lib +# public_surface: bash tools/check_gonol_authority.sh +# internal_surface: active_files +# auth_boundary: none +# storage_boundary: read-only repository files +# network_boundary: none +# user_data_boundary: none +# admin_only: false +# tests: tests/test_gonol_build_skill.py, tests/test_char_compress_authority.py +# rollout: skill-lib CI gate +# rollback: revert only with an explicit authority change and matching doctrine update +# requires: gonol-build/SKILL.md, char-compress/SKILL.md, active skill-lib projections +# since: 2026-09-12 +# unresolved: cross-repository authority truth is validated by each owning repository and Stack consistency gates +# === END MODULE_BUILD === + ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" From a2ff7745e19ee66d8eb8cd2fd970864bb0f994d9 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:13:16 -0700 Subject: [PATCH 27/36] chore: remove one-shot ai documentation workflow --- .github/workflows/repair-ai-docs.yml | 97 ---------------------------- 1 file changed, 97 deletions(-) delete mode 100644 .github/workflows/repair-ai-docs.yml diff --git a/.github/workflows/repair-ai-docs.yml b/.github/workflows/repair-ai-docs.yml deleted file mode 100644 index e42f48d..0000000 --- a/.github/workflows/repair-ai-docs.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: repair-ai-docs - -on: - push: - branches: [repair/authority-and-ai-launcher] - paths: [.github/workflows/repair-ai-docs.yml] - -permissions: - contents: write - -jobs: - repair: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7.0.1 - with: - ref: repair/authority-and-ai-launcher - - name: Repair ai launcher documentation - shell: bash - run: | - python - <<'PY' - from pathlib import Path - - replacements = { - "README.md": [ - ( - "The canonical `ai` tmux launcher lives at `tools/ai.sh`. Install a stable command in the user PATH without copying the implementation:", - "The canonical `ai.sh` launcher lives at `tools/ai.sh`. It runs on Termux, reaches the `a0` VM through the SSH host alias `a0`, and manages the remote `a0` tmux session. Install it into the caller's PATH without copying the implementation:", - ), - ( - "The installer creates `~/.local/bin/ai` pointing back to this checkout. `ai status` reports actual pane state, `ai restart deepcode` recreates/restarts DeepCode, and pane output persists under `~/.local/state/a0/logs`. Provider credentials remain owned by the provider CLIs/environment.", - "On Termux the installer symlinks `ai.sh` into `$PREFIX/bin`; elsewhere it falls back to `~/.local/bin/ai.sh`. `ai.sh status` reports remote pane state, `ai.sh restart deepcode` repairs a missing/dead DeepCode window, and pane output persists on the VM under `~/.local/state/a0/logs`. `ai.sh keys` only propagates already-present VM login-environment keys into tmux and reports presence/missing, never values.", - ), - ], - "CLAUDE.md": [ - ( - "- `tools/ai.sh` is the canonical VM coding-agent tmux launcher; `tools/install_ai.sh` installs the stable `~/.local/bin/ai` PATH wrapper.", - "- `tools/ai.sh` is the canonical Termux-side SSH/tmux launcher for the `a0` VM; `tools/install_ai.sh` installs `ai.sh` into the caller's PATH (Termux `$PREFIX/bin`, otherwise `~/.local/bin`).", - ), - ], - "AGENTS.md": [ - ( - "tools/ai.sh # canonical VM coding-agent tmux launcher\ntools/install_ai.sh # installs ~/.local/bin/ai PATH wrapper", - "tools/ai.sh # canonical Termux -> a0 SSH/tmux coding-agent launcher\ntools/install_ai.sh # installs ai.sh into caller PATH (Termux $PREFIX/bin first)", - ), - ( - "- `tools/ai.sh` — canonical VM coding-agent launcher.\n- `tools/install_ai.sh` — PATH installer for `~/.local/bin/ai`.", - "- `tools/ai.sh` — canonical Termux-side launcher for the remote a0 tmux coding-agent session.\n- `tools/install_ai.sh` — installs `ai.sh` into caller PATH, preferring Termux `$PREFIX/bin`.", - ), - ], - "tools/README.md": [ - ("## Canonical `ai` launcher", "## Canonical `ai.sh` launcher"), - ( - "`tools/ai.sh` is the canonical VM coding-agent launcher. It owns the `a0` tmux\nsession layout, real pane/process status, restart, `remain-on-exit`, and\npersistent pane logs under `~/.local/state/a0/logs`.", - "`tools/ai.sh` is the canonical Termux-side launcher for the coding-agent CLIs on the `a0` VM. It uses the SSH host alias `a0` and owns the remote tmux session layout (`0:shell`, `1:grok`, `2:codex`, `3:deepcode`), real pane/process status, restart, `remain-on-exit`, and persistent VM logs under `~/.local/state/a0/logs`.", - ), - ("Install the stable `ai` command into the user PATH:", "Install the stable `ai.sh` command into the caller PATH:"), - ( - "The installer creates `~/.local/bin/ai` as a wrapper pointing back to the\ncanonical `tools/ai.sh`; it does not copy a second implementation. If\n`~/.local/bin` is absent from PATH it adds one idempotent login-shell line to\n`~/.profile`.", - "On Termux the installer symlinks the canonical source to `$PREFIX/bin/ai.sh`, which is already on PATH. Elsewhere it uses `~/.local/bin/ai.sh` and adds one idempotent login-shell PATH line only when required. No second launcher implementation is copied.", - ), - ("ai\nai status\nai restart deepcode\nai logs deepcode\nai codex", "ai.sh\nai.sh status\nai.sh restart deepcode\nai.sh logs deepcode\nai.sh codex"), - ( - "Provider credentials remain the responsibility of the installed provider CLIs\nand VM environment. The launcher does not read, print, or become a key vault.", - "Provider credentials remain the responsibility of the VM/provider CLIs. `ai.sh keys` only copies already-present VM login-environment values into the remote tmux environment so restarted CLIs can see them; it prints only `present`/`missing` and never stores or displays key values.", - ), - ], - "skill-lib_msdmd.ts": [ - ( - 'summary: "Canonical tmux launcher for coding-agent CLIs with pane health, restart, remain-on-exit, and persistent logs",', - 'summary: "Canonical Termux-side SSH/tmux launcher for a0 VM coding-agent CLIs with pane health, restart, key propagation, remain-on-exit, and persistent remote logs",', - ), - ( - 'summary: "Installs the skill-lib ai launcher as ~/.local/bin/ai and ensures the user PATH contains ~/.local/bin",', - 'summary: "Installs canonical ai.sh into caller PATH, preferring Termux $PREFIX/bin and otherwise ~/.local/bin",', - ), - ], - } - - for filename, pairs in replacements.items(): - path = Path(filename) - text = path.read_text(encoding="utf-8") - for old, new in pairs: - if old not in text: - raise SystemExit(f"expected text missing in {filename}: {old[:100]!r}") - text = text.replace(old, new, 1) - path.write_text(text, encoding="utf-8") - PY - - name: Commit docs repair - shell: bash - run: | - if git diff --quiet; then exit 0; fi - git config user.name "skill-lib repair" - git config user.email "actions@users.noreply.github.com" - git add README.md CLAUDE.md AGENTS.md tools/README.md skill-lib_msdmd.ts - git commit -m "docs: align ai.sh with Termux-to-VM launcher [skip ci]" - git push origin HEAD:repair/authority-and-ai-launcher From 8f3d61631cc96cb8e939e9e79c816cae6393f6a1 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:14:16 -0700 Subject: [PATCH 28/36] docs: align ai.sh with Termux-to-VM launcher --- tools/README.md | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/tools/README.md b/tools/README.md index 75d1157..916ea35 100644 --- a/tools/README.md +++ b/tools/README.md @@ -21,35 +21,39 @@ Stack = active language-gonol construction research EDCM = measurement/evaluation only ``` -## Canonical `ai` launcher +## Canonical `ai.sh` launcher -`tools/ai.sh` is the canonical VM coding-agent launcher. It owns the `a0` tmux -session layout, real pane/process status, restart, `remain-on-exit`, and -persistent pane logs under `~/.local/state/a0/logs`. +`tools/ai.sh` is the canonical Termux-side launcher for the coding-agent CLIs on +the `a0` VM. It uses the SSH host alias `a0` and owns the remote tmux session +layout (`0:shell`, `1:grok`, `2:codex`, `3:deepcode`), real pane/process status, +explicit restart, `remain-on-exit`, and persistent VM logs under +`~/.local/state/a0/logs`. -Install the stable `ai` command into the user PATH: +Install the stable `ai.sh` command into the caller PATH: ```bash bash tools/install_ai.sh ``` -The installer creates `~/.local/bin/ai` as a wrapper pointing back to the -canonical `tools/ai.sh`; it does not copy a second implementation. If -`~/.local/bin` is absent from PATH it adds one idempotent login-shell line to -`~/.profile`. +On Termux the installer symlinks the canonical source to `$PREFIX/bin/ai.sh`, +which is already on PATH. Elsewhere it uses `~/.local/bin/ai.sh` and adds one +idempotent login-shell PATH line only when required. No second launcher +implementation is copied. Examples: ```bash -ai -ai status -ai restart deepcode -ai logs deepcode -ai codex +ai.sh +ai.sh status +ai.sh restart deepcode +ai.sh logs deepcode +ai.sh codex ``` -Provider credentials remain the responsibility of the installed provider CLIs -and VM environment. The launcher does not read, print, or become a key vault. +Provider credentials remain the responsibility of the VM/provider CLIs. +`ai.sh keys` only copies already-present VM login-environment values into the +remote tmux environment so restarted CLIs can see them; it prints only +`present`/`missing` and never stores or displays key values. ## Drift checker From 111e5d2865e306c79c6a6dd06de7254371913476 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:16:37 -0700 Subject: [PATCH 29/36] test: preserve gonol-build behavioral gates under new authority --- tests/test_gonol_build_skill.py | 72 +++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/tests/test_gonol_build_skill.py b/tests/test_gonol_build_skill.py index d857287..e3f0e13 100644 --- a/tests/test_gonol_build_skill.py +++ b/tests/test_gonol_build_skill.py @@ -26,6 +26,7 @@ def test_activation_contract_is_concrete(self) -> None: "EDCM owns measurement/evaluation only", "no universal adjacent-scale ladder is required", "Pronunciation is not required", + "Do not load", ): self.assertIn(phrase, description) @@ -45,6 +46,7 @@ def test_active_construction_resolves_stack_workspace(self) -> None: self.assertIn("research/python-gonol/", self.text) self.assertIn("Do not start in EDCM", self.text) self.assertIn("Historical EDCM constructor names", self.text) + self.assertNotIn("`edcm/gonol.py`", self.text) def test_gonol_object_authority_remains_ucns(self) -> None: for phrase in ( @@ -63,29 +65,91 @@ def test_closed_gonols_participate_atomically(self) -> None: ): self.assertIn(phrase, self.compact) - def test_no_substitute_representation(self) -> None: + def test_no_undeclared_intermediate_or_substitute_representation(self) -> None: for phrase in ( + "Do not invent participant eligibility, a required intermediate stage", "Do not normalize, deduplicate, infer relations", "tokens, AST nodes, compiler objects, embeddings, hashes, or metadata", - "do not fill it with an invented rule", ): self.assertIn(phrase, self.compact) + def test_pronunciation_is_inert_by_default(self) -> None: + for phrase in ( + "Pronunciation is not required by default", + "must not alter gonol identity, closure, ordering, or relations", + "Source pronunciation data may remain evidence or metadata", + "only under an explicit source/admission contract", + ): + self.assertIn(phrase, self.compact) + + def test_construction_invariant_preserves_identity_relation_and_provenance(self) -> None: + for phrase in ( + "ordered eligible closed gonols", + "constitutive relation declared by the owning workspace", + "UCNS gonol construction / authorized geometric application", + "deterministic identity + provenance receipt", + "Preserve exact source identity, occurrence order, multiplicity, relation identity, and provenance", + ): + self.assertIn(phrase, self.compact) + + def test_unresolved_geometry_stays_hmmm(self) -> None: + self.assertIn("preserve that boundary as `hmmm`", self.text) + self.assertIn("do not fill it with an invented rule", self.compact) + def test_local_authority_gate_is_named(self) -> None: self.assertTrue(WITNESS.is_file()) self.assertIn("bash tools/check_gonol_authority.sh", self.text) - def test_completion_preserves_replay_boundary(self) -> None: + def test_completion_preserves_resource_and_replay_boundary(self) -> None: for phrase in ( + "Before launching a construction or replay run whose completion materially depends on scarce resources", "preflight the resources required to finish it", + "do not start the compute run", "Do not add arbitrary wall-clock limits", "the complete declared source scope", "deterministic construction receipts", - "independent complete replay where replay is required", + "independent complete replay where replay is required by the governing protocol", "Replay establishes reproducibility of that construction only", ): self.assertIn(phrase, self.compact) + def test_workflow_preflights_before_constructor_resolution_and_replays_conditionally(self) -> None: + workflow = self.text.split("## Workflow", 1)[1].split("## Authority", 1)[0] + for phrase in ( + "Before launching construction or replay whose completion materially depends on scarce resources", + "preflight the resources required to finish the declared scope", + "Resolve the owning Stack workspace's declared source/admission profile", + "Replay the complete declared scope only where replay is required by the governing protocol", + ): + self.assertIn(phrase, workflow) + self.assertLess( + workflow.index("Before launching construction or replay"), + workflow.index("Resolve the owning Stack workspace's declared source/admission profile"), + ) + + def test_workflow_and_anti_patterns_are_named(self) -> None: + self.assertIn("## Workflow", self.text) + self.assertIn("## Anti-patterns", self.text) + self.assertIn("Resolve the exact UCNS authority and the exact owning Stack research workspace", self.compact) + self.assertIn("Assigning active gonol or language construction authority to EDCM", self.compact) + + def test_anti_patterns_preserve_explicit_contract_exceptions(self) -> None: + anti_patterns = self.text.split("## Anti-patterns", 1)[1].split("## hmmm", 1)[0] + self.assertIn( + "unless an explicit construction admits it", + anti_patterns, + ) + self.assertIn( + "unless explicitly authorized", + anti_patterns, + ) + + def test_usage_guidance_repeats_operational_contract(self) -> None: + self.assertIn("start in the owning research workspace inside `The-Interdependency/stack`", self.compact) + self.assertIn("Do not start in EDCM", self.compact) + self.assertIn("When a gonol closes, use it atomically at an admissible consuming scale", self.compact) + self.assertIn("Ignore pronunciation unless an explicit construction says otherwise", self.compact) + def test_codex_adapter_points_to_canonical_skill(self) -> None: text = ADAPTER.read_text(encoding="utf-8") self.assertIn("Generated by tools/build_codex_plugin_skills.py", text) From b74e0b1f825f9fcf9a7711902e0517dbc5c15a9a Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:17:28 -0700 Subject: [PATCH 30/36] docs: correct canonical ai.sh install and remote behavior --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3b50f9f..b0fc84d 100644 --- a/README.md +++ b/README.md @@ -135,13 +135,21 @@ python tools/build_codex_plugin_skills.py --check ## VM coding-agent launcher -The canonical `ai` tmux launcher lives at `tools/ai.sh`. Install a stable command in the user PATH without copying the implementation: +The canonical `ai.sh` launcher lives at `tools/ai.sh`. It runs on Termux, +reaches the `a0` VM through the SSH host alias `a0`, and manages the remote +`a0` tmux session. Install it into the caller PATH without copying the +implementation: ```bash bash tools/install_ai.sh ``` -The installer creates `~/.local/bin/ai` pointing back to this checkout. `ai status` reports actual pane state, `ai restart deepcode` recreates/restarts DeepCode, and pane output persists under `~/.local/state/a0/logs`. Provider credentials remain owned by the provider CLIs/environment. +On Termux the installer symlinks `ai.sh` into `$PREFIX/bin`; elsewhere it falls +back to `~/.local/bin/ai.sh`. `ai.sh status` reports remote pane state, +`ai.sh restart deepcode` repairs a missing/dead DeepCode window, and pane output +persists on the VM under `~/.local/state/a0/logs`. `ai.sh keys` only propagates +already-present VM login-environment keys into tmux and reports +`present`/`missing`, never values. ## Maintenance tools @@ -218,7 +226,8 @@ authoritative spec. Skills come in two kinds. Pick the right one for what you're adding. **Metadata-block skills** apply the `msdmd` convention to a new block -name (`doc-build`, `cap-build`, `deps-build`, `owner-build`, `test-build`, `meta-module-build`, `risk-boundary-build`, `ratios`, `manifest`, `llms-build`, and `typed-meta-frontend` are the existing examples). +name (`doc-build`, `cap-build`, `deps-build`, `owner-build`, `test-build`, `meta-module-build`, `risk-boundary-build`, +`ratios`, `manifest`, `llms-build`, and `typed-meta-frontend` are the existing examples). To add one: 1. Pick a `` (e.g. `DOCS`, `CAPABILITIES`, `OWNERS`, `LLMS`). From 7f001ce8f12b83a232aa50850d1e560e6d874119 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:18:21 -0700 Subject: [PATCH 31/36] docs: align msdmd collection with canonical ai.sh --- 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 c608938..37fa58b 100644 --- a/skill-lib_msdmd.ts +++ b/skill-lib_msdmd.ts @@ -24,7 +24,7 @@ export default defineMsdmdCollection({ id: "skill_lib_ai_launcher", fields: { source: "tools/ai.sh", - summary: "Canonical tmux launcher for coding-agent CLIs with pane health, restart, remain-on-exit, and persistent logs", + summary: "Canonical Termux-side SSH/tmux launcher for a0 VM coding-agent CLIs with pane health, explicit restart, key propagation, remain-on-exit, and persistent remote logs", }, }, { @@ -33,7 +33,7 @@ export default defineMsdmdCollection({ id: "skill_lib_ai_installer", fields: { source: "tools/install_ai.sh", - summary: "Installs the skill-lib ai launcher as ~/.local/bin/ai and ensures the user PATH contains ~/.local/bin", + summary: "Installs canonical ai.sh into caller PATH, preferring Termux $PREFIX/bin and otherwise ~/.local/bin", }, }, { From e2acc6c84fd17d87225b9d6bb5fbbbca878dcd58 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:18:58 -0700 Subject: [PATCH 32/36] docs: align agent entrypoint with canonical ai.sh --- AGENTS.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a17420d..9aa3099 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,8 +51,8 @@ Read [`RESOURCE_RUN_INVARIANT.md`](RESOURCE_RUN_INVARIANT.md) before any compute /SKILL.md # required: the skill itself /... # optional: parsers, executors, examples llms/ # stdlib module for python -m llms.build -tools/ai.sh # canonical VM coding-agent tmux launcher -tools/install_ai.sh # installs ~/.local/bin/ai PATH wrapper +tools/ai.sh # canonical Termux -> a0 SSH/tmux coding-agent launcher +tools/install_ai.sh # installs ai.sh into caller PATH (Termux $PREFIX/bin first) ``` Every skill is a directory at the repo root containing at least a @@ -193,5 +193,5 @@ propagate from here. - `llms.txt` — generated LLM-facing root instructions. - Each `/SKILL.md` — the authoritative skill spec. - `llms/build.py` — reference runner for `llms-build`. -- `tools/ai.sh` — canonical VM coding-agent launcher. -- `tools/install_ai.sh` — PATH installer for `~/.local/bin/ai`. +- `tools/ai.sh` — canonical Termux-side launcher for the remote `a0` tmux coding-agent session. +- `tools/install_ai.sh` — installs `ai.sh` into caller PATH, preferring Termux `$PREFIX/bin`. From d9552cf39be3de0a7f1b1f329d72d8c19c3eee4d Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:20:09 -0700 Subject: [PATCH 33/36] docs: remove remaining EDCM construction authority from assistant guidance --- CLAUDE.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 82ca5bf..dc04d15 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,7 +11,7 @@ AI-assistant guidance for `The-Interdependency/skill-lib`. - Entry points: `README.md`, `AGENTS.md`, `skills.json`, `ORG_DISTRIBUTION.md`, `llms.txt`, each `/SKILL.md`. - CI workflows: `.github/workflows/hygiene.yml` guards against tracked Python bytecode, `.github/workflows/ci.yml` runs the editorial/helper verification stack, and `.github/workflows/consumer-drift.yml` is a scheduled/dispatch detector that runs `tools/check_consumer_drift.py` against each consumer repo (the consumer repos are public, so it uses the default `GITHUB_TOKEN`). - Validation here is editorial plus pure-stdlib helper scripts in `tools/`, `ratios/`, `llms/`, and the RepoLOTO check module. -- `tools/ai.sh` is the canonical VM coding-agent tmux launcher; `tools/install_ai.sh` installs the stable `~/.local/bin/ai` PATH wrapper. +- `tools/ai.sh` is the canonical Termux-side SSH/tmux launcher for the `a0` VM; `tools/install_ai.sh` installs `ai.sh` into the caller PATH (Termux `$PREFIX/bin`, otherwise `~/.local/bin`). - The `llms/` package exists only to expose the stdlib `python -m llms.build` runner for `llms-build`. ## Layout @@ -191,6 +191,7 @@ blocks first; do not hand-edit `llms.txt` as independent doctrine. ```bash python -m unittest discover -s tests +bash tools/check_gonol_authority.sh python tools/check_skill_lib_drift.py --warnings-fail python tools/check_skill_compliance.py --warnings-fail python ratios/ratios_check.py --strict @@ -212,8 +213,10 @@ There is a small stdlib Python editorial test suite. There is still no `package. skills.json semantics, per-skill spec coverage, SKILL.md frontmatter, README index coverage, collection-point schema/generator/visualizer coverage, universal parser behavior, llms-build behavior, and parser ratio bookends. +- `tools/ai.sh` is the canonical Termux-side controller for the remote `a0` tmux coding-agent session; `tools/install_ai.sh` installs `ai.sh` into caller PATH, preferring Termux `$PREFIX/bin`. - The parsers are reference implementations; the test suite covers core parser behavior and library integration, not every consuming-runner contract. +- `check_gonol_authority.sh` fails closed when active skill-lib surfaces restore EDCM construction ownership. - `check_skill_lib_drift.py` checks editorial agreement among skill directories, `skills.json`, `README.md`, `ORG_DISTRIBUTION.md`, `AGENTS.md`, `CLAUDE.md`, and generated `llms.txt`. - `check_skill_compliance.py` checks baseline `skill-build` invariants for each `SKILL.md`. - `ratios_check.py --strict` verifies opening/closing ratios seals for @@ -252,7 +255,7 @@ There is a small stdlib Python editorial test suite. There is still no `package. 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 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 geometry and EDCM admissible scale options, preserve closure and atomic participation, require declared occurrence-addressed function plans, and keep incomplete constructors visible as `hmmm`. +12. Before constructing, reviewing, replaying, or extending language-gonol research, apply `gonol-build`: resolve current UCNS gonol-object/constructor/geometry authority and the exact owning Stack research workspace; EDCM is measurement/evaluation only. Preserve closure and atomic participation, require declared constitutive relations, and keep incomplete geometry 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. Before mutating `The-Interdependency/stack` structure, apply `stack-update` with `interdependent-work-graph`; update every affected authority/provenance projection, remove superseded claims, recompute the work-graph digest, and require the deterministic stack checker before merge. From 6cd71f0e1d7570705a740dfcb641e3b36f1bcebc Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:20:42 -0700 Subject: [PATCH 34/36] fix: prevent authority gate from flagging negative-test literals --- tools/check_gonol_authority.sh | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/tools/check_gonol_authority.sh b/tools/check_gonol_authority.sh index b7727e7..64aca6c 100755 --- a/tools/check_gonol_authority.sh +++ b/tools/check_gonol_authority.sh @@ -6,10 +6,10 @@ set -euo pipefail # id: gonol_authority_gate # module_name: check_gonol_authority # module_kind: checker -# summary: fail-closed local regression gate for UCNS/Stack/EDCM gonol authority across active skill-lib surfaces +# summary: fail-closed local regression gate for UCNS/Stack/EDCM gonol authority across active skill-lib doctrine and projections # owner: skill-lib # public_surface: bash tools/check_gonol_authority.sh -# internal_surface: active_files +# internal_surface: doctrine_files # auth_boundary: none # storage_boundary: read-only repository files # network_boundary: none @@ -26,7 +26,10 @@ set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" -active_files=( +# These are operative doctrine/projection surfaces only. Unit tests deliberately +# contain forbidden phrases inside assertNotIn() calls and must not be scanned as +# prose claims by this literal regression gate. +doctrine_files=( gonol-build/SKILL.md skills/gonol-build/SKILL.md char-compress/SKILL.md @@ -35,8 +38,6 @@ active_files=( CLAUDE.md ORG_DISTRIBUTION.md skills.json - tests/test_gonol_build_skill.py - tests/test_char_compress_authority.py ) grep -Fq 'UCNS = gonol objects, constructors, and underlying geometry' gonol-build/SKILL.md @@ -51,15 +52,19 @@ grep -Fq 'Stack language-construction research discipline' CLAUDE.md grep -Fq 'exact owning Stack research workspace' AGENTS.md grep -Fq 'Stack language-construction research' ORG_DISTRIBUTION.md -for file in "${active_files[@]}"; do - if grep -Fq 'EDCM owns text-domain gonol construction' "$file"; then - printf 'FAIL: stale EDCM construction authority in %s\n' "$file" >&2 - exit 1 - fi - if grep -Fq 'UCNS geometry / EDCM text construction' "$file"; then - printf 'FAIL: stale UCNS/EDCM authority split in %s\n' "$file" >&2 - exit 1 - fi +for file in "${doctrine_files[@]}"; do + for stale in \ + 'EDCM owns text-domain gonol construction' \ + 'UCNS geometry / EDCM text construction' \ + 'EDCM owns the admissible scale options' \ + 'current UCNS geometry and EDCM admissible scale options' \ + 'start in EDCM and consume current UCNS geometry' + do + if grep -Fq "$stale" "$file"; then + printf 'FAIL: stale gonol authority in %s: %s\n' "$file" "$stale" >&2 + exit 1 + fi + done done echo 'gonol authority: OK' From 5c74519a256d6848142e649d4f2949cde52995bb Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:22:29 -0700 Subject: [PATCH 35/36] fix: preserve unresolved candidate-work boundary --- gonol-build/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gonol-build/SKILL.md b/gonol-build/SKILL.md index 02e5f63..23cd452 100644 --- a/gonol-build/SKILL.md +++ b/gonol-build/SKILL.md @@ -77,7 +77,7 @@ If required UCNS geometry is unresolved, preserve that boundary as `hmmm`; do no ## Candidate boundary -An unresolved constructor or geometry operation is permission to construct a named, bounded candidate only where the declared evidence permits it. It blocks promotion beyond the evidence, not honest experimentation. +An unresolved constructor or geometry operation permits named, bounded candidate work where the declared evidence permits it. It does not block declared experimentation. It blocks promotion beyond the evidence. ## Completion and replay From 190eeaaba09dd5d12c351473b7763c44fb9e94b6 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 21:22:51 -0700 Subject: [PATCH 36/36] docs: state UCNS construction consumption explicitly --- gonol-build/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gonol-build/SKILL.md b/gonol-build/SKILL.md index 23cd452..2590edf 100644 --- a/gonol-build/SKILL.md +++ b/gonol-build/SKILL.md @@ -26,7 +26,7 @@ EDCM = measurement and evaluation of constructed outputs skill-lib = construction/replay discipline ``` -Repository placement does not transfer authority. A Stack workspace may construct English, Python, French, TypeScript, or another domain from UCNS gonol objects without thereby owning UCNS geometry. EDCM may measure a completed construction without defining that construction. +Repository placement does not transfer authority. A Stack workspace may construct English, Python, French, TypeScript, or another domain from UCNS gonol objects without thereby owning UCNS geometry. Language workspaces consume UCNS construction authority; they do not redefine it. EDCM may measure a completed construction without defining that construction. Historical EDCM constructor names and sealed artifacts remain valid historical identities for replay. They do not restore active construction authority to EDCM.