woods 2.0.0.beta4 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +495 -471
- data/CONTRIBUTING.md +12 -2
- data/README.md +11 -26
- data/docs/AGENT_GUIDE.md +31 -12
- data/docs/AGENT_SETUP.md +17 -10
- data/docs/AUTOMATIC_MAINTENANCE.md +222 -0
- data/docs/BACKEND_MATRIX.md +13 -7
- data/docs/CLIENT_HOOKS.md +1 -1
- data/docs/CONFIGURATION_REFERENCE.md +44 -27
- data/docs/CONSOLE_MCP_SETUP.md +95 -16
- data/docs/DOCKER_SETUP.md +15 -0
- data/docs/EVALUATION.md +10 -4
- data/docs/EXTRACTOR_REFERENCE.md +14 -2
- data/docs/FAQ.md +14 -3
- data/docs/GETTING_STARTED.md +18 -17
- data/docs/INCREMENTAL_EXTRACTION.md +8 -3
- data/docs/INDEX_LAYOUT.md +2 -2
- data/docs/MCP_HTTP_TRANSPORT.md +54 -2
- data/docs/MCP_SERVERS.md +28 -11
- data/docs/MCP_TOOL_COOKBOOK.md +1 -1
- data/docs/MCP_WORKTREE_SETUP.md +13 -1
- data/docs/PUBLISHED_INDEX.md +1 -1
- data/docs/README.md +2 -1
- data/docs/RETRIEVAL_GUIDE.md +57 -8
- data/docs/SOURCE_FRESHNESS.md +1 -1
- data/docs/TOKEN_BENCHMARK.md +16 -10
- data/docs/TROUBLESHOOTING.md +133 -37
- data/docs/UPGRADING_TO_2.md +69 -7
- data/docs/WATCH_DAEMON.md +172 -17
- data/docs/WHY_WOODS.md +9 -5
- data/exe/woods-console +13 -11
- data/exe/woods-mcp-http +16 -9
- data/exe/woods-watch +5 -0
- data/lib/generators/woods/watch_generator.rb +53 -0
- data/lib/puma/plugin/woods.rb +10 -0
- data/lib/tasks/woods.rake +14 -0
- data/lib/woods/cache/cache_middleware.rb +18 -11
- data/lib/woods/console/adapter_family.rb +39 -0
- data/lib/woods/console/credential_index.rb +33 -3
- data/lib/woods/console/embedded_executor.rb +401 -43
- data/lib/woods/console/model_validator.rb +8 -0
- data/lib/woods/console/rack_middleware.rb +39 -10
- data/lib/woods/console/redactor.rb +24 -10
- data/lib/woods/console/safe_context.rb +44 -7
- data/lib/woods/console/sql_noise_stripper.rb +41 -12
- data/lib/woods/console/sql_table_scanner.rb +45 -34
- data/lib/woods/console/sql_validator.rb +37 -2
- data/lib/woods/console/stdio_transport.rb +27 -0
- data/lib/woods/extractor.rb +25 -7
- data/lib/woods/git_command.rb +6 -7
- data/lib/woods/git_provenance.rb +4 -6
- data/lib/woods/mcp/bearer_auth.rb +1 -1
- data/lib/woods/mcp/bootstrapper.rb +3 -1
- data/lib/woods/mcp/initialization_guidance.rb +1 -1
- data/lib/woods/mcp/origin_guard.rb +24 -77
- data/lib/woods/mcp/origin_policy.rb +124 -0
- data/lib/woods/mcp/server.rb +41 -9
- data/lib/woods/railtie_support.rb +8 -0
- data/lib/woods/retrieval/corpus_status.rb +46 -0
- data/lib/woods/retriever.rb +19 -7
- data/lib/woods/storage/local_corpus_stats.rb +32 -0
- data/lib/woods/storage/metadata_store.rb +20 -0
- data/lib/woods/storage/vector_store.rb +10 -0
- data/lib/woods/version.rb +1 -1
- data/lib/woods/watch/child_environment.rb +30 -0
- data/lib/woods/watch/cli.rb +91 -0
- data/lib/woods/watch/daemon.rb +55 -7
- data/lib/woods/watch/event_stream.rb +70 -0
- data/lib/woods/watch/guardian.rb +142 -0
- data/lib/woods/watch/installation/layout.rb +70 -0
- data/lib/woods/watch/installation/options.rb +128 -0
- data/lib/woods/watch/installation/planner.rb +128 -0
- data/lib/woods/watch/installation/probe.rb +101 -0
- data/lib/woods/watch/installation/receipt.rb +77 -0
- data/lib/woods/watch/installation/recovery.rb +64 -0
- data/lib/woods/watch/installation/templates.rb +58 -0
- data/lib/woods/watch/installation.rb +56 -0
- data/lib/woods/watch/lifecycle.rb +182 -0
- data/lib/woods/watch/managed_child.rb +113 -0
- data/lib/woods/watch/managed_cleanup.rb +48 -0
- data/lib/woods/watch/managed_process.rb +144 -0
- data/lib/woods/watch/puma_adapter.rb +87 -0
- data/lib/woods/watch/puma_child.rb +66 -0
- data/lib/woods/watch/supervision_records.rb +95 -0
- data/lib/woods/watch/supervision_status.rb +104 -0
- data/lib/woods/watch/supervisor.rb +161 -0
- data/lib/woods/watch/supervisor_reporting.rb +46 -0
- data/plugin/.claude-plugin/plugin.json +1 -1
- data/plugin/skills/woods-agent-enable/SKILL.md +1 -1
- data/plugin/skills/woods-diagnose/SKILL.md +88 -8
- data/plugin/skills/woods-investigate/SKILL.md +6 -6
- data/plugin/skills/woods-mcp-config/SKILL.md +43 -1
- data/plugin/skills/woods-setup/SKILL.md +66 -4
- metadata +37 -5
|
@@ -210,7 +210,7 @@ config.vector_store_options = {
|
|
|
210
210
|
|
|
211
211
|
Woods uses an HNSW index over pgvector's `vector` representation, which supports
|
|
212
212
|
**1–2,000 dimensions** ([pgvector's HNSW limits](https://github.com/pgvector/pgvector#hnsw)).
|
|
213
|
-
|
|
213
|
+
Included in Woods `2.0.0`: the adapter rejects wider dimensions before any
|
|
214
214
|
SQL, and `woods:pgvector` rejects invalid widths before writing a migration.
|
|
215
215
|
There is no automatic vector truncation or half-precision conversion.
|
|
216
216
|
|
|
@@ -282,7 +282,7 @@ in the promoted dump; the index MCP server loads that snapshot at startup or
|
|
|
282
282
|
reload. Incremental embedding publishes changes to paths, dependencies, and
|
|
283
283
|
other unit metadata even when unchanged source needs no new embedding. A run
|
|
284
284
|
with no content or metadata changes keeps the existing dump and retention
|
|
285
|
-
window.
|
|
285
|
+
window. Included in Woods `2.0.0`: a full `Indexer#index_all` run replaces
|
|
286
286
|
the published corpus even when a custom caller reuses in-memory vector and
|
|
287
287
|
metadata stores. Deleted units, including metadata-only records, are removed;
|
|
288
288
|
an empty full rebuild publishes an empty dump. Failed embedding leaves the
|
|
@@ -291,6 +291,13 @@ unchanged. This is a reasonable default for hosts that don't bundle `sqlite3`.
|
|
|
291
291
|
|
|
292
292
|
## Retrieval cache options
|
|
293
293
|
|
|
294
|
+
The 2.0.1 maintenance patch scopes retrieval contexts to one retriever instance.
|
|
295
|
+
Reload retires only that instance's namespace, including results still in flight;
|
|
296
|
+
already-running requests may finish against the previous corpus. Restarting starts
|
|
297
|
+
a fresh context namespace. Retired entries expire under their configured TTL or
|
|
298
|
+
backend eviction; disabling both can retain unused entries indefinitely. Embedding
|
|
299
|
+
caches remain separate and are not cleared by context invalidation.
|
|
300
|
+
|
|
294
301
|
The optional cache wraps both embedding-provider calls and assembled retrieval
|
|
295
302
|
contexts. It is disabled by default and is separate from the Index Server's
|
|
296
303
|
tool-result `_meta` cache hint.
|
|
@@ -451,7 +458,7 @@ A malformed record invalidates the entire snapshot, rather than exposing partial
|
|
|
451
458
|
history. Legacy bare identifier keys, omitted/null unit collections, and optional per-unit hash
|
|
452
459
|
fields remain supported; timestamp strings are not restricted to a new format.
|
|
453
460
|
Unit history limits count matching unit records, not the most recent snapshots
|
|
454
|
-
searched (JSON fallback correction
|
|
461
|
+
searched (JSON fallback correction included in Woods `2.0.0`). A unit
|
|
455
462
|
missing from newer snapshots can still have retained history.
|
|
456
463
|
Snapshot lists and unit history omit unusable files; direct lookup returns no
|
|
457
464
|
snapshot, and a diff with an unavailable snapshot returns empty added, modified,
|
|
@@ -682,7 +689,7 @@ deployment guide including defense layers.
|
|
|
682
689
|
| `console_mcp_enabled` | Boolean | `false` | Master switch. When `false`, stdio exits and the mounted Console middleware passes requests through to Rails. |
|
|
683
690
|
| `console_mcp_http_enabled` | Boolean | `true` | HTTP transport switch; effective only while the master switch is on. Set `false` for stdio-only use without HTTP token validation or an active HTTP endpoint. Read at request time. |
|
|
684
691
|
| `console_mcp_token` | String | `ENV['WOODS_CONSOLE_MCP_TOKEN']` or `nil` | Bearer token required on every enabled Console HTTP request. With both Console flags enabled, production boot raises on a missing token; other environments warn and requests fail closed with 401. A configured token shorter than 32 characters raises at boot while HTTP is enabled. Explicit stdio-only configurations skip HTTP token validation. Generate with `SecureRandom.hex(32)`. |
|
|
685
|
-
| `console_mcp_allowed_origins` | Array\<String\> | `%w[http://localhost http://127.0.0.1 http://[::1]]` | `OriginGuard` allowlist.
|
|
692
|
+
| `console_mcp_allowed_origins` | Array\<String\> | `%w[http://localhost http://127.0.0.1 http://[::1]]` | `OriginGuard` allowlist shared with SDK dispatch. Portless entries permit same-authority requests; cross-origin ports must be listed explicitly. Default HTTP(S) ports normalize to their omitted form. Invalid entries fail at boot. |
|
|
686
693
|
| `console_mcp_path` | String | `/mcp/console` | URL path the Rack middleware responds on. |
|
|
687
694
|
| `console_embedded_read_tools` | Boolean | `false` | Register `console_sql` and `console_query` in supported stdio and Rack modes. |
|
|
688
695
|
| `console_blocked_tables` | Array\<String\> | `Woods::DEFAULT_CONSOLE_BLOCKED_TABLES` | TableGate denylist (case-insensitive). Bare names match every schema; qualified names (`schema.table`) match exactly. |
|
|
@@ -704,7 +711,7 @@ These variables are read by the gem and its MCP servers at runtime. They complem
|
|
|
704
711
|
|----------|---------|---------|
|
|
705
712
|
| `WOODS_RETRIEVAL_MODE` | `semantic` | Explicit packaged MCP retrieval mode: `semantic` or `lexical`. Lexical reads extraction unit JSON without provider autodetection, credentials or vector artifacts. |
|
|
706
713
|
| `WOODS_DIR` | unset | MCP extraction-index path, after a positional argument and before `WOODS_OUTPUT`. See precedence below. |
|
|
707
|
-
| `WOODS_OUTPUT` | unset | MCP index-path fallback when neither a positional path nor `WOODS_DIR` is set;
|
|
714
|
+
| `WOODS_OUTPUT` | unset | MCP index-path fallback when neither a positional path nor `WOODS_DIR` is set; included in Woods `2.0.0`. |
|
|
708
715
|
| `WOODS_REQUIRE_INDEX` | unset | Set to `"1"` to fail closed: the server refuses to boot (raises `MissingArtifact`) unless a real index (`woods.json`) is present. By default an extract-only host boots in pattern/structural mode without it. Explicit lexical mode requires a valid published extraction index, not `woods.json`. |
|
|
709
716
|
| `WOODS_ALLOW_AUTODETECT` | unset | **Deprecated no-op.** Auto-detect is now the default; accepted for backward compatibility only. |
|
|
710
717
|
| `WOODS_SEARCH_MAX_SCAN` | `500` | Cap on unit files loaded during a phase-2 (metadata/source_code) `search`. Hitting the cap sets `partial: true` in the response. |
|
|
@@ -720,7 +727,7 @@ These variables are read by the gem and its MCP servers at runtime. They complem
|
|
|
720
727
|
| `WOODS_QDRANT_URL`, `WOODS_QDRANT_COLLECTION`, `WOODS_QDRANT_API_KEY` | n/a | Override/require Qdrant connection settings when a pgvector/Qdrant-backed index is served outside its host application (no `Woods.configuration` available). |
|
|
721
728
|
| `WOODS_PG_URL` | n/a | Required when a pgvector-backed index is served outside its host application. |
|
|
722
729
|
|
|
723
|
-
**MCP index path precedence (
|
|
730
|
+
**MCP index path precedence (included in Woods `2.0.0`):** positional
|
|
724
731
|
argument → `WOODS_DIR` → `WOODS_OUTPUT` → current directory for `woods-mcp`
|
|
725
732
|
and `woods-mcp-http`. `woods-mcp-start` still requires one of the first three;
|
|
726
733
|
it never silently selects the current directory. An explicitly empty
|
|
@@ -771,10 +778,24 @@ existing index before deciding another extraction is needed.
|
|
|
771
778
|
| `WOODS_WATCH_CATCH_UP` | `1` (enabled) | Set to `"0"` to skip generation-watermark catch-up on daemon start. |
|
|
772
779
|
| `WOODS_WATCH_TRUST_FOREIGN_HOST` | unset (disabled) | Set to `"1"` in each task/MCP reader to trust a foreign daemon's heartbeat for up to 15 minutes, without a local pid check. See [cross-host liveness](WATCH_DAEMON.md#cross-host-liveness) for clock bounds, degraded coverage, and startup limitations. |
|
|
773
780
|
|
|
781
|
+
### Managed watcher startup
|
|
782
|
+
|
|
783
|
+
**Included in Woods `2.0.0`.** `woods-watch` wraps the raw task for native
|
|
784
|
+
Foreman/Puma lifecycle management. `--root PATH` selects the application working
|
|
785
|
+
directory; `--boot-timeout SECONDS` defaults to `300` and bounds boot/handshake,
|
|
786
|
+
not extraction. Explicit child argv follows `--`. Output-directory precedence
|
|
787
|
+
remains `WOODS_OUTPUT`, then `Woods.configuration.output_dir`.
|
|
788
|
+
|
|
789
|
+
Managed mode requires `WOODS_WATCH_IDLE_TIMEOUT` to be unset, preserves one owner,
|
|
790
|
+
and never takes over a conflicting daemon. The optional Puma adapter only starts
|
|
791
|
+
in its finalized development environment. See [startup and installation](WATCH_DAEMON.md#managed-development-startup)
|
|
792
|
+
for the generator's explicit modes, portable receipt, update/removal, and the
|
|
793
|
+
separate supervision status. Raw task settings above remain compatible.
|
|
794
|
+
|
|
774
795
|
### Opt-in plugin refresh hooks
|
|
775
796
|
|
|
776
797
|
These settings control the plugin shell worker. Check installed
|
|
777
|
-
`woods:hook_refresh` support first; the task is
|
|
798
|
+
`woods:hook_refresh` support first; the task is included in Woods `2.0.0`.
|
|
778
799
|
See [hook coverage and retry](WATCH_DAEMON.md#hooks-for-agent-sessions) and
|
|
779
800
|
[optional context limits](WATCH_DAEMON.md#optional-bounded-context-hints).
|
|
780
801
|
|
|
@@ -807,26 +828,23 @@ tasks for manual refreshes; hook transport is not a general shell execution API.
|
|
|
807
828
|
| `GITHUB_BASE_REF` | unset (GitHub Actions) | Build the diff range `origin/<ref>...HEAD` for `woods:incremental`; an unfetched ref makes the range unresolvable, same exit behavior. |
|
|
808
829
|
| `RAILS_ENV` | `development` | Rails environment the rake tasks boot in. |
|
|
809
830
|
| `WOODS_PROFILE` | unset | Set to `"1"` to log disjoint `[Woods] [profile] <phase> in N.NNs` durations, including git enrichment, reconciliation, payload sync, pointer publication (`publish`) and retention (`payload prune`). Separate `[profile total]` lines report whole extraction wall time, including unprofiled setup and failed runs; never add these totals to phase durations. Excludes process/Rails boot before extraction. Off by default. |
|
|
810
|
-
| `WOODS_GIT_DIR` | unset | Absolute path to the
|
|
831
|
+
| `WOODS_GIT_DIR` | unset | Absolute path passed directly to Git's `--git-dir`, selecting that directory's `HEAD`. For a linked worktree use its `worktrees/<id>` directory inside the complete shared Git layout. Wins over the repository Woods would otherwise find, at all three of its git call sites: per-unit `commit_count`/`change_frequency` (enrichment), `manifest.json`'s `git_branch`/`git_sha` (provenance), and the `woods:incremental` diff range. All three build their command line with `Woods::GitCommand.argv`. |
|
|
811
832
|
| `GIT_BRANCH`, `GIT_SHA` | unset | Provenance for a checkout with no `.git` at all (a source tarball, a Docker `COPY` that excludes it). Ignored when a `.git` is present but unresolvable, so a stale build arg cannot mask a worktree. |
|
|
812
833
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
`
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
```bash
|
|
828
|
-
WOODS_GIT_DIR=/canonical-git bundle exec rake woods:extract
|
|
829
|
-
```
|
|
834
|
+
For linked worktrees in containers, preserve access to the complete shared
|
|
835
|
+
Git directory and the worktree-specific HEAD. A same-path mount that resolves
|
|
836
|
+
the existing `.git` pointer needs no override. For a relocated complete layout,
|
|
837
|
+
set `WOODS_GIT_DIR=/mounted-common/worktrees/<id>`, deriving `<id>` from Git's
|
|
838
|
+
worktree metadata rather than the branch name. Selecting `/mounted-common`
|
|
839
|
+
itself selects the primary checkout's HEAD and can produce incorrect history,
|
|
840
|
+
provenance, and incremental paths. See the canonical
|
|
841
|
+
[worktree mount and verification steps](TROUBLESHOOTING.md#git-directory-mounts-for-linked-worktrees).
|
|
842
|
+
|
|
843
|
+
Git subprocesses inherit Git's own environment variables, so inspect existing
|
|
844
|
+
`GIT_DIR` and `GIT_COMMON_DIR` settings when resolving layout problems.
|
|
845
|
+
If HEAD cannot be resolved, enrichment omits the Git keys and provenance is
|
|
846
|
+
`"unknown"` for a present but unresolvable `.git`; one warning names the cause.
|
|
847
|
+
After correcting the layout, run a full extraction to refresh retained metadata.
|
|
830
848
|
|
|
831
849
|
### Exporters
|
|
832
850
|
|
|
@@ -846,11 +864,10 @@ The `woods-mcp` bootstrapper emits a one-line STDERR banner at startup indicatin
|
|
|
846
864
|
|
|
847
865
|
## Git enrichment history
|
|
848
866
|
|
|
849
|
-
|
|
867
|
+
Woods 2.0 requires **Git 2.31 or newer** for optional per-unit git
|
|
850
868
|
metadata. Extraction still succeeds when git is unavailable or history cannot
|
|
851
869
|
be read completely. Git enrichment is omitted in either case; a failed or
|
|
852
870
|
incomplete streamed history read logs a warning.
|
|
853
|
-
This requirement and the history policy below are unreleased after 2.0.0.beta2.
|
|
854
871
|
|
|
855
872
|
Per-unit enrichment also requires a non-shallow repository. A shallow checkout
|
|
856
873
|
or a failed repository-depth probe omits enrichment with one warning per
|
data/docs/CONSOLE_MCP_SETUP.md
CHANGED
|
@@ -48,7 +48,7 @@ its token, allowed origins and TLS as described in [Option C](#option-c-http-rac
|
|
|
48
48
|
|
|
49
49
|
The rake task does two things before starting the MCP server:
|
|
50
50
|
|
|
51
|
-
1. **Captures stdout before Rails boots.** Rails boot emits OpenTelemetry warnings, gem notices, and other output to stdout. An MCP client cannot parse these as JSON-RPC
|
|
51
|
+
1. **Captures stdout before Rails boots.** Rails boot emits OpenTelemetry warnings, gem notices, and other output to stdout. An MCP client cannot parse these as JSON-RPC. The rake task saves the protocol output and redirects application stdout to stderr. In the runtime isolation fix (included in Woods `2.0.0`), that redirection remains active throughout the server's lifetime; only the MCP transport writes to the saved protocol pipe. Rails loggers, `puts`, and writes to standard output during queries stay on stderr.
|
|
52
52
|
2. **Calls `Rails.application.eager_load!`** to load all application models. Without eager loading, only the models that happen to be autoloaded before the first query appear in the registry.
|
|
53
53
|
|
|
54
54
|
### MCP client configuration
|
|
@@ -83,7 +83,7 @@ rake woods:console
|
|
|
83
83
|
│ ├─ Rails.application.eager_load!
|
|
84
84
|
│ ├─ build model registry from ActiveRecord::Base.descendants
|
|
85
85
|
│ ├─ Server.build_embedded(model_validator:, safe_context:, ...)
|
|
86
|
-
│ └─
|
|
86
|
+
│ └─ Woods::Console::StdioTransport.new(server, output: protocol_out).open
|
|
87
87
|
│
|
|
88
88
|
└─ MCP server responds to tool calls via stdin/stdout
|
|
89
89
|
```
|
|
@@ -201,7 +201,7 @@ request. Missing or incorrect tokens receive `401 Unauthorized`.
|
|
|
201
201
|
The HTTP authentication scheme is ASCII case-insensitive (`Bearer`, `bearer`,
|
|
202
202
|
or `BEARER`); the token remains case-sensitive and must match exactly after one
|
|
203
203
|
space. This applies to both Console HTTP and `woods-mcp-http`. Case-insensitive
|
|
204
|
-
scheme support is
|
|
204
|
+
scheme support is included in Woods `2.0.0`; use the canonical `Bearer`
|
|
205
205
|
spelling in client configuration for compatibility with earlier releases.
|
|
206
206
|
|
|
207
207
|
For non-loopback access, `console_mcp_allowed_origins` must include the public
|
|
@@ -209,7 +209,10 @@ Rails/MCP host. If a browser-based client sends an `Origin` header from a
|
|
|
209
209
|
different host, include that exact origin too. This allow-list controls both
|
|
210
210
|
DNS-rebinding Host checks and browser CORS; keep Rails' own `config.hosts`, TLS,
|
|
211
211
|
and proxy rules aligned with it. Server-to-server clients normally omit
|
|
212
|
-
`Origin`, but
|
|
212
|
+
`Origin`, but a present request `Host` must still be allowed. Supporting security
|
|
213
|
+
revisions deliberately allow configured non-loopback Hosts through the SDK too;
|
|
214
|
+
2.0.0 could refuse them at that inner layer despite the Woods allowlist. This
|
|
215
|
+
widening is limited to the configured authorities and retains bearer auth.
|
|
213
216
|
|
|
214
217
|
Do not mount `Woods::Console::RackMiddleware` by itself. The Railtie composes
|
|
215
218
|
`OriginGuard`, `BearerAuth`, and the Console middleware in the supported order.
|
|
@@ -636,6 +639,9 @@ Redaction is defense-in-depth, prefer not storing plaintext secrets in database
|
|
|
636
639
|
|
|
637
640
|
### `console_redacted_key_values`
|
|
638
641
|
|
|
642
|
+
See [read policy compatibility](#read-policy-compatibility) for SQL column-list
|
|
643
|
+
restrictions, conservative typed masking, exact key spelling and binary columns.
|
|
644
|
+
|
|
639
645
|
Column-name redaction falls short when credentials are stored in a **key-value (EAV)** table, e.g. a Stripe Connect `authorizations` row of `{key: "stripe_access_token", value: "sk_live_..."}`. The column holding the secret is called `value`, which is generic: adding `value` to `console_redacted_columns` would over-redact every unrelated row in the table.
|
|
640
646
|
|
|
641
647
|
`console_redacted_key_values` takes one or more patterns that describe "when a row has `key_column` set to one of these names, redact its `value_column`":
|
|
@@ -700,7 +706,7 @@ these controls, in order:
|
|
|
700
706
|
|
|
701
707
|
1. `SqlValidator` rejects DML/DDL (`INSERT`/`UPDATE`/`DELETE`/`MERGE`/`DROP`/`TRUNCATE`/`ALTER`/`CREATE`/`REPLACE`), row-lock clauses (`FOR UPDATE`, `FOR SHARE`, `LOCK IN SHARE MODE`), writable CTEs (every `AS (...)` body, not just the first), `UNION`/`INTO`/`COPY`, multi-statement and comment-hidden injections, and most administrative keywords (`DO`, `SET`, `LISTEN`, `NOTIFY`, `CALL`, `LOAD`, `VACUUM`, `PREPARE`, transaction control, `EXPLAIN ANALYZE`) at the string level. Enforces a read-only **function allowlist** (`ALLOWED_FUNCTIONS`), anything not on it is rejected by name, quoted forms (`"pg_terminate_backend"(…)`) included. Only `SELECT`, `WITH…SELECT`, and plain `EXPLAIN` pass.
|
|
702
708
|
2. `TableGate` refuses any SQL, model, or join that touches a `console_blocked_tables` entry.
|
|
703
|
-
3. `SafeContext` wraps every request in a rolled-back transaction with
|
|
709
|
+
3. `SafeContext` wraps every request in a rolled-back transaction with an adapter-dependent statement timeout. **It does NOT cover async side effects**: ActiveJob `perform_later`, ActionMailer `deliver_later`, direct HTTP egress, `Thread.new`-spawned work, `after_rollback` callbacks, and writes through a different shard all execute as live. Treat the Console MCP as an admin-trust boundary, not a sandbox.
|
|
704
710
|
4. `CredentialScanner` + column/EAV redaction scrub results.
|
|
705
711
|
|
|
706
712
|
Keep the flag off when the host requires a narrower database capability.
|
|
@@ -718,7 +724,7 @@ supported transport (stdio, Docker/SSH launcher, and HTTP).
|
|
|
718
724
|
| 1 | Blocked tables | `console_blocked_tables` | Tool dispatch, before executor | Reject any tool call that touches a named table (model, table, or sql arg) |
|
|
719
725
|
| 2 | Credential scanner | `console_disabled_scanner_patterns` (`[:all]` to disable entirely) | After executor, before render | Content-shape redaction of credential-shaped strings anywhere in the response tree |
|
|
720
726
|
| 3 | Column + EAV redaction | `console_redacted_columns`, `console_redacted_key_values` | After executor, before Layer 2 | Identity-based redaction by column name and by key/value row shape |
|
|
721
|
-
| 4 | SqlValidator + SafeContext | built-in | Inside executor | SQL
|
|
727
|
+
| 4 | SqlValidator + SafeContext | built-in | Inside executor | SQL validation and function allowlist for `console_sql`; transaction rollback for every request |
|
|
722
728
|
|
|
723
729
|
Layers 0–3 are configured via `Woods.configure`. Layer 4 is always on and has no knobs. Observability hooks, `console.table_gate.rejected` for Layer 1, `console.credential_scan.hits` for Layer 2, emit structured log lines via `Woods::Observability::StructuredLogger` so operators can audit enforcement without scraping MCP wire traffic.
|
|
724
730
|
|
|
@@ -754,13 +760,20 @@ boundary remain necessary.
|
|
|
754
760
|
|
|
755
761
|
### Statement timeout
|
|
756
762
|
|
|
757
|
-
|
|
763
|
+
SafeContext attempts a **5000ms** (5-second) timeout. Support depends on the
|
|
764
|
+
adapter and server; an unsupported setting is skipped and logged when a Rails
|
|
765
|
+
logger is available.
|
|
758
766
|
|
|
759
767
|
| Adapter | Mechanism | Scope |
|
|
760
768
|
|---------|-----------|-------|
|
|
761
|
-
| PostgreSQL | `SET statement_timeout = '5000ms'` |
|
|
762
|
-
| MySQL | `SET max_execution_time = 5000`
|
|
763
|
-
|
|
|
769
|
+
| PostgreSQL | `SET LOCAL statement_timeout = '5000ms'` | Transaction-local; discarded on rollback |
|
|
770
|
+
| MySQL | `SET max_execution_time = 5000` | SELECT only; previous session value restored in `ensure` |
|
|
771
|
+
| MariaDB | `SET max_statement_time = 5.0` | Seconds; previous session value restored in `ensure` |
|
|
772
|
+
| SQLite / unrecognized family | No supported per-statement timeout | Do not rely on a query time limit |
|
|
773
|
+
|
|
774
|
+
Rollback remains active when a timeout setting is unsupported. Recognition of a
|
|
775
|
+
MySQL-family adapter alone does not establish that its server supports the
|
|
776
|
+
corresponding timeout variable.
|
|
764
777
|
|
|
765
778
|
### SQL validation (tier 4 `console_sql`)
|
|
766
779
|
|
|
@@ -771,7 +784,7 @@ Validation runs **once**, inside the executor, with the dialect of the live adap
|
|
|
771
784
|
|
|
772
785
|
- **Allowed prefixes:** `SELECT`, `WITH...SELECT`, and plain `EXPLAIN`. `EXPLAIN ANALYZE` is rejected, it executes the query rather than just planning it (both the whitespace and `EXPLAIN (ANALYZE, …)` option-list spellings).
|
|
773
786
|
- **Rejected prefixes:** `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `DROP`, `ALTER`, `TRUNCATE`, `CREATE`, `GRANT`, `REVOKE`
|
|
774
|
-
- **Rejected anywhere in query:** `UNION`, `INTO`, `COPY`; row-lock clauses (`FOR UPDATE`, `FOR NO KEY UPDATE`, `FOR SHARE`, `FOR KEY SHARE`, `FOR UPDATE NOWAIT`/`SKIP LOCKED`, MySQL `LOCK IN SHARE MODE`) — these take live row locks even inside the rolled-back transaction. The lock check is adapter-aware: `console_sql` validates with the active adapter's dialect, including MySQL double-quoted strings/backtick identifiers and PostgreSQL quoted identifiers/E-strings.
|
|
787
|
+
- **Rejected anywhere in query:** `UNION`, `INTO`, `COPY`; row-lock clauses (`FOR UPDATE`, `FOR NO KEY UPDATE`, `FOR SHARE`, `FOR KEY SHARE`, `FOR UPDATE NOWAIT`/`SKIP LOCKED`, MySQL `LOCK IN SHARE MODE`) — these take live row locks even inside the rolled-back transaction. The lock check is adapter-aware: `console_sql` validates with the active adapter's dialect, including MySQL double-quoted strings/backtick identifiers and PostgreSQL quoted identifiers/E-strings. Direct validator calls without a dialect conservatively scan all supported normalizations; packaged `console_sql` refuses unrecognized adapter families. Every view is scanned under both MySQL executable-comment (`/*!...*/`) semantics, so `#` comments and version-guarded comments cannot split a clause apart.
|
|
775
788
|
- **Function allowlist (the authoritative function control):** every function-call-shaped identifier must appear in `ALLOWED_FUNCTIONS`, a conservative set of pure read-only functions (aggregates, window functions, string/number/date/JSON readers) kept portable across MySQL, PostgreSQL, and SQLite. Anything else is rejected by name, quoted forms (`"pg_terminate_backend"(…)`) included. This is an allowlist because a denylist cannot enumerate every side-effecting function (`nextval`, `pg_advisory_lock`, `pg_terminate_backend`, …). A legacy `DANGEROUS_FUNCTIONS` denylist (`pg_sleep`, `lo_import`, `lo_export`, `pg_read_file`, `pg_write_file`, `load_file`, `sleep`, `benchmark`) still runs first as belt-and-suspenders.
|
|
776
789
|
- **Rejected patterns:** multiple statements (semicolons), writable CTEs (every `AS (...)` body is checked, so a writable CTE in any WITH position is refused — `WITH a AS (SELECT 1), b AS (DELETE FROM users RETURNING *) SELECT * FROM b`), a CTE list attached to top-level DML (`WITH a AS (SELECT 1) DELETE FROM users RETURNING *`), comment-hidden injections
|
|
777
790
|
|
|
@@ -799,13 +812,15 @@ to enforce their narrower parameterized scope grammar.
|
|
|
799
812
|
- **HTTP:** Check that the Rails server is running and listening on the expected port. An unauthenticated `curl http://localhost:3000/mcp/console` should return `401` when the enabled middleware and bearer-auth guard are mounted. A request with the configured bearer token proceeds to MCP protocol handling.
|
|
800
813
|
- **All modes:** Run `bundle exec rake woods:console` directly in a terminal. It should hang (waiting for MCP protocol input) rather than exit immediately. If it exits, check the error output.
|
|
801
814
|
|
|
802
|
-
|
|
815
|
+
<a id="rails-boot-noise-breaks-mcp-protocol"></a>
|
|
816
|
+
|
|
817
|
+
### Rails logs break MCP protocol
|
|
803
818
|
|
|
804
|
-
|
|
819
|
+
Prefer `bundle exec rake woods:console`: it captures output before the Rails environment boots. Direct `rails runner` invocation can redirect output only after Rails has booted; it cannot recover an already contaminated protocol stream.
|
|
805
820
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
821
|
+
The runtime isolation fix is included in Woods `2.0.0`. Earlier builds restore stdout after boot, so a logger that writes there can interleave SQL or application logs with MCP responses. On those builds, configure the Console process's application logger to write to stderr or a file. Discarding stderr does not fix logs written to stdout.
|
|
822
|
+
|
|
823
|
+
With a build containing the fix, application output remains on stderr during tool calls. If protocol contamination persists, inspect wrapper scripts and output emitted before the rake task starts; reserve stdout for MCP and retain stderr for diagnosis. Do not disable Console redaction or credential scanning to troubleshoot transport logging.
|
|
809
824
|
|
|
810
825
|
### Models not visible to `console_status`
|
|
811
826
|
|
|
@@ -900,3 +915,67 @@ These corrections require `2.0.0.beta4` or a reviewed development revision that
|
|
|
900
915
|
contains them. Confirm that a patched release is available before selecting it.
|
|
901
916
|
On affected versions, disable Console where these policies are required; Index MCP
|
|
902
917
|
can stay enabled because it reads the published code index separately.
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
## Maintenance policy corrections
|
|
921
|
+
|
|
922
|
+
The 2.0.1 maintenance patch applies authentication and origin policy to each
|
|
923
|
+
Console HTTP mount. Keep the normal Railtie setup: these additional checks do not
|
|
924
|
+
make an unreviewed manual mount the recommended installation path. Configure
|
|
925
|
+
allowed origins before boot and restart after changes; malformed entries fail
|
|
926
|
+
once at boot with the offending entry identified.
|
|
927
|
+
|
|
928
|
+
Protected collection values are masked as complete cells. EAV key policy checks
|
|
929
|
+
both stored and cast keys, including in predicates and ordering. Raw SQL refuses
|
|
930
|
+
ambiguous protected source identity, protected whole-row projections, positional
|
|
931
|
+
ordering that could expose protected values, and unsupported result types.
|
|
932
|
+
Explicit unaliased scalar columns and the structured tools are the recovery path.
|
|
933
|
+
|
|
934
|
+
SQL dialect detection follows adapter ancestry before adapter names. PostgreSQL
|
|
935
|
+
subclasses, Mysql2, MariaDB, Trilogy and SQLite use their applicable policies.
|
|
936
|
+
Genuinely unknown families are refused only by raw `console_sql`; this restriction
|
|
937
|
+
does not disable structured Tier-1 tools. Existing tool opt-ins remain unchanged.
|
|
938
|
+
|
|
939
|
+
PostgreSQL Unicode-escaped identifiers are refused by `console_sql` before
|
|
940
|
+
execution. Use ordinary identifiers or standard quoted identifiers instead;
|
|
941
|
+
structured query tools are unaffected by this syntax restriction.
|
|
942
|
+
|
|
943
|
+
### Read policy compatibility
|
|
944
|
+
|
|
945
|
+
These rules describe the security-patch source; verify the installed revision
|
|
946
|
+
and loaded gem path until its release is published.
|
|
947
|
+
|
|
948
|
+
- **Column alias lists:** when either `console_redacted_columns` or
|
|
949
|
+
`console_redacted_key_values` is nonempty, `console_sql` refuses relation
|
|
950
|
+
and CTE column alias lists before execution, including lists on base tables,
|
|
951
|
+
derived tables, parenthesized `VALUES` sources and table functions. This applies
|
|
952
|
+
even when the selected names are not protected and independently of function
|
|
953
|
+
validation. Ordinary relation
|
|
954
|
+
aliases, CTEs without column lists and allowed scalar functions remain subject
|
|
955
|
+
to the normal SQL policy. Use explicit, unaliased protected columns or a
|
|
956
|
+
structured Console tool.
|
|
957
|
+
- **Conservative typed masking:** EAV type lookup matches the final source-table
|
|
958
|
+
name case-insensitively and includes every matching registered model, even
|
|
959
|
+
across schemas. Any matching type can cause masking. This deliberately may
|
|
960
|
+
mask extra values when table names differ only by case or share that final
|
|
961
|
+
name; qualifying the table does not narrow that type set.
|
|
962
|
+
- **Exact sensitive values:** `sensitive_keys` compares the stored and cast key
|
|
963
|
+
values with exact case after string conversion. Configure their actual raw or
|
|
964
|
+
cast spelling. `CredentialIndex` also matches credential substrings with exact
|
|
965
|
+
case; it does not decode hexadecimal binary output such as PostgreSQL `bytea`.
|
|
966
|
+
Binary cells have no general text-scanning guarantee: non-UTF-8 data can fail
|
|
967
|
+
JSON normalization before scanning. Put binary secret columns in
|
|
968
|
+
`console_redacted_columns` so they are masked before serialization.
|
|
969
|
+
- **Adapter boundary:** raw `console_sql` requires PostgreSQL, MySQL-family
|
|
970
|
+
(including Mysql2, MariaDB and Trilogy), or SQLite classification. Compatible
|
|
971
|
+
subclasses are recognized by ancestry. Unknown families receive a validation
|
|
972
|
+
refusal for raw SQL; structured tools remain available under their normal
|
|
973
|
+
gates. See [statement timeouts](#statement-timeout) for adapter limits.
|
|
974
|
+
- **SQL functions and select entries:** 2.x enforces a read-only function
|
|
975
|
+
allowlist; 1.6.x retains a function denylist. For `console_query`, provide one
|
|
976
|
+
expression per `select` array entry. 2.x refuses comma-combined entries that
|
|
977
|
+
1.6.4 splits before validation. Execution and typed redaction use the same
|
|
978
|
+
validated projection on all patched lines.
|
|
979
|
+
- **Association counts:** polymorphic `belongs_to` counts remain unsupported
|
|
980
|
+
on this maintenance line and fail closed with a generic execution error.
|
|
981
|
+
The 2.1 functional correction is not included in this backport.
|
data/docs/DOCKER_SETUP.md
CHANGED
|
@@ -87,9 +87,24 @@ docker compose exec app bundle exec rake woods:extract_framework
|
|
|
87
87
|
|
|
88
88
|
Run the watcher as its own development service or process-manager entry, not as a one-off terminal command. Docker Desktop bind mounts may not deliver reliable native filesystem events; set `WOODS_WATCH_POLL=1` for polling when needed. The watcher updates structural generations automatically, while semantic vectors still require `woods:embed_incremental`.
|
|
89
89
|
|
|
90
|
+
Use the application's actual Rails task entrypoint. If its root `Rakefile` wraps
|
|
91
|
+
Compose, the container may need `bundle exec rails woods:watch`. Keep the raw
|
|
92
|
+
task under one external restart owner: `restart: unless-stopped` recovers after
|
|
93
|
+
Docker restarts while respecting an intentional stop; `on-failure` covers failed
|
|
94
|
+
process exits but not Docker restart. Leave idle TTL unset for continuous work.
|
|
95
|
+
|
|
96
|
+
Validate `docker compose config`: explicit YAML anchor keys can replace inherited
|
|
97
|
+
mounts/environment, and short `depends_on` does not establish database readiness.
|
|
98
|
+
Preserve the existing source/bundle mounts and use the application's healthcheck
|
|
99
|
+
convention. With Grove, include the watcher in the applicable shared or isolated
|
|
100
|
+
services list and align source/index mounts to the selected worktree. Follow
|
|
101
|
+
[Docker and Grove verification](AUTOMATIC_MAINTENANCE.md#docker-verify-the-resolved-service)
|
|
102
|
+
instead of copying a generic service that loses required settings.
|
|
103
|
+
|
|
90
104
|
When host-side tasks or one-off containers read the daemon's shared index,
|
|
91
105
|
`WOODS_WATCH_TRUST_FOREIGN_HOST=1` lets those readers trust its recent heartbeat.
|
|
92
106
|
Set it in each reader process; Docker does not forward host variables by default.
|
|
107
|
+
Ordinary Index MCP reads do not need this trust or the extraction writer lock.
|
|
93
108
|
See [cross-host liveness](WATCH_DAEMON.md#cross-host-liveness) for the 15-minute
|
|
94
109
|
crash-detection bound and single-supervisor requirement.
|
|
95
110
|
|
data/docs/EVALUATION.md
CHANGED
|
@@ -90,8 +90,8 @@ bundle exec ruby -Ilib bench/evaluation/runner.rb
|
|
|
90
90
|
strategy selection also fail. The baseline format is developer-only and is
|
|
91
91
|
**not** the `EVAL_BASELINE_FILE` aggregate-threshold format.
|
|
92
92
|
|
|
93
|
-
B-190/B-191
|
|
94
|
-
|
|
93
|
+
B-190/B-191 baseline, with the #549 output-label refresh captured on Ruby 4.0.6
|
|
94
|
+
(five warmed pipeline repetitions per query):
|
|
95
95
|
|
|
96
96
|
| Strategy | Queries | Precision@5 | Recall | MRR | Mean actual context tokens |
|
|
97
97
|
|---|---:|---:|---:|---:|---:|
|
|
@@ -99,8 +99,14 @@ and 3.4.10 replay the same answers):
|
|
|
99
99
|
| Vector | 4 | 0.313 | 0.375 | 0.625 | 1,041.2 |
|
|
100
100
|
| Graph | 8 | 0.813 | 0.519 | 1.000 | 1,041.1 |
|
|
101
101
|
| Hybrid | 4 | 0.750 | 0.396 | 1.000 | 1,058.8 |
|
|
102
|
-
| Direct with type filtering | 4 | 0.375 | 0.750 | 0.625 |
|
|
103
|
-
| Within-type vector fallback | 4 | 0.400 | 1.000 | 1.000 | 1,
|
|
102
|
+
| Direct with type filtering | 4 | 0.375 | 0.750 | 0.625 | 552.0 |
|
|
103
|
+
| Within-type vector fallback | 4 | 0.400 | 1.000 | 1.000 | 1,251.8 |
|
|
104
|
+
|
|
105
|
+
The clearer `Retrieval metadata records` heading adds one exact `cl100k_base`
|
|
106
|
+
token to each of the eight direct/fallback contexts. The other 20 contexts,
|
|
107
|
+
retrieved identifiers and order, annotations, and quality metrics are unchanged.
|
|
108
|
+
The refresh reuses captured vectors and the pinned `tiktoken 0.11.0` tokenizer;
|
|
109
|
+
it performs no new model inference.
|
|
104
110
|
|
|
105
111
|
Precision@5 divides relevant hits by the actual returned slice size (up to five),
|
|
106
112
|
not always by five. Recall divides retrieved relevant units by all annotated
|
data/docs/EXTRACTOR_REFERENCE.md
CHANGED
|
@@ -32,6 +32,14 @@ Extractors discover code one of two ways:
|
|
|
32
32
|
|
|
33
33
|
Some extractors combine both (e.g., `JobExtractor` scans directories first, then supplements with `ApplicationJob.descendants`).
|
|
34
34
|
|
|
35
|
+
Discovery is not exhaustive. A standalone module under `app/models` that is
|
|
36
|
+
called through singleton methods is not discovered by the model/PORO paths;
|
|
37
|
+
conventional concerns and app modules included by live models have separate
|
|
38
|
+
concern discovery. This gap is tracked in [#552](https://github.com/lost-in-the/woods/issues/552).
|
|
39
|
+
Separately, dependency scanning does not capture every method-body constant
|
|
40
|
+
reference ([#475](https://github.com/lost-in-the/woods/issues/475)). A missing unit
|
|
41
|
+
or edge is not proof of unused code; cross-check the application source.
|
|
42
|
+
|
|
35
43
|
### Identifier naming (source-derived units)
|
|
36
44
|
|
|
37
45
|
File-based extractors derive an identifier in three steps, first match wins:
|
|
@@ -746,11 +754,15 @@ History is limited to commits reachable from `HEAD` in the past 365 days,
|
|
|
746
754
|
including merged branch history. Unmerged branches, remote refs, and tool
|
|
747
755
|
checkpoint refs do not contribute. Commands run against the application root;
|
|
748
756
|
when `WOODS_GIT_DIR` is set, `HEAD` belongs to that explicitly selected git
|
|
749
|
-
directory
|
|
757
|
+
directory. For a linked worktree, select its `worktrees/<id>` directory within
|
|
758
|
+
the complete shared Git layout; selecting the shared root instead uses the
|
|
759
|
+
primary checkout's HEAD. See the [worktree mount guide](TROUBLESHOOTING.md#git-directory-mounts-for-linked-worktrees).
|
|
750
760
|
|
|
751
761
|
After upgrading from a version that included all refs, run a full
|
|
752
762
|
`woods:extract` to replace previously published git metadata. Incremental
|
|
753
|
-
extraction refreshes only the units it rewrites.
|
|
763
|
+
extraction refreshes only the units it rewrites. A commit alone does not
|
|
764
|
+
necessarily trigger the source-file watcher; run full extraction when current
|
|
765
|
+
Git history is required.
|
|
754
766
|
|
|
755
767
|
| Field | Description |
|
|
756
768
|
|-------|-------------|
|
data/docs/FAQ.md
CHANGED
|
@@ -134,7 +134,7 @@ When a model includes a concern, the behavior defined in that concern is part of
|
|
|
134
134
|
|
|
135
135
|
### How do I update the index after code changes?
|
|
136
136
|
|
|
137
|
-
Use incremental mode
|
|
137
|
+
Use incremental mode to dispatch a selected batch of changed paths:
|
|
138
138
|
|
|
139
139
|
```bash
|
|
140
140
|
bundle exec rake woods:incremental
|
|
@@ -143,7 +143,12 @@ bundle exec rake woods:incremental
|
|
|
143
143
|
docker compose exec app bundle exec rake woods:incremental
|
|
144
144
|
```
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
The default Git range is `HEAD~1`; CI variables, an explicit range, or
|
|
147
|
+
`CHANGED_FILES` can select another batch. Incremental extraction also refreshes
|
|
148
|
+
affected concern consumers and re-runs whole-app extractors when their trigger
|
|
149
|
+
paths change. It can reduce work, but has no universal speedup: Rails boot, graph
|
|
150
|
+
work, and publication still take time. See the [incremental contract](INCREMENTAL_EXTRACTION.md)
|
|
151
|
+
for scope, whole-app triggers, and cases that require a full extraction.
|
|
147
152
|
|
|
148
153
|
---
|
|
149
154
|
|
|
@@ -411,7 +416,13 @@ When you run `rake woods:embed`, Woods generates embedding vectors for each extr
|
|
|
411
416
|
|
|
412
417
|
### What is the `codebase_retrieve` tool for?
|
|
413
418
|
|
|
414
|
-
`codebase_retrieve`
|
|
419
|
+
`codebase_retrieve` ranks extracted units for a natural-language query, such as
|
|
420
|
+
"find where user email validation happens". Default semantic mode requires an
|
|
421
|
+
embedding provider and vector store. Explicit lexical mode ranks published
|
|
422
|
+
extraction text without either: set `WOODS_RETRIEVAL_MODE=lexical` in the MCP
|
|
423
|
+
process environment and restart it. There is no automatic fallback between
|
|
424
|
+
modes. See the [retrieval guide](RETRIEVAL_GUIDE.md#embedding-free-lexical-retrieval)
|
|
425
|
+
for setup, ranking evidence, and the estimated text-budget contract.
|
|
415
426
|
|
|
416
427
|
---
|
|
417
428
|
|
data/docs/GETTING_STARTED.md
CHANGED
|
@@ -12,15 +12,15 @@ If an agent will perform the installation, use the safety and handoff checklist
|
|
|
12
12
|
|
|
13
13
|
## 1. Install the gem
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
that **exact version is published**
|
|
17
|
-
|
|
15
|
+
Choose a version from the [RubyGems versions page](https://rubygems.org/gems/woods/versions)
|
|
16
|
+
and confirm that **exact version is published** before editing the Gemfile.
|
|
17
|
+
A prepared release checkout can update the documentation
|
|
18
18
|
before its gem is published; if the version is absent, choose an available
|
|
19
19
|
version or wait for publication.
|
|
20
20
|
|
|
21
21
|
If the published 2.x line has only beta or release-candidate versions, use an
|
|
22
|
-
exact pin to the published prerelease
|
|
23
|
-
|
|
22
|
+
exact pin to the published prerelease; `~> 2.0` does not select prereleases.
|
|
23
|
+
Follow the selected version's
|
|
24
24
|
tag documentation. The `main` guides may describe features absent from the
|
|
25
25
|
published gem.
|
|
26
26
|
|
|
@@ -148,21 +148,22 @@ Reconnect the MCP server and check `woods_status`. For OpenAI, pgvector, Qdrant,
|
|
|
148
148
|
|
|
149
149
|
### Keep the index current
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
# Procfile.dev
|
|
159
|
-
web: bin/rails server
|
|
160
|
-
woods: bundle exec rake woods:watch
|
|
161
|
-
```
|
|
151
|
+
Enable one watcher through the application's normal development startup. The
|
|
152
|
+
[managed startup guide](WATCH_DAEMON.md#managed-development-startup) covers
|
|
153
|
+
opt-in Puma integration for a simple Rails application, an owned Foreman entry
|
|
154
|
+
for existing Procfile workflows, and external supervision for Docker/Grove.
|
|
155
|
+
The managed launcher and generator are **included in Woods `2.0.0`**;
|
|
156
|
+
check the installed commands before using them. Older packages can run the raw
|
|
157
|
+
`bin/rails woods:watch` task under an external restart-capable supervisor.
|
|
162
158
|
|
|
163
159
|
On startup it reconciles changes made since the last successful generation. While running it batches file events, reloads Rails code when safe, extracts affected units, and publishes atomically. The Index Server detects the new generation on its next call and reloads automatically. After the initial extraction, ordinary code edits need no manual extraction or MCP restart.
|
|
164
160
|
|
|
165
|
-
When dependencies, initializers, database configuration, credentials, or schema
|
|
161
|
+
When dependencies, initializers, database configuration, credentials, or schema
|
|
162
|
+
change, the raw task exits 75 to request a fresh Rails boot. The managed launcher
|
|
163
|
+
handles that restart internally; an external supervisor must handle it for the
|
|
164
|
+
raw task. Do not add the bare task to Foreman. Docker bind mounts may require
|
|
165
|
+
polling. See the [low-interaction workflow](AUTOMATIC_MAINTENANCE.md) for ownership,
|
|
166
|
+
hooks, and the checks that establish automatic maintenance is active.
|
|
166
167
|
|
|
167
168
|
The watcher maintains the structural index. If semantic retrieval is enabled, also run `bin/rails woods:embed_incremental` to update vectors. Without a resident watcher, run `bin/rails woods:incremental` after changes. Use a full `woods:extract` after major upgrades or when validation reports drift. CI and shared-artifact patterns are covered in [Incremental extraction](INCREMENTAL_EXTRACTION.md).
|
|
168
169
|
|
|
@@ -89,8 +89,13 @@ Recovery choices, in the order they are worth trying:
|
|
|
89
89
|
3. Run a full `woods:extract` when the range cannot be repaired this run.
|
|
90
90
|
|
|
91
91
|
The diff itself is rooted at the extracted application (`git -C Rails.root`),
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
independently of the process working directory. An explicit `WOODS_GIT_DIR`
|
|
93
|
+
selects that Git directory's HEAD for both the diff and manifest provenance.
|
|
94
|
+
For a linked worktree, use its worktree-specific directory within the complete
|
|
95
|
+
shared layout; selecting the shared root instead reads the primary checkout's
|
|
96
|
+
HEAD. See [worktree mount verification](TROUBLESHOOTING.md#git-directory-mounts-for-linked-worktrees).
|
|
97
|
+
Git-only changes may not trigger the source-file watcher; see the
|
|
98
|
+
[watcher limitation](WATCH_DAEMON.md#watcher-backends).
|
|
94
99
|
|
|
95
100
|
Named, source-defined app modules included by runtime models are tracked as concern units even
|
|
96
101
|
outside `concerns/` directories. Changing their source refreshes their includers,
|
|
@@ -100,7 +105,7 @@ to populate these previously missing source mappings.
|
|
|
100
105
|
|
|
101
106
|
## Handled source errors and retry
|
|
102
107
|
|
|
103
|
-
|
|
108
|
+
Included in Woods `2.0.0`: when an incremental extraction or named refresh
|
|
104
109
|
records a handled consumer error (for example malformed locale or schedule
|
|
105
110
|
YAML), it raises `Woods::ExtractionError` before publishing. Empty output from
|
|
106
111
|
that failed consumer does not authorize replacing or deleting its last-good
|
data/docs/INDEX_LAYOUT.md
CHANGED
|
@@ -94,8 +94,8 @@ families and `manifest.provenance.mode`; it is not Rails runtime evidence.
|
|
|
94
94
|
### Semantic graph validation
|
|
95
95
|
|
|
96
96
|
`woods:validate` checks raw graph data against the unit indexes and artifacts in
|
|
97
|
-
one pinned published generation. This validation is
|
|
98
|
-
|
|
97
|
+
one pinned published generation. This validation is included in Woods `2.0.0`.
|
|
98
|
+
It checks the shapes of `nodes`, `edges`, `reverse`, `file_map`,
|
|
99
99
|
`type_index`, and optional `variants`; typed identities must be unique and agree
|
|
100
100
|
with the actual indexed units. Forward sources must exist. Reverse, file, and
|
|
101
101
|
type memberships must match the union of primary and variant contributions.
|