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 diff --git a/AGENTS.md b/AGENTS.md index 714cbc5..9aa3099 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 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 @@ -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 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`. diff --git a/CLAUDE.md b/CLAUDE.md index 67e2aff..dc04d15 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 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 @@ -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. | @@ -190,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 @@ -211,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 @@ -251,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. 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/README.md b/README.md index 5904a61..b0fc84d 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,24 @@ python tools/build_codex_plugin_skills.py --apply python tools/build_codex_plugin_skills.py --check ``` +## VM coding-agent launcher + +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 +``` + +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 Pure-stdlib helper scripts live in [`tools/`](tools/README.md). The small @@ -208,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`). 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/gonol-build/SKILL.md b/gonol-build/SKILL.md index 6e0e97d..2590edf 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. Language workspaces consume UCNS construction authority; they do not redefine it. 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 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 -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 +bash tools/check_gonol_authority.sh ``` -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. diff --git a/skill-lib_msdmd.ts b/skill-lib_msdmd.ts index 09ea7e1..37fa58b 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 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", + }, + }, + { + file: "tools/install_ai.sh", + block: "MODULE_BUILD", + id: "skill_lib_ai_installer", + fields: { + source: "tools/install_ai.sh", + summary: "Installs canonical ai.sh into caller PATH, preferring Termux $PREFIX/bin and otherwise ~/.local/bin", }, }, { 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."}, 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." --- diff --git a/tests/test_ai_launcher.py b/tests/test_ai_launcher.py new file mode 100644 index 0000000..e507be5 --- /dev/null +++ b/tests/test_ai_launcher.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +from pathlib import Path +import subprocess +import unittest + + +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_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) + 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}"', + 'ssh "$HOST"', + 'ssh -tt "$HOST"', + "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_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_start_repairs_missing_or_dead_agents_without_restarting_healthy_ones(self) -> None: + text = LAUNCHER.read_text(encoding="utf-8") + 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", + "printenv", + "tmux set-environment", + "present", + "missing", + ): + self.assertIn(phrase, text) + self.assertNotIn("read -s", text) + self.assertNotIn("KEY=", text) + + def test_installer_places_ai_sh_on_termux_path_without_copying(self) -> None: + text = INSTALLER.read_text(encoding="utf-8") + for phrase in ( + '$PREFIX/bin', + 'TARGET="$BIN_DIR/ai.sh"', + 'SOURCE="$SOURCE_DIR/ai.sh"', + 'ln -sfn "$SOURCE" "$TARGET"', + 'skill-lib ai launcher', + ): + self.assertIn(phrase, text) + self.assertNotIn('cp "$SOURCE" "$TARGET"', text) + + +if __name__ == "__main__": + unittest.main() 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) diff --git a/tests/test_gonol_build_skill.py b/tests/test_gonol_build_skill.py index d8d4460..e3f0e13 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.sh" class GonolBuildSkillTest(unittest.TestCase): @@ -21,68 +21,74 @@ 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) + self.assertNotIn("`edcm/gonol.py`", 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_gonol_object_authority_remains_ucns(self) -> None: + for phrase in ( + "Consume UCNS gonol constructors and geometry", + "Defining a competing gonol object", + "consume UCNS construction authority", + ): + self.assertIn(phrase, self.compact) - def test_closed_words_promote_atomically(self) -> None: + def test_closed_gonols_participate_atomically(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", + "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_no_undeclared_intermediate_stage(self) -> None: - self.assertIn( - "Do not invent participant eligibility or another required stage", - self.compact, - ) + 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", + ): + self.assertIn(phrase, self.compact) def test_pronunciation_is_inert_by_default(self) -> None: for phrase in ( - "Pronunciation is not required for this construction", + "Pronunciation is not required by default", "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", + "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_and_provenance(self) -> None: + def test_construction_invariant_preserves_identity_relation_and_provenance(self) -> None: for phrase in ( - "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", "deterministic identity + provenance receipt", - "Preserve exact source identity, occurrence order, multiplicity, and provenance", - "Do not normalize, deduplicate, infer relations", + "Preserve exact source identity, occurrence order, multiplicity, relation identity, and provenance", ): self.assertIn(phrase, self.compact) @@ -90,7 +96,11 @@ 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_completion_requires_full_scope_and_replay(self) -> None: + 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_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", @@ -103,50 +113,50 @@ def test_completion_requires_full_scope_and_replay(self) -> None: ): self.assertIn(phrase, self.compact) - def test_workflow_preflights_before_compute_and_replays_conditionally(self) -> None: + 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 EDCM constructor's declared scale option set"), - ) - self.assertNotIn( - "Preflight resources before a completion claim, then replay the complete declared scope", - workflow, + 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 current UCNS and EDCM authorities before building", self.compact) - self.assertIn("Moving text semantics into UCNS or inventing geometry in EDCM", self.compact) + 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 a later explicitly declared experiment makes phonology part of its construction", + "unless an explicit construction admits it", anti_patterns, ) self.assertIn( - "unless the active contract explicitly authorizes it", + "unless explicitly authorized", 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) + 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) 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() diff --git a/tools/README.md b/tools/README.md index c97a06b..916ea35 100644 --- a/tools/README.md +++ b/tools/README.md @@ -3,8 +3,57 @@ 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.sh` launcher + +`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.sh` command into the caller PATH: + +```bash +bash tools/install_ai.sh +``` + +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.sh +ai.sh status +ai.sh restart deepcode +ai.sh logs deepcode +ai.sh codex +``` + +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 @@ -146,8 +195,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 +209,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 diff --git a/tools/ai.sh b/tools/ai.sh new file mode 100755 index 0000000..136523a --- /dev/null +++ b/tools/ai.sh @@ -0,0 +1,303 @@ +# 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 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.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 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: third-party CLI executable names and provider authentication methods may change +# === END MODULE_BUILD === + +HOST="${A0_AI_HOST:-a0}" +SESSION="${A0_AI_SESSION:-a0}" +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:-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.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 +} + +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=\"\$(printenv \"\$key\" 2>/dev/null || true)\"; 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_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_shell() { + local index="$1" name="$2" + ensure_session + 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 + + 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 +} + +respawn() { + local name="$1" command_line="$2" binary pane_command + binary="${command_line%% *}" + 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 + 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_agent() { + 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 [[ "$existed" == 0 || "$dead" == 1 ]]; then + respawn "$name" "$command_line" + fi +} + +start_all() { + ensure_window_shell 0 shell + ensure_agent grok || true + ensure_agent codex || true + ensure_agent deepcode || true +} + +restart_one() { + 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}" + 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" + remote_tty "tmux select-window -t $(q "$SESSION:$name") && exec tmux attach-session -t $(q "$SESSION")" +} + +open_agent() { + 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 && ( "$existed" == 0 || "$dead" == 1 ) ]]; then + respawn "$name" "$command_line" + fi + attach_window "$name" +} + +logs() { + 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 + 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) 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; 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}" ;; + 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 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 diff --git a/tools/check_gonol_authority.sh b/tools/check_gonol_authority.sh new file mode 100755 index 0000000..64aca6c --- /dev/null +++ b/tools/check_gonol_authority.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# 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 doctrine and projections +# owner: skill-lib +# public_surface: bash tools/check_gonol_authority.sh +# internal_surface: doctrine_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" + +# 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 + README.md + AGENTS.md + CLAUDE.md + ORG_DISTRIBUTION.md + skills.json +) + +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 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 "${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' +# 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..3b6a788 --- /dev/null +++ b/tools/install_ai.sh @@ -0,0 +1,58 @@ +#!/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 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: PATH target selection and symlink installation +# auth_boundary: none +# 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: remove the installed ai.sh symlink and marked PATH line if one was added +# requires: bash +# since: 2026-09-12 +# 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" +PROFILE="${A0_AI_PROFILE:-$HOME/.profile}" + +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 + +TARGET="$BIN_DIR/ai.sh" +[[ -f "$SOURCE" ]] || { printf 'ERROR: canonical launcher missing: %s\n' "$SOURCE" >&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" + 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 + printf 'PATH updated for future login shells in %s\n' "$PROFILE" + printf 'for this shell: export PATH=%q:\$PATH\n' "$BIN_DIR" +fi + +printf 'installed: %s -> %s\n' "$TARGET" "$SOURCE" +bash "$TARGET" --help + +# ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm