From a19e137e005fff0d9e45dc4accc79d98925bd558 Mon Sep 17 00:00:00 2001 From: Steve Brown Date: Fri, 23 Oct 2026 03:59:43 -0400 Subject: [PATCH] fix(release): use canonical Tambo owner and retain repository guard --- .github/workflows/ci.yml | 2 + .github/workflows/release.yml | 2 +- Cargo.toml | 2 +- README.md | 14 ++--- docs/book/book.toml | 4 +- docs/book/src/agents.md | 2 +- docs/book/src/docs-map.md | 8 +-- docs/book/src/installation-reference.md | 22 ++++---- docs/book/src/installing.md | 8 +-- docs/book/src/introduction.md | 6 +-- docs/book/src/pendant-autoload.md | 2 +- docs/book/src/reference.md | 2 +- docs/book/src/stack-standard.md | 4 +- docs/book/src/stack.md | 2 +- docs/book/src/using.md | 2 +- docs/demos/bootstrap-compat/run.py | 2 +- docs/knowledge/repository-knowledge.json | 8 +-- docs/stack-table.md | 2 +- docs/stack/README-TEMPLATE.md | 4 +- install.sh | 4 +- justfile | 2 + scripts/check-doc-links.sh | 2 + scripts/install.sh | 4 +- scripts/setup-environment.sh | 2 +- scripts/test-doc-links.py | 22 ++++---- scripts/test-install-bootstrap.py | 29 ++++++++-- scripts/test-readme.sh | 2 +- scripts/test-release-repository.py | 69 ++++++++++++++++++++++++ skills/caboodle/SKILL.md | 2 +- skills/tambo/SKILL.md | 2 +- 30 files changed, 169 insertions(+), 69 deletions(-) create mode 100644 scripts/test-release-repository.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb62705..eff7e78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,8 @@ jobs: run: scripts/test-release-install.sh - name: Bootstrap legacy and renamed release controls run: python3 scripts/test-install-bootstrap.py + - name: Canonical release repository refusal controls + run: python3 scripts/test-release-repository.py - name: Registry visibility refusal controls run: python3 scripts/test-crate-version.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 782524b..7b35c8e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -150,7 +150,7 @@ jobs: shell: bash run: | set -euo pipefail - test "$GITHUB_REPOSITORY" = scbrown/tambo + test "$GITHUB_REPOSITORY" = intigraph/tambo version=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "tambo") | .version') test "$VERSION" = "v$version" echo "TAMBO_PUBLISH_VERSION=$version" >> "$GITHUB_ENV" diff --git a/Cargo.toml b/Cargo.toml index 1871ac7..023cfd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.5.0" edition = "2021" description = "Install and prove the whole AI knowledge-tool kit" license = "Apache-2.0" -repository = "https://github.com/scbrown/tambo" +repository = "https://github.com/intigraph/tambo" rust-version = "1.80" # Tambo is the renamed installer. The legacy executable remains supported. # Publication runs through the official release workflow after name/owner checks. diff --git a/README.md b/README.md index 0ad7747..e0a62d8 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The compatibility command `caboodle` remains available. ## Install ```bash -curl -fsSL https://raw.githubusercontent.com/scbrown/tambo/main/install.sh | sh +curl -fsSL https://raw.githubusercontent.com/intigraph/tambo/main/install.sh | sh ``` Downloads the latest release, verifies its SHA-256 and version, and installs @@ -18,7 +18,7 @@ Downloads the latest release, verifies its SHA-256 and version, and installs `tar`, Python 3 and `sha256sum` or `shasum`. Add that directory to `PATH`. Published archives support Linux x86_64 and macOS arm64/x86_64; **Linux arm64 has no published archive**. Source builds, pinned versions, removal and the -Homebrew alternative are in the [installation reference](https://scbrown.github.io/caboodle/installation-reference.html). +Homebrew alternative are in the [installation reference](https://intigraph.github.io/tambo/installation-reference.html). ## First success: local, single-user @@ -40,7 +40,7 @@ tambo verify ### Advanced: shared services and agents For issued credentials, remote stores and registering Bobbin with your agent, -use the [agent and installation reference](https://scbrown.github.io/caboodle/installation-reference.html). +use the [agent and installation reference](https://intigraph.github.io/tambo/installation-reference.html). The default quickstart is local and needs no account or remote server. From the code repository you want searchable, initialize and index it before @@ -54,12 +54,12 @@ claude mcp add bobbin -- "$(command -v bobbin)" serve "$PWD" ## Where to go next -- [Choose a profile](https://scbrown.github.io/caboodle/profiles.html) or use `tambo init --guided`. +- [Choose a profile](https://intigraph.github.io/tambo/profiles.html) or use `tambo init --guided`. - [Camayoc](https://github.com/scbrown/camayoc): vocabulary, shapes and governed agent memory. -- [Getting started](https://scbrown.github.io/caboodle/getting-started.html) and [command reference](https://scbrown.github.io/caboodle/reference.html). +- [Getting started](https://intigraph.github.io/tambo/getting-started.html) and [command reference](https://intigraph.github.io/tambo/reference.html). - **Load this repository's graph:** repository-pendant publication is pending. When a release provides the archive, checksum and provenance, follow Quipu's - [verified import workflow](https://scbrown.github.io/quipu/sharing/index.html). + [verified import workflow](https://intigraph.github.io/quipu/sharing/index.html). Import stages knowledge; it does not promote it into ROOT automatically. ## The stack @@ -73,7 +73,7 @@ when. | tool | what it gives your agents | |---|---| -| [tambo](https://github.com/scbrown/tambo) | 🧰 Agent Platform Toolkit - installs and configures the quipu stack | +| [tambo](https://github.com/intigraph/tambo) | 🧰 Agent Platform Toolkit - installs and configures the quipu stack | | [quipu](https://github.com/scbrown/quipu) | stores shared facts with provenance and history; can check writes against your rules | | [camayoc](https://github.com/scbrown/camayoc) | prepares knowledge and vocabulary for Quipu, with checks before it is admitted | | [quechua](https://github.com/scbrown/quechua) | shared vocabulary and shapes for interoperable knowledge | diff --git a/docs/book/book.toml b/docs/book/book.toml index 022af79..f947f0f 100644 --- a/docs/book/book.toml +++ b/docs/book/book.toml @@ -9,8 +9,8 @@ src = "src" default-theme = "coal" preferred-dark-theme = "coal" # Keep working GitHub alias links until the repository rename is verified. -git-repository-url = "https://github.com/scbrown/caboodle" -edit-url-template = "https://github.com/scbrown/caboodle/edit/main/docs/book/{path}" +git-repository-url = "https://github.com/intigraph/tambo" +edit-url-template = "https://github.com/intigraph/tambo/edit/main/docs/book/{path}" additional-css = ["custom/css/custom.css"] site-url = "/tambo/" diff --git a/docs/book/src/agents.md b/docs/book/src/agents.md index 99e48e3..233a48d 100644 --- a/docs/book/src/agents.md +++ b/docs/book/src/agents.md @@ -1,7 +1,7 @@ # Using it with agents Caboodle is a CLI that an agent can run with the -[Tambo skill](https://github.com/scbrown/tambo/blob/main/skills/tambo/SKILL.md). +[Tambo skill](https://github.com/intigraph/tambo/blob/main/skills/tambo/SKILL.md). It does not expose its own MCP server. MCP (Model Context Protocol) lets an agent call servers supplied by the installed tools. diff --git a/docs/book/src/docs-map.md b/docs/book/src/docs-map.md index 3cb9d2d..c888f99 100644 --- a/docs/book/src/docs-map.md +++ b/docs/book/src/docs-map.md @@ -28,7 +28,7 @@ These links point to the source repository so they work on both GitHub and the published book. Every loose document under `docs/` is listed here. -- [Stack README standard](https://github.com/scbrown/caboodle/blob/main/docs/stack/README-STANDARD.md): section order, theme, shared stack block and review checklist. -- [README template](https://github.com/scbrown/caboodle/blob/main/docs/stack/README-TEMPLATE.md): fill-in template implementing the standard. -- [Design vision](https://github.com/scbrown/caboodle/blob/main/docs/design/vision.md): **Historical** design proposal; use the reference for shipped commands. -- [txtai gap analysis](https://github.com/scbrown/caboodle/blob/main/docs/design/txtai-gap-analysis.md): **Historical** comparison and design opportunities, not a current capability guarantee. +- [Stack README standard](https://github.com/intigraph/tambo/blob/main/docs/stack/README-STANDARD.md): section order, theme, shared stack block and review checklist. +- [README template](https://github.com/intigraph/tambo/blob/main/docs/stack/README-TEMPLATE.md): fill-in template implementing the standard. +- [Design vision](https://github.com/intigraph/tambo/blob/main/docs/design/vision.md): **Historical** design proposal; use the reference for shipped commands. +- [txtai gap analysis](https://github.com/intigraph/tambo/blob/main/docs/design/txtai-gap-analysis.md): **Historical** comparison and design opportunities, not a current capability guarantee. diff --git a/docs/book/src/installation-reference.md b/docs/book/src/installation-reference.md index 4b859cb..a4b2517 100644 --- a/docs/book/src/installation-reference.md +++ b/docs/book/src/installation-reference.md @@ -9,13 +9,13 @@ Checksummed releases: Linux x86_64, macOS arm64 and macOS x86_64. The installer verifies SHA256 before placing the binary in `~/.cargo/bin`. ```bash -curl -fsSL https://raw.githubusercontent.com/scbrown/caboodle/main/scripts/install.sh | bash +curl -fsSL https://raw.githubusercontent.com/intigraph/tambo/main/scripts/install.sh | bash ``` To pin a release, pass the version to the receiving shell: ```bash -curl -fsSL https://raw.githubusercontent.com/scbrown/caboodle/main/scripts/install.sh | CABOODLE_VERSION=vX.Y.Z bash +curl -fsSL https://raw.githubusercontent.com/intigraph/tambo/main/scripts/install.sh | CABOODLE_VERSION=vX.Y.Z bash ``` Add the install directory to this shell's PATH: @@ -37,7 +37,7 @@ not read that file, which is why the agent step below registers servers by absolute path. Or build the latest release from source with Rust (`cargo install --git -https://github.com/scbrown/caboodle --tag vX.Y.Z --locked`). Either way, +https://github.com/intigraph/tambo --tag vX.Y.Z --locked`). Either way, `caboodle --version` prints `caboodle X.Y.Z` for the release you installed. ### macOS with Homebrew @@ -102,7 +102,7 @@ remains remote until you remove that configuration deliberately. To customize the tools and intended-use contract instead, use `tambo init --guided` or `tambo plan --profile retrieval --intent caboodle-intent.toml`, review the resulting plan, then run `tambo install`. See the -[walkthrough](https://scbrown.github.io/caboodle/getting-started.html). +[walkthrough](https://intigraph.github.io/tambo/getting-started.html). ## On your own code @@ -114,11 +114,11 @@ review the resulting plan, then run `tambo install`. See the | Recheck the selected tools | `caboodle verify` | | Compare against this build's reviewed versions | `caboodle check-updates` | -[Full command and configuration reference](https://scbrown.github.io/caboodle/reference.html). +[Full command and configuration reference](https://intigraph.github.io/tambo/reference.html). ## Wire it into your agent -Tambo is a CLI, with an [agent skill](https://github.com/scbrown/tambo/blob/main/skills/tambo/SKILL.md), not an MCP +Tambo is a CLI, with an [agent skill](https://github.com/intigraph/tambo/blob/main/skills/tambo/SKILL.md), not an MCP server. Bobbin, which the `retrieval` profile installed above, is one. It searches one repository: the code you want your agent to work on, such as your own project's git checkout. Do not use `~/caboodle`, which holds only the plan. @@ -146,7 +146,7 @@ serve` exits with `Bobbin not initialized` and Claude Code reports the server as failed to connect. MCP (Model Context Protocol) lets your agent call the installed server. -[Agent setup](https://scbrown.github.io/caboodle/agents.html) covers indexing, Yupana, other clients +[Agent setup](https://intigraph.github.io/tambo/agents.html) covers indexing, Yupana, other clients and managed crew registration through `caboodle project-settings`. ## Before you start @@ -160,12 +160,12 @@ and managed crew registration through `caboodle project-settings`. Have `curl`, `tar`, `git`, `bash`, `python3` and `sha256sum` on PATH (`brew install coreutils` supplies `sha256sum` on macOS). The `everything` profile also needs Go. No account or remote server is needed. -[Installation details](https://scbrown.github.io/caboodle/installing.html) cover source builds, +[Installation details](https://intigraph.github.io/tambo/installing.html) cover source builds, installed files and removal; `caboodle doctor` names missing prerequisites. ## What's next -- [Read the book](https://scbrown.github.io/caboodle/introduction.html) -- [Find a topic in the docs map](https://scbrown.github.io/caboodle/docs-map.html) -- [Choose your profile](https://scbrown.github.io/caboodle/profiles.html) +- [Read the book](https://intigraph.github.io/tambo/introduction.html) +- [Find a topic in the docs map](https://intigraph.github.io/tambo/docs-map.html) +- [Choose your profile](https://intigraph.github.io/tambo/profiles.html) diff --git a/docs/book/src/installing.md b/docs/book/src/installing.md index 4a271e7..3840302 100644 --- a/docs/book/src/installing.md +++ b/docs/book/src/installing.md @@ -52,17 +52,17 @@ embedded release pins; it does not refresh package metadata. Run the checksummed release installer in one line: ```bash -curl -fsSL https://raw.githubusercontent.com/scbrown/caboodle/main/scripts/install.sh | bash +curl -fsSL https://raw.githubusercontent.com/intigraph/tambo/main/scripts/install.sh | bash ``` Pin a release by setting the version on the receiving shell: ```bash -curl -fsSL https://raw.githubusercontent.com/scbrown/caboodle/main/scripts/install.sh | CABOODLE_VERSION=vX.Y.Z bash +curl -fsSL https://raw.githubusercontent.com/intigraph/tambo/main/scripts/install.sh | CABOODLE_VERSION=vX.Y.Z bash ``` The script still verifies the release archive's SHA256 checksum before replacing -the binary. Read the [installer source](https://github.com/scbrown/caboodle/blob/main/scripts/install.sh) +the binary. Read the [installer source](https://github.com/intigraph/tambo/blob/main/scripts/install.sh) when inspecting the bootstrap. After installation, `caboodle --version` reads back the installed release. @@ -89,7 +89,7 @@ reorder PATH. A Rust toolchain can install the reviewed revision directly: ```bash -cargo install --git https://github.com/scbrown/caboodle \ +cargo install --git https://github.com/intigraph/tambo \ --rev --locked caboodle --version ``` diff --git a/docs/book/src/introduction.md b/docs/book/src/introduction.md index d947998..8c9cc36 100644 --- a/docs/book/src/introduction.md +++ b/docs/book/src/introduction.md @@ -7,7 +7,7 @@ when. *Bitemporal* means keeping both when a fact was recorded and, when supplie when it was true. **Caboodle installs and configures this stack**, then proves the selected tools -work. [Quipu](https://scbrown.github.io/quipu/) holds the knowledge. Camayoc +work. [Quipu](https://intigraph.github.io/quipu/) holds the knowledge. Camayoc prepares knowledge and vocabulary for it. Bobbin searches code and can include knowledge from Quipu; Yupana shows code impact and can read policies from Quipu. Desire Path turns agent mistakes into feature requests and also works on its @@ -16,7 +16,7 @@ separately or connect them around the same store. Write refusal is configurable, not automatic in every installation: enable Quipu's write checks for the rules you want enforced. See -[Quipu's configuration reference](https://scbrown.github.io/quipu/getting-started/configuration.html) +[Quipu's configuration reference](https://intigraph.github.io/quipu/getting-started/configuration.html) for the settings and their defaults. ![The quipu stack loop: agents send activity to Camayoc, which sends tagged, quarantined episodes to Quipu. Quipu supplies knowledge to Bobbin, which feeds the next agent turn. Yupana enforces code policies and contributes committed structure to Quipu and code context to Bobbin. Desire Path turns hallucinations into feature requests. Seeds tracks work items in the Quipu knowledge base. Caboodle installs, proves, and observes the tools.](images/stack-loop.svg) @@ -25,7 +25,7 @@ for the settings and their defaults. ### 1. Try it in your browser -**[Open Quipu Explore — no installation](https://scbrown.github.io/quipu/explore/).** +**[Open Quipu Explore — no installation](https://intigraph.github.io/quipu/explore/).** The real store runs as WebAssembly in your browser. Use the SPARQL box, edit a fact, and export a knowledge pack. diff --git a/docs/book/src/pendant-autoload.md b/docs/book/src/pendant-autoload.md index e9fbb22..8adc330 100644 --- a/docs/book/src/pendant-autoload.md +++ b/docs/book/src/pendant-autoload.md @@ -21,7 +21,7 @@ graphs that are not loaded yet. Different shape bundles need an explicit `--shapes-from`. A nonconforming union stays in quarantine, and nothing is promoted to ROOT. A local retraction survives a reload of the same snapshot. See quipu's - [pack composition](https://scbrown.github.io/quipu/concepts/pack-composition.html). + [pack composition](https://intigraph.github.io/quipu/concepts/pack-composition.html). - **Manual loading.** `install-stack.sh --pendant PATH` loads a pack by hand, and `scripts/setup-environment.sh` stages and verifies packs in cloud environments. diff --git a/docs/book/src/reference.md b/docs/book/src/reference.md index 31bb1d8..7fac67c 100644 --- a/docs/book/src/reference.md +++ b/docs/book/src/reference.md @@ -6,7 +6,7 @@ records: ```bash # Build caboodle from source instead of the release installer. -cargo install --git https://github.com/scbrown/caboodle --locked +cargo install --git https://github.com/intigraph/tambo --locked # Report what would block an install here. Changes nothing; exits nonzero on a blocker. caboodle doctor diff --git a/docs/book/src/stack-standard.md b/docs/book/src/stack-standard.md index d78613f..2853ccd 100644 --- a/docs/book/src/stack-standard.md +++ b/docs/book/src/stack-standard.md @@ -4,10 +4,10 @@ Every public repo in the stack (caboodle, quipu, camayoc, bobbin, yupana, desire-path) follows one README shape and one theme, so a reader who knows one can find their way around the others: try it first, then this book for depth. -- [The standard](https://github.com/scbrown/caboodle/blob/main/docs/stack/README-STANDARD.md): +- [The standard](https://github.com/intigraph/tambo/blob/main/docs/stack/README-STANDARD.md): section order, theme, the shared stack block, the rules, the mdBook skeleton, and the review checklist. -- [The README template](https://github.com/scbrown/caboodle/blob/main/docs/stack/README-TEMPLATE.md): +- [The README template](https://github.com/intigraph/tambo/blob/main/docs/stack/README-TEMPLATE.md): a fill-in-the-blanks README that already meets it. Status: draft, under review with the yupana pilot before the other repos adopt it. diff --git a/docs/book/src/stack.md b/docs/book/src/stack.md index a96c181..7b086c5 100644 --- a/docs/book/src/stack.md +++ b/docs/book/src/stack.md @@ -29,7 +29,7 @@ the tool demonstrate its own job, through three proofs: Install and verification outcomes are also queued as quipu episodes, so a fresh box's first knowledge is a record of the box itself. The agent-facing version of -this workflow is the [`tambo` skill](https://github.com/scbrown/tambo/blob/main/skills/tambo/SKILL.md), and the full +this workflow is the [`tambo` skill](https://github.com/intigraph/tambo/blob/main/skills/tambo/SKILL.md), and the full design is in the [book](introduction.md). ## Related projects diff --git a/docs/book/src/using.md b/docs/book/src/using.md index 781bd92..57e19aa 100644 --- a/docs/book/src/using.md +++ b/docs/book/src/using.md @@ -4,7 +4,7 @@ Caboodle ships a resumable interview and the plan/apply/verify engine with adapters for Quipu, Camayoc, Bobbin, Yupana, and Desire Path. ```bash -cargo install --git https://github.com/scbrown/caboodle --locked +cargo install --git https://github.com/intigraph/tambo --locked # Guided: use, crew themes, and anticipated graph questions are checkpointed. caboodle init --guided diff --git a/docs/demos/bootstrap-compat/run.py b/docs/demos/bootstrap-compat/run.py index 21d7df9..4208389 100644 --- a/docs/demos/bootstrap-compat/run.py +++ b/docs/demos/bootstrap-compat/run.py @@ -21,7 +21,7 @@ source = subprocess.check_output(['git', 'show', f'{revision}:scripts/install.sh'], cwd=REPO) (root / 'scripts/install.sh').write_bytes(source) Bootstrap.run_installer.__globals__['ROOT'] = root - case = Bootstrap('test_default_uses_compatibility_repository_and_legacy_release') + case = Bootstrap('test_default_uses_canonical_repository_and_legacy_release') case.setUp() try: case.routes['https://api.github.com/repos/scbrown/caboodle/releases/latest'] = { diff --git a/docs/knowledge/repository-knowledge.json b/docs/knowledge/repository-knowledge.json index 38ccdc6..5f2cba3 100644 --- a/docs/knowledge/repository-knowledge.json +++ b/docs/knowledge/repository-knowledge.json @@ -8,7 +8,7 @@ "source": "README.md", "subject": "http://aegis.gastown.local/ontology/doc/tambo/README.md", "summary": "Tambo installs and verifies the knowledge-tool stack from a reviewable plan. The transition retains the caboodle command and existing plan/state paths; publication and installed verification remain separate.", - "source_sha256": "de96246f8a6f898be1d21d0b1f8cf21c142cb0e22db9830e26648ba7ddb13a9f", + "source_sha256": "f990353237f5e1a9c895a72bfe3fef0957f73d9db70fd0761d6f09b123518b93", "type": "Concept" }, { @@ -60,7 +60,7 @@ "source": "Cargo.toml", "subject": "http://aegis.gastown.local/ontology/code/tambo/Cargo.toml", "summary": "The package and primary command are tambo, while the Rust library import name remains caboodle and a legacy caboodle binary is explicitly declared for compatibility.", - "source_sha256": "79c08b5213243be342e58e23c1ae53091c1fce03e3e347d9fd121fba8ae799ba", + "source_sha256": "d1fbb60bb8460f96413ef15235be4b98e54dbd513793c66e339e99f286641bbc", "type": "DecisionRecord", "properties": { "status": "active", @@ -72,7 +72,7 @@ "source": "README.md", "subject": "http://aegis.gastown.local/ontology/doc/tambo/README.md", "summary": "Start with the local single-user quickstart and its verified-tool success checks before selecting remote service mode.", - "source_sha256": "de96246f8a6f898be1d21d0b1f8cf21c142cb0e22db9830e26648ba7ddb13a9f", + "source_sha256": "f990353237f5e1a9c895a72bfe3fef0957f73d9db70fd0761d6f09b123518b93", "properties": { "startHereOrder": 1, "glossaryTerm": "https://scbrown.github.io/quechua/ns#Tool" @@ -93,7 +93,7 @@ "source": "Cargo.toml", "subject": "http://aegis.gastown.local/ontology/code/tambo/Cargo.toml", "summary": "Read the declared library and binary names before integrating the crate or changing compatibility assumptions.", - "source_sha256": "79c08b5213243be342e58e23c1ae53091c1fce03e3e347d9fd121fba8ae799ba", + "source_sha256": "d1fbb60bb8460f96413ef15235be4b98e54dbd513793c66e339e99f286641bbc", "properties": { "startHereOrder": 3 } diff --git a/docs/stack-table.md b/docs/stack-table.md index c1ab2d2..36cd740 100644 --- a/docs/stack-table.md +++ b/docs/stack-table.md @@ -12,7 +12,7 @@ when. | tool | what it gives your agents | |---|---| -| [tambo](https://github.com/scbrown/tambo) | 🧰 Agent Platform Toolkit - installs and configures the quipu stack | +| [tambo](https://github.com/intigraph/tambo) | 🧰 Agent Platform Toolkit - installs and configures the quipu stack | | [quipu](https://github.com/scbrown/quipu) | stores shared facts with provenance and history; can check writes against your rules | | [camayoc](https://github.com/scbrown/camayoc) | prepares knowledge and vocabulary for Quipu, with checks before it is admitted | | [quechua](https://github.com/scbrown/quechua) | shared vocabulary and shapes for interoperable knowledge | diff --git a/docs/stack/README-TEMPLATE.md b/docs/stack/README-TEMPLATE.md index 8a81737..3b8975b 100644 --- a/docs/stack/README-TEMPLATE.md +++ b/docs/stack/README-TEMPLATE.md @@ -22,7 +22,7 @@

License: Apache-2.0 CI - Part of the caboodle stack + Part of the caboodle stack

**TOOLNAME IS A WHAT-IT-IS FOR WHO-IT-IS-FOR. It comes as a CLI, an MCP server @@ -126,7 +126,7 @@ when. | tool | what it gives your agents | |---|---| -| [tambo](https://github.com/scbrown/tambo) | 🧰 Agent Platform Toolkit - installs and configures the quipu stack | +| [tambo](https://github.com/intigraph/tambo) | 🧰 Agent Platform Toolkit - installs and configures the quipu stack | | [quipu](https://github.com/scbrown/quipu) | stores shared facts with provenance and history; can check writes against your rules | | [camayoc](https://github.com/scbrown/camayoc) | prepares knowledge and vocabulary for Quipu, with checks before it is admitted | | [quechua](https://github.com/scbrown/quechua) | shared vocabulary and shapes for interoperable knowledge | diff --git a/install.sh b/install.sh index 9b46f7c..a9c1881 100755 --- a/install.sh +++ b/install.sh @@ -1,8 +1,8 @@ #!/bin/sh set -eu -# This compatibility URL also redirects after the repository rename. -repo=${TAMBO_REPOSITORY:-${CABOODLE_REPOSITORY:-scbrown/caboodle}} +# Canonical repository; retain both Tambo and legacy Caboodle overrides. +repo=${TAMBO_REPOSITORY:-${CABOODLE_REPOSITORY:-intigraph/tambo}} version=${TAMBO_VERSION:-${CABOODLE_VERSION:-}} install_dir=${TAMBO_INSTALL_DIR:-${CABOODLE_INSTALL_DIR:-${CARGO_HOME:-$HOME/.cargo}/bin}} diff --git a/justfile b/justfile index d8ab089..5efbac9 100644 --- a/justfile +++ b/justfile @@ -21,6 +21,8 @@ check: cargo clippy --all-targets --all-features -- -D warnings cargo test --all-features scripts/test-release-install.sh + python3 scripts/test-release-repository.py + python3 scripts/test-install-bootstrap.py python3 scripts/test-crate-version.py python3 scripts/test-stack-pendants.py python3 tests/test_skill_render_source.py diff --git a/scripts/check-doc-links.sh b/scripts/check-doc-links.sh index 4b0b037..bc22287 100755 --- a/scripts/check-doc-links.sh +++ b/scripts/check-doc-links.sh @@ -25,7 +25,9 @@ if [ "$expect_root" = true ]; then fi if [ -n "$root_dir" ]; then book_uri=$(python3 -c 'from pathlib import Path; import sys; print((Path(sys.argv[1]).resolve() / "tambo").as_uri())' "$root_dir") + set -- --remap "^https://intigraph\\.github\\.io/tambo/ ${book_uri}/" "$@" set -- --remap "^https://scbrown\\.github\\.io/(caboodle|tambo)/ ${book_uri}/" "$@" fi exec lychee --config .lychee.toml \ + --remap "^https://github\\.com/intigraph/tambo/blob/main/ ${repo_uri}/" \ --remap "^https://github\\.com/scbrown/(caboodle|tambo)/blob/main/ ${repo_uri}/" "$@" diff --git a/scripts/install.sh b/scripts/install.sh index 9b46f7c..a9c1881 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,8 +1,8 @@ #!/bin/sh set -eu -# This compatibility URL also redirects after the repository rename. -repo=${TAMBO_REPOSITORY:-${CABOODLE_REPOSITORY:-scbrown/caboodle}} +# Canonical repository; retain both Tambo and legacy Caboodle overrides. +repo=${TAMBO_REPOSITORY:-${CABOODLE_REPOSITORY:-intigraph/tambo}} version=${TAMBO_VERSION:-${CABOODLE_VERSION:-}} install_dir=${TAMBO_INSTALL_DIR:-${CABOODLE_INSTALL_DIR:-${CARGO_HOME:-$HOME/.cargo}/bin}} diff --git a/scripts/setup-environment.sh b/scripts/setup-environment.sh index dfc29c2..0a21cb8 100755 --- a/scripts/setup-environment.sh +++ b/scripts/setup-environment.sh @@ -83,7 +83,7 @@ QUIPU_PID=$! ( # Prebuilt, sha256-verified release binary — seconds, not a cargo build. have caboodle || curl -fsSL \ - https://raw.githubusercontent.com/scbrown/caboodle/main/scripts/install.sh \ + https://raw.githubusercontent.com/intigraph/tambo/main/scripts/install.sh \ | sh >/dev/null 2>&1 || true ) & diff --git a/scripts/test-doc-links.py b/scripts/test-doc-links.py index d522a50..83f69d7 100644 --- a/scripts/test-doc-links.py +++ b/scripts/test-doc-links.py @@ -14,7 +14,8 @@ REPO = Path(__file__).resolve().parent.parent OWN = "https://github.com/scbrown/caboodle/blob/main/" -CANONICAL = "https://github.com/scbrown/tambo/blob/main/" +LEGACY = "https://github.com/scbrown/tambo/blob/main/" +CANONICAL = "https://github.com/intigraph/tambo/blob/main/" TARGETS = [ "skills/tambo/SKILL.md", "docs/design/txtai-gap-analysis.md", @@ -57,14 +58,14 @@ def test_actual_five_targets_checked_not_excluded_and_deleted_target_fails(self) dest = self.root / target dest.parent.mkdir(parents=True, exist_ok=True) shutil.copyfile(REPO / target, dest) - links = [prefix + target for prefix in (OWN, CANONICAL) for target in TARGETS] + links = [prefix + target for prefix in (OWN, LEGACY, CANONICAL) for target in TARGETS] rc, result = self.check(links) self.assertEqual(rc, 0, result) - self.assertEqual((result["successful"], result["remaps"], result["excludes"]), (10, 10, 0)) + self.assertEqual((result["successful"], result["remaps"], result["excludes"]), (15, 15, 0)) (self.root / TARGETS[0]).unlink() rc, result = self.check(links) self.assertNotEqual(rc, 0) - self.assertEqual((result["successful"], result["errors"], result["excludes"]), (8, 2, 0)) + self.assertEqual((result["successful"], result["errors"], result["excludes"]), (12, 3, 0)) self.assertIn("SKILL.md", json.dumps(result["error_map"])) def test_existing_anchor_passes_missing_anchor_fails(self): @@ -83,13 +84,13 @@ def test_own_pages_anchor_uses_fresh_build(self): page.write_text('

Why use it

') link = "https://scbrown.github.io/caboodle/introduction.html#why-use-it" canonical = "https://scbrown.github.io/tambo/introduction.html#why-use-it" - rc, result = self.check([link, canonical]) + rc, result = self.check([link, canonical, "https://intigraph.github.io/tambo/introduction.html#why-use-it"]) self.assertEqual(rc, 0, result) - self.assertEqual((result["successful"], result["remaps"], result["excludes"]), (2, 2, 0)) + self.assertEqual((result["successful"], result["remaps"], result["excludes"]), (3, 3, 0)) page.write_text('

New heading

') - rc, result = self.check([link, canonical]) + rc, result = self.check([link, canonical, "https://intigraph.github.io/tambo/introduction.html#why-use-it"]) self.assertNotEqual(rc, 0, result) - self.assertEqual((result["errors"], result["excludes"]), (2, 0)) + self.assertEqual((result["errors"], result["excludes"]), (3, 0)) def test_other_pages_books_are_not_remapped(self): rc, result = self.check([ @@ -111,10 +112,13 @@ def test_other_owner_repo_and_branch_are_not_remapped(self): "https://github.com/scbrown/caboodle/tree/main/missing.md", "https://github.com/other/tambo/blob/main/missing.md", "https://github.com/scbrown/tambo/blob/v1.0.0/missing.md", + "https://github.com/intigraph/other/blob/main/missing.md", + "https://github.com/intigraph/tambo/blob/v1.0.0/missing.md", + "https://github.com/intigraph/tambo/tree/main/missing.md", ] rc, result = self.check(links) self.assertEqual(rc, 0, result) - self.assertEqual((result["remaps"], result["excludes"], result["successful"]), (0, 6, 0)) + self.assertEqual((result["remaps"], result["excludes"], result["successful"]), (0, 9, 0)) def test_normal_mode_still_checks_unrelated_remote_failure(self): # A real disposable HTTP server supplies a positive 200 control and a diff --git a/scripts/test-install-bootstrap.py b/scripts/test-install-bootstrap.py index 467dfc8..8373f78 100644 --- a/scripts/test-install-bootstrap.py +++ b/scripts/test-install-bootstrap.py @@ -70,7 +70,7 @@ def archive(self, prefix, version, members, corrupt_checksum=False): checksum = '0' * 64 if corrupt_checksum else hashlib.sha256(path.read_bytes()).hexdigest() self.routes[f'{self.base}/{name}.sha256'] = {'status': 200, 'body': f'{checksum} {name}\n'} - def run_installer(self, version=None): + def run_installer(self, version=None, repository=None, legacy_repository=None): route_file = self.root / 'routes.json' route_file.write_text(json.dumps(self.routes)) env = {k: v for k, v in os.environ.items() if not k.startswith(('TAMBO_', 'CABOODLE_'))} @@ -79,6 +79,10 @@ def run_installer(self, version=None): CABOODLE_INSTALL_DIR=str(self.root / 'installed'), CABOODLE_TARGET=self.target, CABOODLE_RELEASE_BASE_URL=self.base, FIXTURE_ROUTES=str(route_file), FIXTURE_REQUESTS=str(self.requests)) + if repository is not None: + env['TAMBO_REPOSITORY'] = repository + if legacy_repository is not None: + env['CABOODLE_REPOSITORY'] = legacy_repository if version: env['CABOODLE_VERSION'] = version self.result = subprocess.run(['bash', str(ROOT / 'scripts/install.sh')], env=env, @@ -91,15 +95,32 @@ def assert_installed(self, names): for name in names: self.assertTrue(os.access(self.root / 'installed' / name, os.X_OK)) - def test_default_uses_compatibility_repository_and_legacy_release(self): - self.routes['https://api.github.com/repos/scbrown/caboodle/releases/latest'] = { + def test_default_uses_canonical_repository_and_legacy_release(self): + self.routes['https://api.github.com/repos/intigraph/tambo/releases/latest'] = { 'status': 200, 'body': '{"tag_name":"v0.2.23"}\n'} self.archive('caboodle', 'v0.2.23', ['caboodle']) self.run_installer() self.assert_installed(['caboodle']) - self.assertIn('https://api.github.com/repos/scbrown/caboodle/releases/latest', + self.assertIn('https://api.github.com/repos/intigraph/tambo/releases/latest', self.requests.read_text().splitlines()) + def test_legacy_repository_override_still_works(self): + url = 'https://api.github.com/repos/scbrown/caboodle/releases/latest' + self.routes[url] = {'status': 200, 'body': '{"tag_name":"v0.2.23"}'} + self.archive('caboodle', 'v0.2.23', ['caboodle']) + self.run_installer(legacy_repository='scbrown/caboodle') + self.assert_installed(['caboodle']) + self.assertIn(url, self.requests.read_text().splitlines()) + + def test_tambo_repository_override_wins_over_legacy(self): + url = 'https://api.github.com/repos/fixture-owner/tambo/releases/latest' + self.routes[url] = {'status': 200, 'body': '{"tag_name":"v0.2.23"}'} + self.archive('caboodle', 'v0.2.23', ['caboodle']) + self.run_installer(repository='fixture-owner/tambo', legacy_repository='scbrown/caboodle') + self.assert_installed(['caboodle']) + self.assertIn(url, self.requests.read_text().splitlines()) + self.assertNotIn('repos/scbrown/caboodle', self.requests.read_text()) + def test_pinned_legacy_release(self): self.archive('caboodle', 'v0.2.23', ['caboodle']) self.run_installer('v0.2.23') diff --git a/scripts/test-readme.sh b/scripts/test-readme.sh index 28e26bc..8dcc12f 100755 --- a/scripts/test-readme.sh +++ b/scripts/test-readme.sh @@ -26,7 +26,7 @@ install = text.split("## Install", 1)[1].split("## First success", 1)[0] local = text.split("## First success", 1)[1].split("### Advanced:", 1)[0] bootstrap = re.findall(r"```bash\n(.*?)```", install, re.S)[0] # Exercise this proposal's installer rather than fetching unrelated main bytes. -bootstrap = bootstrap.replace('https://raw.githubusercontent.com/scbrown/tambo/main/install.sh', pathlib.Path(sys.argv[1]).parent.joinpath('install.sh').as_uri()) +bootstrap = bootstrap.replace('https://raw.githubusercontent.com/intigraph/tambo/main/install.sh', pathlib.Path(sys.argv[1]).parent.joinpath('install.sh').as_uri()) commands = re.findall(r"```bash\n(.*?)```", local, re.S) assert commands == ["tambo quickstart\n", "tambo verify\n"], commands pathlib.Path(sys.argv[2]).write_text(bootstrap + '\nexport PATH="${CARGO_HOME:-$HOME/.cargo}/bin:$PATH"\n' + "\n".join(commands)) diff --git a/scripts/test-release-repository.py b/scripts/test-release-repository.py new file mode 100644 index 0000000..029ef91 --- /dev/null +++ b/scripts/test-release-repository.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Replay the actual canonical-repository release step without publishing. + +# arming: just check and CI; cargo metadata is an owned fixture, not a build. +""" +import json +import os +from pathlib import Path +import subprocess +import tempfile +import tomllib +import unittest + +ROOT = Path(__file__).resolve().parents[1] + + +def release_step(): + workflow = (ROOT / '.github/workflows/release.yml').read_text() + start = workflow.index(' - name: Require the canonical repository and matching tag\n') + block = workflow[start:].split(' run: |\n', 1)[1] + lines = [] + for row in block.splitlines(): + if row and not row.startswith(' '): + break + lines.append(row[10:]) + return '\n'.join(lines) + + +class CanonicalRelease(unittest.TestCase): + def setUp(self): + self.directory = tempfile.TemporaryDirectory(prefix='release-repository-') + self.addCleanup(self.directory.cleanup) + self.root = Path(self.directory.name) + self.env_file = self.root / 'env' + version = tomllib.loads((ROOT / 'Cargo.toml').read_text())['package']['version'] + self.version = version + cargo = self.root / 'cargo' + cargo.write_text('#!/bin/sh\nprintf \'%s\\n\' \'' + json.dumps( + {'packages': [{'name': 'tambo', 'version': version}]}) + "'\n") + cargo.chmod(0o755) + + def run_step(self, repository, tag=None): + env = dict(os.environ, PATH=str(self.root) + ':/usr/bin:/bin', + VERSION=tag or 'v' + self.version, GITHUB_ENV=str(self.env_file)) + if repository is None: + env.pop('GITHUB_REPOSITORY', None) + else: + env['GITHUB_REPOSITORY'] = repository + return subprocess.run(['bash', '-c', release_step()], env=env, + capture_output=True, text=True, timeout=10) + + def test_canonical_repository_and_matching_tag_pass(self): + result = self.run_step('intigraph/tambo') + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(self.env_file.read_text(), 'TAMBO_PUBLISH_VERSION=' + self.version + '\n') + + def test_foreign_legacy_near_miss_and_missing_repository_refuse(self): + for repository in ('foreign/tambo', 'scbrown/tambo', 'intigraph/tambo-fork', None): + with self.subTest(repository=repository): + self.assertNotEqual(self.run_step(repository).returncode, 0) + self.assertFalse(self.env_file.exists()) + + def test_wrong_tag_still_refuses(self): + self.assertNotEqual(self.run_step('intigraph/tambo', 'v0.0.0-invalid').returncode, 0) + self.assertFalse(self.env_file.exists()) + + +if __name__ == '__main__': + unittest.main() diff --git a/skills/caboodle/SKILL.md b/skills/caboodle/SKILL.md index 7e82c6f..84b5420 100644 --- a/skills/caboodle/SKILL.md +++ b/skills/caboodle/SKILL.md @@ -14,7 +14,7 @@ For CABOODLE itself, prefer the reviewed checksummed release path documented in `docs/book/src/installing.md`. A source install must pin a reviewed commit. 1. If `caboodle` is absent and the request authorizes installation, install the public source with: - `cargo install --git https://github.com/scbrown/caboodle --locked`. + `cargo install --git https://github.com/intigraph/tambo --locked`. Otherwise stop and request authorization; bootstrapping CABOODLE is itself an installation. 2. Prove the binary answers: `caboodle --version`. diff --git a/skills/tambo/SKILL.md b/skills/tambo/SKILL.md index 1a3b724..8f2b62f 100644 --- a/skills/tambo/SKILL.md +++ b/skills/tambo/SKILL.md @@ -18,7 +18,7 @@ For Tambo itself, prefer the reviewed checksummed release path documented in `docs/book/src/installing.md`. A source install must pin a reviewed commit. 1. If `tambo` is absent and the request authorizes installation, install the public source with: - `cargo install --git https://github.com/scbrown/caboodle --bin tambo --locked`. + `cargo install --git https://github.com/intigraph/tambo --bin tambo --locked`. The compatibility repository URL remains valid through the repository rename. Otherwise stop and request authorization; bootstrapping Tambo is itself an installation.