Skip to content

feat: no-index MCP chirp + ADR-044 ephemeral port + dogfood/v1.1 cleanups (1.1.0-rc2)#55

Closed
tachyon-beep wants to merge 27 commits into
mainfrom
feat/serve-no-index-chirp
Closed

feat: no-index MCP chirp + ADR-044 ephemeral port + dogfood/v1.1 cleanups (1.1.0-rc2)#55
tachyon-beep wants to merge 27 commits into
mainfrom
feat/serve-no-index-chirp

Conversation

@tachyon-beep

@tachyon-beep tachyon-beep commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

This PR bundles related loomweave serve improvements plus a batch of dogfood-friction fixes and deferred v1.1 engineering cleanups (see commit groups). Ships as 1.1.0-rc2.

1. No-index MCP chirp (cf5f397)

serve no longer exits 1 when there is no index. It serves a degraded MCP stdio session that answers initialize and chirps "run loomweave install + loomweave analyze" from every tool call, so the MCP client connects and is told how to recover instead of staring at a server that died at startup.

2. ADR-044 — read-API ephemeral port publication (a0731d4..c7f2530)

Fixes the cross-project 127.0.0.1:9111 collision: every project's loomweave serve bound the same hardcoded port, so two could not run concurrently and consumers mis-targeted each other's instances.

  • Deterministic per-project port (loomweave_port::deterministic_port, blake3 band 9400–10399, disjoint from Filigree's 8400–9399) with an OS-ephemeral :0 fallback when the deterministic port is taken (auto only — an explicit operator bind in use stays a hard error).
  • Publishes the live port to .loomweave/ephemeral.port — a normative cross-product file contract (port-only ASCII + optional \n, atomic temp+rename, loopback-only, RAII-removed on clean shutdown/error/panic). Stale-file/crash cases are tolerated; the ADR-034 instance-ID guard is the correctness backstop.
  • HttpReadConfig.bind: Option<SocketAddr>None (the new default) auto-selects; Some(addr) is honored verbatim.
  • Consume-time resolver resolve_loomweave_url (precedence: explicit > published file > config > none), the reference reader Wardline's Python twin mirrors. Reported by doctor and project_status_get.
  • Installer stops pinning 9111: the YAML stub omits bind; integration_bindings writes the per-project deterministic URL and self-heals the old bind: 127.0.0.1:9111 stamp on repair.
  • ADR-044 accepted (glossary managed-clash verdict vs Filigree's .filigree/ephemeral.port). Closes clarion-7f574bc34f.

Wardline-side consume-time resolution remains a separate follow-up (its own repo), captured in ADR-044's Related follow-up.

3. Dogfood-friction fixes + deferred v1.1 cleanups (7ff84b2..5675f4a)

Resolves the actionable loomweave-impacting tickets from the 2026-06-06 dogfood report and several deferred v1.1 gap-register items. Each is its own commit.

  • Worktree-aware staleness (ADR-045, 032425c). Snapshot/project_status_get/loomweave://context/session-start banner gain indexed_at_commit + worktree_dirty; a new Staleness::StaleWorktree verdict fires when an otherwise-fresh index has untracked source. Detection uses a hardened, hash-free git ls-files --others scoped to ingested source extensions (false-positive guard), proven filter-RCE-safe by the ls_files_others_does_not_run_clean_filter test. Closes clarion-26c7e52027 + clarion-d9cf8bcfa9.
  • *.loomweave/.gitignore instance_id + .lock (ADR-005, 7ff84b2). git add -A no longer stages the serve fingerprint or analyze lock; ADR-005 documents the live-index commit hazard → loomweave db backup. Closes clarion-7381e6382d.
  • WAL checkpoint(TRUNCATE) after each committed run (69ebadd). On-disk .db reflects committed state while serve is alive. Closes clarion-cdee445ed8.
  • Drop dead entity_fts.content_text (migration 0009, 8be269d). Never populated, never read (content search is ADR-040 embeddings); CURRENT_SCHEMA_VERSION → 9. Closes clarion-716449c371.
  • release.yml macOS aarch64 verify gate (3c8feae). Mirrors ci.yml, wired into build/publish needs. Closes clarion-47d395e03c.
  • macOS Gatekeeper doc (5da9ccd) + ADR-024 marker backfilled to v1.0.0 (b598ebf) activating the migration-retirement guard. Close clarion-03dfa1f94d + clarion-b20448b3ac.

Verification

Full CI floor green: fmt / clippy -D warnings / build / nextest 1209 passed / doc -D warnings / cargo deny; Python ruff / ruff format / mypy --strict / pytest 166 passed (85%); version-lockstep + ADR-024 migration-retirement guards pass at 1.1.0-rc2; wardline scan --fail-on ERROR clean on changed crates.

🤖 Generated with Claude Code

…sing DB

When `.loomweave/loomweave.db` is absent, `loomweave serve` did a hard
`ensure!(db_path.exists())` and exited 1 before the MCP protocol started.
An MCP stdio client (Claude Code) just saw the server die at startup with
the real reason buried in stderr — it read as "loomweave mcp failing"
with no actionable signal.

Now `serve` starts a degraded "no-index" stdio session instead:
- `initialize` succeeds so the client connects cleanly; the `instructions`
  field leads with the run-`install`+`analyze` chirp (mirrors the
  SessionStart hook wording).
- Every `tools/call` returns the same chirp as a tool result with
  `isError: true` — the load-bearing channel, since not every client
  surfaces `initialize.instructions`.
- `tools/list` and the static `loomweave-workflow` prompt still answer so
  the surface looks healthy.
- No HTTP read API bind, no LLM/embedding providers, no Filigree client,
  no ReaderPool — nothing to back them without a DB. One warn line to
  stderr (never stdout) at degraded startup.

loomweave-mcp gains `handle_json_rpc_no_index` + `serve_stdio_no_index`
plus chirp helpers; serve.rs swaps the exit for a `serve_no_index` branch.

Closes clarion-ac36f51c2b.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf5f39721b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// staring at a server that died at startup with the reason buried in
// stderr — serve a degraded stdio session that answers `initialize` and
// chirps "run analyze" from every tool call. clarion-ac36f51c2b.
return serve_no_index(path, &db_path);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the project path before degraded mode

When --path is mistyped, deleted, or points at a non-directory, this derived DB path also does not exist, so serve now starts a long-lived degraded MCP server instead of surfacing the bad project path. The recovery text then tells the user to run loomweave install --path <bad path> even though install::run rejects nonexistent targets, making stale MCP registrations look like merely missing indexes. Canonicalize/validate the project root before taking the no-index branch, and only degrade when the root is valid but the DB is absent.

Useful? React with 👍 / 👎.

…oling

Read-API port deconfliction (clarion-7f574bc34f):
- ADR-044 (Proposed): serve publishes .loomweave/ephemeral.port with a
  per-project deterministic port + ephemeral fallback and a loomweave-side
  resolver (twin of filigree_url), so concurrent projects stop colliding on
  the hardcoded 9111; installer stops pinning the port. Indexed in the ADR
  README.
- Stopgap so this project coexists with others on 9111 until the ADR lands:
  loomweave.yaml serve.http.bind -> 127.0.0.1:9112 and wardline.yaml
  loomweave.url -> :9112.

Wardline tooling:
- .mcp.json: drop the hardcoded --loomweave-url/--filigree-url from the
  wardline MCP args (resolved from wardline.yaml instead); normalize server
  entries.
- .pre-commit-config.yaml: add a local wardline-scan hook.
- .agents/skills/wardline-gate: add the wardline-gate skill pack.

- .gitignore: ignore the raw wardline scan output (findings.jsonl).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 49a6753d6e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread loomweave.yaml Outdated
serve:
http:
bind: 127.0.0.1:9111
bind: 127.0.0.1:9112

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep dogfood binding constants in sync

With this repo-local bind changed to 127.0.0.1:9112, the checked-in dogfood bindings no longer converge with the code that manages them: integration_bindings::loomweave_yaml_ok() still requires LOOMWEAVE_HTTP_BIND (127.0.0.1:9111) and wardline_yaml_ok() still requires LOOMWEAVE_HTTP_URL (http://127.0.0.1:9111). In this project, running loomweave doctor after the change reports the bindings as stale, and loomweave doctor --fix / loomweave install --all rewrites them back to 9111, undoing the new port and reintroducing the collision this config change is trying to avoid.

Useful? React with 👍 / 👎.

Comment thread .mcp.json
Comment on lines 19 to +23
"args": [
"mcp",
"--root",
".",
"--loomweave-url",
"http://127.0.0.1:9111",
"--filigree-url",
"http://127.0.0.1:8542/api/weft/scan-results"
],
"command": "/home/john/.local/bin/wardline",
"type": "stdio"
"."
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass peer URLs to Wardline MCP

For the repo-local Wardline MCP server, this now starts Wardline with only mcp --root ., dropping both peer URL flags. The installer/doctor code in integration_bindings::desired_wardline_args() still treats --loomweave-url and --filigree-url as the desired contract, and the install/doctor tests assert those flags, so this checked-in MCP config is immediately classified as stale and Wardline MCP scans launched from this file no longer get the Loomweave/Filigree endpoints needed for the three-way dogfood integration.

Useful? React with 👍 / 👎.

Comment thread .pre-commit-config.yaml
Comment on lines +24 to +26
- id: wardline-scan
name: wardline scan
entry: wardline scan

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make the Wardline hook fail on findings

This hook runs only wardline scan, but the Wardline workflow added in this commit documents the gating invocation as wardline scan . --fail-on ERROR, with exit code 0 also used when the gate is not requested and exit code 1 only when a non-suppressed defect is at/above --fail-on. As written, commits with Python changes can run the scan without tripping pre-commit on ERROR findings, so the new hook does not actually enforce the trust-boundary gate it is installing.

Useful? React with 👍 / 👎.

tachyon-beep and others added 15 commits June 6, 2026 07:49
… contract

Incorporates the Wardline (consumer-side) review. The interop surface is the
file, not loomweave's Rust resolver — Wardline implements its own Python reader
against it (SEI-style "consumers conform"). Pins, as normative:

- File contract: <project>/.loomweave/ephemeral.port, plain-ASCII port only,
  optional trailing newline, host/scheme implied, atomic temp+rename, created on
  loopback bind / removed on clean shutdown.
- Loopback-only publication: a non-loopback bind (allow_non_loopback, ADR-034)
  publishes no file, so the port-only format never under-specifies the host.
- Resolution precedence (consume-time, per read): explicit flag/env > published
  file > configured url > none. The file self-heals stale/default config but
  never overrides a deliberate explicit target.
- Fail-soft: validate 1..=65535; malformed or resolved-but-refused (stale file /
  crashed serve) degrades, never errors. Instance-ID guard (ADR-034) is the
  correctness backstop so the reader can be simple.
- Related follow-up: consume-time resolution applies to both sibling legs;
  Wardline's filigree leg (install-time today) should unify Wardline-side.

Tracking: clarion-7f574bc34f

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ic publish (ADR-044)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…eans temp on rename failure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s per-project port (ADR-044)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…; drop misleading # Panics docs (ADR-044)

Replace the two .expect() unwraps in validate_loopback_trust and
validate_auth_trust with compiler-enforced pattern matching, and delete
the # Panics doc sections (a # Panics heading documenting when a method
will *not* panic inverts the rustdoc convention). Behavior is identical.

Also add a field doc comment to HttpReadConfig.bind and two tests:
the auth-trust None path and explicit YAML-null bind parsing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sh .loomweave/ephemeral.port (ADR-044)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t is taken (ADR-044)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mweave URL, no fixed bind (ADR-044)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… on repair (ADR-044)

Older `install --all` runs unconditionally stamped a fixed bind. Task 5
stopped writing it but left existing stamps in place, so re-install kept
`bind: 9111`, serve honored it verbatim (no auto-port), and the collision
returned invisibly (loomweave_yaml_ok no longer inspected bind). Strip
exactly the old auto-default literal on repair and treat its presence as
not-ok so doctor/binding_state flags and fixes it. Operator-chosen binds
(any other value) are preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ead-API port (ADR-044)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…weave_url (ADR-044)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…112 stopgap

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…read-API report, reconcile ADR precedence

- install.rs GITIGNORE_CONTENTS now ignores .loomweave/ephemeral.port so
  freshly-installed projects do not show the runtime port file as untracked
  while serving; install test asserts the new rule.
- project_status_get reports loomweave_read_api (resolved_url +
  resolution_source) via a query-time resolve_loomweave_url(None, project_root),
  the second in-repo consumer named by ADR-044 alongside doctor. Additive field;
  existing project_status tests unaffected. Two new tests cover published-port
  and no-file ("none") cases.
- ADR-044: clarify precedence level 1 is an operator's deliberately-supplied
  target (typed flag/env), while an installer-seeded --loomweave-url in .mcp.json
  is config-tier (precedence 3) so the published file self-heals it; added a
  Related follow-up bullet for Wardline (clarion-7f574bc34f).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tachyon-beep tachyon-beep changed the title feat(serve): degrade to no-index MCP server instead of exiting on missing DB feat: no-index MCP chirp + ADR-044 read-API ephemeral-port deconfliction Jun 6, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c7f253000b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


impl Drop for PublishedPortGuard {
fn drop(&mut self) {
loomweave_federation::loomweave_port::remove_published_port(&self.project_root);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep other live port publishers from being unlinked

When two loomweave serve instances are started for the same project with auto HTTP enabled, the first one publishes the deterministic port and the second falls back to an ephemeral port and overwrites .loomweave/ephemeral.port; when the first instance later shuts down, this unconditional removal deletes the second instance’s still-live discovery file. That leaves consumers unable to resolve the running read API until the second server restarts, so the guard should only remove the file if it still contains the port this server published (or otherwise use an ownership token).

Useful? React with 👍 / 👎.

Comment on lines +83 to +84
let port = loomweave_federation::loomweave_port::deterministic_port(project_root);
let loomweave_url = format!("http://127.0.0.1:{port}");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match peer URL to preserved custom binds

When an existing loomweave.yaml uses an explicit custom loopback bind, install_loomweave_yaml now intentionally preserves it, but the desired Wardline URL is still always derived from the deterministic auto-port here. After loomweave install --all / doctor --fix, Wardline config and MCP args point at a port that loomweave serve will never bind in that custom-bind project, so the three-way integration is repaired into a broken state unless the user removes their explicit bind.

Useful? React with 👍 / 👎.

Comment on lines +398 to +400
let _published_port_guard = if local_addr.ip().is_loopback() {
if let Err(err) =
loomweave_federation::loomweave_port::publish_port(&project_root, local_addr.port())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not publish IPv6 loopback as 127.0.0.1

If an operator explicitly binds the read API to IPv6 loopback, e.g. [::1]:9412, is_loopback() is true so this publishes only the port, but every consumer composes http://127.0.0.1:<port>. On systems where that listener is IPv6-only, Wardline and status consumers are routed to an address where Loomweave is not listening; restrict publication to the IPv4 loopback address or make the published contract preserve the bound host.

Useful? React with 👍 / 👎.

Comment thread wardline.yaml
# ADR-044: pinned to this project's deterministic read-API port. The published
# .loomweave/ephemeral.port overrides this once Wardline resolves consume-time
# (clarion-7f574bc34f follow-up). Until then this keeps local wardline->loomweave working.
url: http://127.0.0.1:10196

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid committing path-derived Wardline ports

Fresh evidence is that the desired Loomweave URL is now derived from deterministic_port(project_root), which hashes the canonical checkout path, while this tracked config hard-codes one checkout’s resulting port. In any clone whose path hashes differently, loomweave doctor reports the checked-in dogfood binding as stale and doctor --fix / install --all rewrites this tracked file to a different port, so the repo no longer converges cleanly across developer machines until Wardline resolves .loomweave/ephemeral.port itself.

Useful? React with 👍 / 👎.

tachyon-beep and others added 9 commits June 6, 2026 10:27
Workspace + Python plugin in lockstep. Cross-ecosystem version normalization in
check-workspace-version-lockstep.py (SemVer prerelease 1.1.0-rc1 == PEP 440
1.1.0rc1). CHANGELOG: ADR-044 ephemeral-port deconfliction + no-index MCP chirp.
No package published for release candidates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…mit hazard (ADR-005)

The shipped .loomweave/.gitignore (ADR-005) excluded WAL/shadow/logs but not
the per-project `instance_id` fingerprint or the analyze advisory lock
(`loomweave.lock`, fs2), so `git add -A` staged live runtime state into demo
repos. Add `instance_id` and `*.lock` to GITIGNORE_CONTENTS and refresh ADR-005's
verbatim block + Excluded list (also reconciling ephemeral.port/embeddings.db).
The install test now asserts both rules ship.

ADR-005 also gains a "Committing a live index" note: the on-disk loomweave.db
lags its pending WAL while serve runs, so commit a consistent copy via
`loomweave db backup` (or stop serve) rather than git-add-ing the live file.

Closes clarion-7381e6382d. Refs clarion-cdee445ed8.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ace db backup

After a successful CommitRun the writer-actor now runs
`PRAGMA wal_checkpoint(TRUNCATE)` so the on-disk loomweave.db reflects committed
state while the writer is still alive — previously the WAL only truncated on
last-connection close, leaving a multi-MB pending sidecar that made the .db an
unreliable point-in-time artifact for commit. The checkpoint is best-effort:
failure logs a warning and leaves committed frames durable.

`loomweave analyze --help` now points at `loomweave db backup` for committing the
index as a versioned artifact (the verb already exists; this is discoverability).

Closes clarion-cdee445ed8.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ee verdict (ADR-045)

project_status_get reported staleness:"fresh" while the working tree held
un-indexed source, so the session-start banner ("index is fresh, ask Loomweave")
lied about uncommitted code. Make staleness worktree-aware:

- Snapshot gains indexed_at_commit + worktree_dirty; a new Staleness::StaleWorktree
  verdict fires when an otherwise-fresh index has untracked source on disk.
- Detection uses loomweave_core::list_untracked_files — hardened, hash-free
  `git ls-files --others --exclude-standard`, scoped to ingested source extensions
  so a scratch notes.txt does not flag (false-positive guard). Fail-soft outside
  a git work tree.
- Surfaced on loomweave://context, project_status_get (worktree_dirty +
  staleness_note), and the session-start banner with a concrete re-analyze remedy;
  orientation treats StaleWorktree as stale.
- ADR-045 records the maintainer-authorized security boundary: `git status` is
  forbidden (filter.clean RCE on hashed content; clarion-4b5a8aff54), but
  ls-files --others is hash-free — proven by the new
  ls_files_others_does_not_run_clean_filter security test, not reasoning alone.

Closes clarion-26c7e52027 and clarion-d9cf8bcfa9.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-04)

Release archives are unsigned (ADR-033), so macOS Gatekeeper blocks the
downloaded loomweave binary on first launch. Add a Troubleshooting entry with
the `xattr -d com.apple.quarantine` fix and the GUI "Open Anyway" alternative.

Closes clarion-03dfa1f94d.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v1.0.0 was the first externally-published build; 0001_initial_schema.sql is
byte-identical at v1.0.0 and HEAD, and all schema changes since are additive
0002+ migrations. Backfilling the marker activates
scripts/check-migration-retirement.py's guard (previously pre-trigger despite
shipped releases): in-place edits to 0001 now fail CI, enforcing additive-only.

Closes clarion-b20448b3ac.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…47d395e03c)

release.yml's `verify` job was Linux-only, so a macOS-only clippy/--all-targets
regression — caught on PRs by ci.yml's rust-macos job but not re-verified at
release — could pass `verify` and proceed to the build/publish jobs (the
aarch64 build leg only builds --bins, not tests/all-targets). Add a `verify-macos`
job mirroring ci.yml's rust-macos (clippy + bin build on macos-14) and add it to
the needs chain of build-rust, build-wheels, and build-plugin. No new runner
dependency — build-rust already uses macos-14.

Closes clarion-47d395e03c.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…9, V11-STO-06)

content_text shipped in 0001 reserved for an on-demand source-text projection
that was never built: the entities_ai trigger always wrote '', the entities_au
trigger never touched it, and no query reads it (search MATCHes the table, not
the column). It was permanently-empty schema drift; content search is served by
the ADR-040 embeddings sidecar. FTS5 has no ALTER DROP COLUMN, so migration 0009
recreates entity_fts and its triggers without it and rebuilds the index from
entities. Behaviour-preserving — only a never-populated, never-read column goes.

Bumps CURRENT_SCHEMA_VERSION to 9; updates the schema_migrations expectation
tests and the authoritative detailed-design.md FTS block; adds a regression test
asserting content_text is gone and MATCH search still works.

Closes clarion-716449c371.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Workspace + Python plugin in lockstep. rc2 rolls up the dogfood-friction fixes
and deferred v1.1 engineering items landed on this branch: worktree-aware
staleness (ADR-045), .gitignore instance_id/*.lock (ADR-005), WAL
checkpoint(TRUNCATE), entity_fts.content_text drop (migration 0009), the macOS
aarch64 release verify gate, the Gatekeeper doc, and the ADR-024 marker backfill.
No package published for release candidates.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tachyon-beep tachyon-beep changed the title feat: no-index MCP chirp + ADR-044 read-API ephemeral-port deconfliction feat: no-index MCP chirp + ADR-044 ephemeral port + dogfood/v1.1 cleanups (1.1.0-rc2) Jun 6, 2026
…nstall + doctor)

`loomweave install` now pushes a managed Loomweave block into the always-loaded
CLAUDE.md / AGENTS.md context, mirroring Filigree's instruction injection, so an
agent learns to ask Loomweave's MCP tools before re-grepping the tree.
`loomweave doctor` verifies it and, with --fix, repairs it via the same
idempotent installer.

New `instructions.rs` manages a `<!-- loomweave:instructions -->`…
`<!-- /loomweave:instructions -->` span and edits ONLY its own bytes — it never
truncates to EOF, so a co-resident Filigree/Wardline block in the same file
survives every create/append/replace/malformed operation. Drift is a body
content hash (not the marker version, so a version bump on identical content is
not drift), and the malformed-repair strips all orphan start markers so it stays
safe and converges in a single pass.

- install: --instructions flag + InstallPlan plumbing; bare `install` does it.
- doctor: Missing=warning (optional surface), Drifted/Malformed=problem; wired
  into both the text and JSON report paths with a next-action remediation.
- thin embedded asset: a pointer to the MCP tools + the loomweave-workflow skill.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tachyon-beep

Copy link
Copy Markdown
Collaborator Author

Superseded by #56 — this PR was auto-closed when its head branch feat/serve-no-index-chirp was renamed to rc3. All commits plus the new agent-orientation injection feature continue in #56.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a93731f72

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

http.get("enabled").and_then(Value::as_bool) == Some(true)
&& http.get("bind").and_then(Value::as_str) == Some(LOOMWEAVE_HTTP_BIND)
&& http.get("wardline_taint_write").and_then(Value::as_bool) == Some(true)
&& http.get("bind").and_then(Value::as_str) != Some(STALE_DEFAULT_BIND)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate custom HTTP binds before marking bindings healthy

When loomweave.yaml contains an explicit but invalid bind such as bind: not-a-socket (or a non-string value), this predicate now treats the config as healthy because anything other than the stale 127.0.0.1:9111 literal passes. The actual config loader rejects invalid binds in deserialize_optional_socket_addr, so loomweave serve will fail while doctor / doctor --fix report the integration bindings as present and do not repair or remove the broken value. Preserve valid custom binds, but parse/validate this field before returning Present.

Useful? React with 👍 / 👎.

Comment on lines +216 to +222
Some((span_start, body_start)) if trimmed == END_MARKER => {
// Body is everything between the start-marker line and the
// end-marker line; trim a single trailing newline so it round-trips
// against `canonical_body` (which has no trailing newline).
let raw_body = &content[body_start..line_start];
let body = raw_body.strip_suffix('\n').unwrap_or(raw_body).to_owned();
return Span::WellFormed {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat nested start markers as malformed

If a file has an orphaned Loomweave start marker before a later well-formed Loomweave block (for example after a bad merge, with Filigree/Wardline prose between them), this accepts the first later end marker as closing the orphaned start. doctor --fix then classifies the whole intervening region as a drifted Loomweave span and splice_span replaces it, deleting the neighboring tool block or user text. Detect a second START_PREFIX before the matching end marker as malformed so the safe orphan-stripping path is used instead.

Useful? React with 👍 / 👎.

Comment on lines +196 to +199
"Index does NOT reflect the working tree: untracked source files of \
already-indexed types are present (new modules not yet analyzed). \
Run `loomweave analyze {}` before relying on graph answers \
(e.g. \"what calls X\").",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Flag stale-worktree snapshots in doctor JSON

For a StaleWorktree snapshot, this new banner no longer contains the substring may be stale, but check_index_freshness_json still classifies freshness by searching only for that phrase. As a result, loomweave doctor --json reports index.freshness as ok even when untracked source is present and the index does not reflect the working tree, which can let JSON-based gates miss exactly the stale condition added here.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant