Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
cf5f397
feat(serve): degrade to no-index MCP server instead of exiting on mis…
tachyon-beep Jun 5, 2026
49a6753
docs(adr): ADR-044 read-API ephemeral port; stopgap 9112; wardline to…
tachyon-beep Jun 5, 2026
d4e0474
docs(adr): pin ADR-044 ephemeral-port file as normative cross-product…
tachyon-beep Jun 5, 2026
a0731d4
feat(federation): loomweave_port — deterministic read-API port + atom…
tachyon-beep Jun 5, 2026
adc3122
refactor(federation): loomweave_port publish uses canonical path + cl…
tachyon-beep Jun 5, 2026
69e1ff5
feat(config): serve.http.bind is Option<SocketAddr>; None auto-select…
tachyon-beep Jun 5, 2026
02a7a90
refactor(config): pattern-match HttpReadConfig bind instead of expect…
tachyon-beep Jun 5, 2026
ba8233a
feat(serve): auto-select read-API port with ephemeral fallback; publi…
tachyon-beep Jun 5, 2026
0b4df33
test(serve): cover ephemeral fallback when deterministic read-API por…
tachyon-beep Jun 5, 2026
c102297
feat(install): YAML stub no longer pins serve.http.bind 9111 (ADR-044)
tachyon-beep Jun 5, 2026
7cf7782
feat(install): integration bindings use per-project deterministic loo…
tachyon-beep Jun 5, 2026
efd2285
fix(install): strip stale auto-stamped serve.http.bind 127.0.0.1:9111…
tachyon-beep Jun 5, 2026
461614e
feat(doctor): resolve_loomweave_url + doctor reports live published r…
tachyon-beep Jun 5, 2026
d0b15b3
test(federation): cover blank-config SOURCE_NONE path in resolve_loom…
tachyon-beep Jun 5, 2026
046c341
docs(adr): accept ADR-044; auto-port docs, glossary verdict, revert 9…
tachyon-beep Jun 5, 2026
85d9cd1
docs(plan): ADR-044 ephemeral-port implementation plan
tachyon-beep Jun 5, 2026
c7f2530
fix(adr-044): gitignore ephemeral.port template, wire project_status …
tachyon-beep Jun 5, 2026
b3f58a6
chore(release): bump to 1.1.0rc1 (Cargo 1.1.0-rc1 / PEP440 1.1.0rc1)
tachyon-beep Jun 6, 2026
7ff84b2
fix(install): gitignore instance_id + *.lock; document live-index com…
tachyon-beep Jun 6, 2026
69ebadd
fix(storage): checkpoint WAL(TRUNCATE) after each committed run; surf…
tachyon-beep Jun 6, 2026
032425c
feat(mcp): worktree-aware staleness — indexed_at_commit + StaleWorktr…
tachyon-beep Jun 6, 2026
5da9ccd
docs(getting-started): macOS Gatekeeper quarantine workaround (V11-CI…
tachyon-beep Jun 6, 2026
b598ebf
chore(storage): backfill ADR-024 published_build marker to v1.0.0
tachyon-beep Jun 6, 2026
3c8feae
ci(release): add macOS aarch64 verify gate mirroring ci.yml (clarion-…
tachyon-beep Jun 6, 2026
8be269d
fix(storage): drop dead entity_fts.content_text column (migration 000…
tachyon-beep Jun 6, 2026
5675f4a
chore(release): bump to 1.1.0rc2 (Cargo 1.1.0-rc2 / PEP440 1.1.0rc2)
tachyon-beep Jun 6, 2026
0a93731
feat(cli): inject agent-orientation block into CLAUDE.md/AGENTS.md (i…
tachyon-beep Jun 6, 2026
af435c4
fix(plugin): leave RLIMIT_NPROC uncapped for pyright-runtime plugins;…
tachyon-beep Jun 6, 2026
86355a0
chore(release): bump to 1.1.0rc3 (Cargo 1.1.0-rc3 / PEP440 1.1.0rc3)
tachyon-beep Jun 6, 2026
6938cf1
docs: agent-first experience report from elspeth dogfooding session
tachyon-beep Jun 6, 2026
91e79d2
docs(ci): rebrand stale Clarion->Loomweave in release.yml cosign comm…
tachyon-beep Jun 6, 2026
9328e8f
fix(config): fail-loud LLM config + discoverability (agent-first-feed…
tachyon-beep Jun 6, 2026
2504fc4
fix(lint): satisfy clippy + rustdoc in the §2 config work
tachyon-beep Jun 6, 2026
d7aa778
feat(federation): adopt WEFT_FEDERATION_TOKEN as the federation token…
tachyon-beep Jun 6, 2026
700a315
feat(weft): consolidate store to .weft/loomweave/ + .weft-only siblin…
tachyon-beep Jun 7, 2026
c4e19fb
test(ci): bound nextest slow-timeout so `--workspace` completes inste…
tachyon-beep Jun 7, 2026
72544dd
fix(cli): analyze summary reports whole-graph totals + incremental ma…
tachyon-beep Jun 7, 2026
f4d1ce1
fix(docs): update references from `.loomweave/` to `.weft/loomweave/`…
tachyon-beep Jun 7, 2026
00aaa85
chore(git): untrack .filigree.conf and gitignore it
tachyon-beep Jun 7, 2026
7575344
fix(mcp): correct args and type order for filigree server configuration
tachyon-beep Jun 7, 2026
208d090
fix(config): tolerate sibling analysis: section in McpConfig (clarion…
tachyon-beep Jun 7, 2026
b7a1b30
fix(install): gitignore loomweave.db by default — reverse ADR-005 (we…
tachyon-beep Jun 7, 2026
234fe7f
docs(proposal): draft shared weft.toml key layout for hub blessing (w…
tachyon-beep Jun 7, 2026
1b1c258
feat(db): add `loomweave db checkpoint` WAL-truncate verb (C-2, weft-…
tachyon-beep Jun 7, 2026
b66c58d
fix(findings): content-keyed finding ids — dedupe across re-analyses …
tachyon-beep Jun 7, 2026
cb49008
feat(mcp): whole-project finding browser + has_findings filter; hones…
tachyon-beep Jun 7, 2026
982b463
feat(findings): stale-finding sweep — retire findings whose code no l…
tachyon-beep Jun 8, 2026
8759d16
feat(doctor): detect a git-tracked runtime DB and self-heal under --f…
tachyon-beep Jun 8, 2026
6057b69
feat(doctor): index-DB health check + git-tracked-DB gate (C1, schema)
tachyon-beep Jun 8, 2026
ec12c83
fix(doctor): write the project-scoped wardline→filigree bridge URL (o…
tachyon-beep Jun 8, 2026
a91483a
ci: extract reusable verify.yml; ci.yml + release.yml call it (V11-CI…
tachyon-beep Jun 8, 2026
9987982
fix: PR#21 deferred review findings — TOCTOU repair, schema-validated…
tachyon-beep Jun 8, 2026
78c8402
feat(mcp): Wardline trust boundaries as find_dead_code roots (clarion…
tachyon-beep Jun 8, 2026
304941e
refactor(core): split plugin/host.rs validators into host_validate.rs…
tachyon-beep Jun 8, 2026
1670aa5
feat(federation): weft.toml cross-read sibling-endpoint reader (clari…
tachyon-beep Jun 8, 2026
aba5c67
docs(storage): fix broken intra-doc link in reject_unmigrated_for_read
tachyon-beep Jun 8, 2026
a863751
docs: correct resolver precedence docs (164f) + document store_dir sk…
tachyon-beep Jun 8, 2026
ce02958
test(secret-scan): lock briefing_blocked-survives-reanalysis invarian…
tachyon-beep Jun 8, 2026
1015274
fix(storage): entity_find content+substring recall so discovery beats…
tachyon-beep Jun 8, 2026
fcd7978
docs(skill): reflect entity_find content recall + project_finding_lis…
tachyon-beep Jun 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions .agents/skills/loomweave-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ calls this?" without reading a single file.
- You need a function's neighborhood, execution paths, or which subsystem it belongs to.

**Not for:** editing code, reading exact implementation bodies (use `summary` or
read the file once you have its path), or codebases with no `.loomweave/` index.
read the file once you have its path), or codebases with no `.weft/loomweave/` index.

## Entity IDs — the model

Expand Down Expand Up @@ -65,18 +65,27 @@ tell which case you're in.
| `execution_paths_from` | bounded call paths out of an entity | `{"id": "<id>", "max_depth": 5}` |
| `subsystem_members` | modules in a subsystem | `{"id": "core:subsystem:<hash>"}` |
| `subsystem_of` | the subsystem an entity belongs to (reverse of `subsystem_members`) | `{"id": "<id>"}` |
| `summary` | on-demand prose summary of one entity | `{"id": "<id>"}` |
| `summary` | on-demand prose summary of one entity | `{"id": "<id>"}` |
| `summary_preview_cost` | preview a `summary` call's cache status / cost before spending | `{"id": "<id>"}` |
| `issues_for` | Filigree issues attached to an entity | `{"id": "<id>"}` |
| `source_for_entity` | an entity's exact indexed source span + bounded context | `{"id": "<id>", "context_lines": 10}` |
| `call_sites` | the source line(s) behind a calls/references edge | `{"id": "<id>", "role": "caller"}` |
| `orientation_pack` | one deterministic orientation packet for an entity or file:line (entity + context + neighbors + paths + issues + freshness) | `{"file": "rel/path.py", "line": 42}` |
| `index_diff` | index freshness / drift vs. the current working tree | `{}` |
| `analyze_start` | launch a background re-index, return its `run_id` | `{}` |
| `analyze_start` | launch a background re-index, return its `run_id` | `{}` |
| `analyze_status` | poll a started analyze (queued/running/terminal + progress) | `{"run_id": "<id>"}` |
| `analyze_cancel` | stop a running analyze (group-kills plugin + Pyright) | `{"run_id": "<id>"}` |
| `analyze_cancel` | stop a running analyze (group-kills plugin + Pyright) | `{"run_id": "<id>"}` |
| `project_status` | index freshness, counts, LLM + Filigree status | `{}` |

† **Write-gated.** `summary` (`entity_summary_get`), `analyze_start`,
`analyze_cancel`, `propose_guidance`, and `promote_guidance` are registered only
when `serve.mcp.enable_write_tools: true` is set in `loomweave.yaml` (default
`false`). When the gate is off they do not appear in `tools/list` and a call
returns a tool-disabled error — run `loomweave config check` to see the active
policy. `summary` additionally requires the live LLM provider to be enabled
(`llm_policy.enabled: true` + `allow_live_provider: true`), or it serves cache
only.

`callers_of` / `neighborhood` / `execution_paths_from` take a `confidence`
tier — one of `"resolved"` (default; only high-confidence edges),
`"ambiguous"`, or `"inferred"`. There is no `"all"` value. When you suspect an
Expand Down Expand Up @@ -152,7 +161,7 @@ honest-empty unless a plugin emits those tags. Likewise `high_churn` and

`search_semantic` is also in the catalogue. It is opt-in under
`semantic_search:`; when enabled, `loomweave analyze` populates the git-ignored
`.loomweave/embeddings.db` sidecar and the query path filters stale vectors by
`.weft/loomweave/embeddings.db` sidecar and the query path filters stale vectors by
content hash.

> Not in this catalogue: `emit_observation` as a general-purpose write surface.
Expand All @@ -163,6 +172,7 @@ for team sharing). Agents may call `propose_guidance` to create a Filigree
observation, but that proposal is inert until an operator promotes it through
`promote_guidance` or the CLI. Promoted sheets reach you through `guidance_for`
and are composed into `summary` prompts with a real guidance fingerprint.
(`propose_guidance` and `promote_guidance` are write-gated — see the † note above.)

## Workflow: orient, then navigate

Expand Down Expand Up @@ -192,7 +202,7 @@ and are composed into `summary` prompts with a real guidance fingerprint.

## Launch

`loomweave serve --path <dir>` where `<dir>` contains `.loomweave/loomweave.db`
`loomweave serve --path <dir>` where `<dir>` contains `.weft/loomweave/loomweave.db`
(built by `loomweave analyze <dir>`). In an MCP client the tools appear as
`mcp__loomweave__find_entity`, etc.

Expand Down
65 changes: 65 additions & 0 deletions .agents/skills/wardline-gate/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
name: wardline-gate
description: >
Use when scanning for or fixing trust-boundary / taint findings, when a
`wardline scan` reports a defect, or when wiring wardline into an agent's
edit-verify loop. Explains the scan -> explain -> fix-at-the-boundary ->
rescan cycle and the baseline-vs-waiver discipline.
---

# Wardline: the trust-boundary gate

Wardline is a deterministic, whole-program static taint analyzer. It marks trust
boundaries with two decorators from `wardline.decorators`: `@external_boundary`
(untrusted data arriving from outside) and `@trusted` (a producer that must only
receive validated data). When untrusted data reaches a trusted producer it raises
`PY-WL-101` at `ERROR`.

## The loop

1. **Scan.** Run `wardline scan . --fail-on ERROR` (or call the `scan` MCP tool).
Read the gate verdict and the active (non-suppressed) findings — `active` is
the population the gate enforces on.
2. **Explain.** For each active defect, call `explain_taint` with the finding's
`fingerprint`, `path`+`line`, and its `qualname` as `sink_qualname`. Do this
right after the scan and before editing — a stale fingerprint returns an error.
With a Loomweave store configured, pass `chain: true` to walk the full taint
chain back to the originating boundary.
3. **Fix at the BOUNDARY, not the sink.** Add validation or rejection at the hop
where untrusted data should have been checked — not a band-aid at the sink.
4. **Re-scan.** Confirm the finding is gone.

## Exit codes (CLI path)

- `0` — clean (or gate not requested).
- `1` — the gate tripped: a non-suppressed defect at/above `--fail-on`.
- `2` — a wardline error (bad config, unreadable path). Not a finding.

Branch on the code. On a trip, read the structured report wardline just wrote —
the finding names the function, file, and lines, which is enough to locate the
leak.

## Suppression discipline

Prefer FIXING a finding. Suppress only a finding you have judged a true
non-issue, always with a reason:

- MCP `baseline` — snapshot current defects so only NEW findings surface.
`overwrite: false` (default) refuses to clobber an existing baseline;
`overwrite: true` re-derives it. A coarse, whole-set tool; requires a reason.
- `waiver_add` — waive ONE finding by fingerprint with a mandatory reason and an
expiry date. An audited, time-boxed exception.
- `wardline judge` (opt-in, network) — an LLM pass that labels each defect
TRUE/FALSE positive. Never runs automatically, never folded into scan; fails
loud with no API key so "couldn't triage" is never mistaken for "nothing to
triage". Above-floor false positives can be recorded as audited suppressions.

## CLI vs MCP

- **CLI:** `wardline scan`, `wardline judge`, `wardline baseline create/update`.
Branch on the exit code; read the findings file it writes.
- **MCP:** `wardline mcp` exposes `scan`, `explain_taint`, `fix`, `judge`
(network), `baseline`, `waiver_add`; resources
`wardline://vocab|rules|config|config-schema`; and the `wardline:loop` prompt.
The server is stateless — the read-only tools are pure functions of your code
on disk and your config.
15 changes: 15 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# Bound every test's wall-clock so `cargo nextest run --workspace` always
# *completes* (and reports) instead of hanging. The pre-existing emission tests
# tracked by clarion-1d405be546 hang indefinitely; without a cap the literal CI
# command (CLAUDE.md "Build, test, lint") can never run clean, forcing a
# "green via family-exclusion" caveat. With the cap, a hung test is terminated
# and reported as a timeout failure — honestly red, fast — and clarion-1d405be546
# remains its owner's bug to fix (the cap does not fix it).
#
# `terminate-after` counts `period`s: a test slow past `period` is warned (SLOW),
# and killed after `period * terminate-after`. The period sits well above the
# slowest legitimate test (the single-threaded serve-http integration tests) with
# CI-runner headroom, so only a genuine hang trips it.
[profile.default]
slow-timeout = { period = "60s", terminate-after = 3 }

[test-groups]
serve-http = { max-threads = 1 }

Expand Down
6 changes: 0 additions & 6 deletions .filigree.conf

This file was deleted.

220 changes: 5 additions & 215 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,219 +9,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
RUSTFLAGS: "-D warnings"

jobs:
rust:
name: Rust
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10
with:
# Full history so the ADR-024 migration-retirement guard can resolve
# the published_build.txt ref via `git show <ref>:0001` (the marker
# names a commit SHA, which a shallow checkout can't read). Mirrors
# the release.yml verify job. clarion-12667da9f5 / clarion-0106a61480.
fetch-depth: 0

- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
with:
toolchain: stable
components: clippy, rustfmt, llvm-tools-preview

- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32

# Python is used by the migration-retirement guard and lockstep guards
# below. Pin >= 3.11 explicitly so the stdlib `tomllib` is available
# regardless of which Python the runner image happens to preinstall.
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: "3.11"

- name: fmt
run: cargo fmt --all -- --check

- name: migration retirement guard
run: |
python scripts/check-migration-retirement.py --self-test
python scripts/check-migration-retirement.py

- name: cross-workspace version lockstep
run: python scripts/check-workspace-version-lockstep.py

- name: pyright pin lockstep
run: |
python scripts/check-pyright-pin-lockstep.py --self-test
python scripts/check-pyright-pin-lockstep.py

- name: wardline version bounds
run: |
python scripts/check-wardline-version-bounds.py --self-test
python scripts/check-wardline-version-bounds.py

- name: entity-cap ADR/code lockstep
run: |
python scripts/check-entity-cap-lockstep.py --self-test
python scripts/check-entity-cap-lockstep.py

- name: clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings

- name: install cargo-nextest
uses: taiki-e/install-action@e310bff3ef77234d477d6bb655da153a5c49d1db

# Ensure all workspace binaries (notably loomweave-plugin-fixture) are built
# before nextest runs. wp2_e2e tests need the fixture binary on disk and
# nextest's CARGO_BIN_EXE_* propagation is not reliably set for cross-package
# dev-dep binaries (deferred issue clarion-adeff0916d).
- name: build workspace bins
run: cargo build --workspace --bins

- name: test
run: cargo nextest run --workspace --all-features --no-tests=pass

- name: doc
run: cargo doc --workspace --no-deps --all-features
env:
RUSTDOCFLAGS: "-D warnings"

- name: install cargo-deny
uses: taiki-e/install-action@2e721ffcfc34740897fc3130e2dd782b1c136896

- name: deny
run: cargo deny check

# macOS build + lint parity. The release matrix was the first place macOS was
# ever compiled, so a macOS-only `-D warnings` regression stayed invisible
# until tag-cut (clarion-12667da9f5). This native runner job closes that gap.
# It mirrors only the Linux job's clippy + bin build — the Python guards are
# platform-independent and already covered by the `rust` job. No `--target`
# flag: native builds avoid the ring C-build-script failure seen when
# cross-compiling Linux -> macOS.
#
# Only aarch64-apple-darwin (macos-14) runs here: the x86_64 (macos-13) leg is
# temporarily dropped while those runners are offline/unreliable. Restore it
# when macos-13 runner health recovers (clarion-12667da9f5 follow-up). The
# unused-symbol class this gate guards is `target_os = "macos"`, i.e.
# arch-independent, so aarch64 coverage catches the same regressions.
rust-macos:
name: Rust (${{ matrix.target }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- target: aarch64-apple-darwin
runner: macos-14
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10

- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
with:
toolchain: stable
components: clippy

- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32
with:
key: ${{ matrix.target }}

- name: clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings

- name: build workspace bins
run: cargo build --workspace --bins

python-plugin:
name: Python plugin
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: "3.11"
cache: pip
cache-dependency-path: plugins/python/uv.lock

- name: cache pyright runtime
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae
with:
path: ~/.cache/pyright-python/
key: pyright-python-1.1.409-${{ runner.os }}

- name: check Python ontology version lockstep
run: |
python scripts/check-python-ontology-version.py --self-test
python scripts/check-python-ontology-version.py

- name: install uv
run: python -m pip install uv==0.10.2

- name: sync plugin (locked dev extras)
run: uv sync --project plugins/python --locked --extra dev

- name: audit locked Python dependencies
run: |
uv export --project plugins/python --locked --extra dev --no-emit-project \
--format requirements.txt \
--output-file /tmp/loomweave-python-dev-requirements.txt
uv run --project plugins/python --extra dev pip-audit \
-r /tmp/loomweave-python-dev-requirements.txt

- name: check B.4*/B.5 performance gates
run: uv run --project plugins/python --extra dev python scripts/check-b4-gate-result.py --run-b5-smoke

- name: ruff check
run: uv run --project plugins/python --extra dev ruff check plugins/python

- name: ruff format check
run: uv run --project plugins/python --extra dev ruff format --check plugins/python

- name: mypy
run: uv run --project plugins/python --extra dev mypy --strict plugins/python

- name: pytest
run: uv run --project plugins/python --extra dev pytest plugins/python

walking-skeleton:
name: Sprint 1 walking skeleton (end-to-end)
runs-on: ubuntu-latest
needs: [rust, python-plugin]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10

- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
with:
toolchain: stable

- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
with:
python-version: "3.11"
cache: pip
cache-dependency-path: plugins/python/pyproject.toml

- name: cache pyright runtime
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae
with:
path: ~/.cache/pyright-python/
key: pyright-python-1.1.409-${{ runner.os }}

- name: install sqlite3 cli
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends sqlite3

- name: run walking skeleton
run: bash tests/e2e/sprint_1_walking_skeleton.sh

- name: run WP5 secret scanner smoke
run: CARGO_BUILD=0 bash tests/e2e/wp5_secret_scan.sh

- name: Sprint 2 MCP surface
run: CARGO_BUILD=0 bash tests/e2e/sprint_2_mcp_surface.sh

- name: Phase 3 subsystems
run: CARGO_BUILD=0 bash tests/e2e/phase3_subsystems.sh
# Every gate lives in the reusable verify.yml so CI and the release pre-publish
# gate share one definition and cannot drift (V11-CI-01, clarion-c9f62eec7d).
verify:
name: Verify
uses: ./.github/workflows/verify.yml
Loading
Loading