@gmickel/gno 2.7.1 → 2.8.0
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.
- package/README.md +3 -2
- package/assets/skill/SKILL.md +8 -1
- package/assets/skill/cli-reference.md +8 -1
- package/assets/skill/examples.md +2 -1
- package/assets/skill/mcp-reference.md +3 -1
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/{gno-browser-clipper-v2.7.1.zip → gno-browser-clipper-v2.8.0.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.8.0.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/spec/cli.md +48 -6
- package/spec/db/schema.sql +0 -1
- package/spec/mcp.md +18 -3
- package/spec/output-schemas/audit-report.schema.json +18 -4
- package/spec/output-schemas/backlinks.schema.json +4 -0
- package/spec/output-schemas/collection-list.schema.json +13 -0
- package/spec/output-schemas/graph.schema.json +2 -0
- package/spec/output-schemas/links-list.schema.json +4 -0
- package/spec/output-schemas/status.schema.json +15 -0
- package/src/cli/commands/audit.ts +23 -4
- package/src/cli/commands/collection/list.ts +39 -5
- package/src/cli/commands/embed.ts +3 -3
- package/src/cli/commands/links.ts +34 -131
- package/src/cli/commands/shared.ts +7 -0
- package/src/cli/commands/status.ts +5 -0
- package/src/cli/program.ts +12 -2
- package/src/config/loader.ts +43 -0
- package/src/config/types.ts +8 -0
- package/src/core/audit-contract.ts +16 -4
- package/src/core/audit-freshness.ts +11 -1
- package/src/core/audit-links.ts +145 -25
- package/src/core/audit-provenance.ts +11 -4
- package/src/core/audit-workspace.ts +19 -4
- package/src/core/audit.ts +67 -15
- package/src/core/context-compiler.ts +3 -0
- package/src/core/context-evidence.ts +11 -0
- package/src/core/graph-edge-confidence.ts +23 -1
- package/src/core/host-paths.ts +1 -0
- package/src/core/knowledge-impact.ts +28 -0
- package/src/core/link-workspace.ts +324 -0
- package/src/core/retrieval-replay-candidate.ts +6 -0
- package/src/core/retrieval-trace-request.ts +3 -0
- package/src/index.ts +14 -1
- package/src/ingestion/graph-reconciliation.ts +77 -15
- package/src/ingestion/source-availability/darwin-path.ts +9 -3
- package/src/ingestion/sync.ts +22 -1
- package/src/ingestion/types.ts +14 -0
- package/src/llm/inference-scope.ts +4 -3
- package/src/mcp/http-egress.ts +42 -3
- package/src/mcp/tools/audit.ts +11 -2
- package/src/mcp/tools/changes.ts +1 -0
- package/src/mcp/tools/links.ts +3 -0
- package/src/mcp/tools/sessions.ts +33 -4
- package/src/mcp/tools/status.ts +3 -0
- package/src/pipeline/expansion.ts +19 -31
- package/src/pipeline/graph-retrieval.ts +22 -2
- package/src/pipeline/hybrid.ts +1 -1
- package/src/pipeline/types.ts +6 -3
- package/src/serve/findings-pass.ts +1 -1
- package/src/serve/public/pages/GraphView.tsx +2 -0
- package/src/serve/routes/changes.ts +6 -1
- package/src/serve/routes/links.ts +13 -0
- package/src/serve/routes/sessions.ts +41 -53
- package/src/sessions/config-refresh.ts +111 -0
- package/src/store/migrations/033-drop-documents-active-index.ts +30 -0
- package/src/store/migrations/034-collection-link-workspace.ts +47 -0
- package/src/store/migrations/index.ts +4 -0
- package/src/store/sqlite/adapter.ts +390 -231
- package/src/store/sqlite/eligibility.ts +8 -2
- package/src/store/sqlite/graph-link-resolver.ts +252 -5
- package/src/store/sqlite/graph-neighbors.ts +147 -40
- package/src/store/sqlite/graph-reference-state.ts +13 -2
- package/src/store/sqlite/workspace-link-resolver.ts +654 -0
- package/src/store/types.ts +49 -3
- package/src/store/vector/stats.ts +1 -1
- package/browser-extension/artifacts/gno-browser-clipper-v2.7.1.zip.sha256 +0 -1
package/README.md
CHANGED
|
@@ -139,7 +139,7 @@ See the [guide](docs/COMPILED-CONTEXT.md).
|
|
|
139
139
|
|
|
140
140
|
<!-- public-truth:current-version -->
|
|
141
141
|
|
|
142
|
-
> Current source version: **v2.
|
|
142
|
+
> Current source version: **v2.8.0**. See [CHANGELOG.md](./CHANGELOG.md).
|
|
143
143
|
|
|
144
144
|
<!-- /public-truth -->
|
|
145
145
|
|
|
@@ -216,7 +216,8 @@ See the [guide](docs/COMPILED-CONTEXT.md).
|
|
|
216
216
|
and traces. Authentication never overrides policy.
|
|
217
217
|
- **Source availability (`any` | `local`)**: opt-in `local` indexes only files
|
|
218
218
|
already on disk and never makes a cloud provider download one. Supported on
|
|
219
|
-
macOS with Google Drive
|
|
219
|
+
macOS with Google Drive (My Drive and Shared drives), iCloud Drive, and
|
|
220
|
+
OneDrive SharePoint library roots.
|
|
220
221
|
Cloud-only files are skipped and reported, not treated as conversion errors,
|
|
221
222
|
and documents under a cloud-only folder stay indexed. Other platforms fail
|
|
222
223
|
with an error. On a 5,000-file all-local collection, `local` scans about 1%
|
package/assets/skill/SKILL.md
CHANGED
|
@@ -352,6 +352,12 @@ offline audits inspect parsed local links, explicitly declared capture/logical-
|
|
|
352
352
|
record provenance, and observable source/index freshness. They never repair,
|
|
353
353
|
rewrite, persist findings, judge factual truth, or replace retrieval.
|
|
354
354
|
|
|
355
|
+
`--max-findings` accepts `all` (MCP `maxFindings: "all"`) to export every
|
|
356
|
+
finding. Link findings carry `referenceKind`, `resolutionStatus`, and
|
|
357
|
+
`resolvedScope` in their evidence detail; ambiguous vault links list the tied
|
|
358
|
+
`candidates`. Report `truncation.snapshotTruncated` as "totals cover the
|
|
359
|
+
bounded snapshot, not the whole index".
|
|
360
|
+
|
|
355
361
|
Treat exit `4` as a complete report with findings. Exit `5` or report status
|
|
356
362
|
`partial`/`changed_during_audit` means evidence is unavailable, inconclusive,
|
|
357
363
|
cancelled, truncated, or repeatedly changed—never healthy. Preserve stable
|
|
@@ -389,7 +395,7 @@ remaining steps apply under the default `full` profile.
|
|
|
389
395
|
- MCP text is the compact `gno-context-agent-v1` evidence projection. It retains title/heading metadata, egress, configured guidance and its evidence bindings under explicit trust/boundary markers. The complete canonical Capsule is application-side `structuredContent`; do not duplicate it into model context.
|
|
390
396
|
3. Use `gno_ask` only for explicit local verified synthesis. Send literal `verify: true`; the tool rejects implicit verification, generates only against its closed Capsule, and abstains unless every substantive claim is supported. Preserve exact spans, gaps, semantic capability state, and abstention. This does not guarantee corpus completeness or source truth.
|
|
391
397
|
4. Use `gno_query` for interactive lookup or manual retrieval control. It returns snippets plus `uri`, `docid`, often `line`, and sometimes `context`. Treat `context` as user-configured guidance for interpreting that exact result; cite source content at the returned URI/lines, not the guidance itself. Bounded graph expansion is on by default; set `graph: false` or `noGraph: true` only for an explicit BM25/vector-only path.
|
|
392
|
-
5. Use graph/link expansion for relationship context: `gno_graph_query` for typed relationship traversal, `gno_graph_neighbors` for nearby documents, `gno_graph_path` for "how are X and Y connected?", `gno_links`/`gno_backlinks` for one-document link expansion, and `gno_similar` for semantic neighbors. Prefer explicit or typed edges over inferred, ambiguous, or similarity edges when confidence matters.
|
|
398
|
+
5. Use graph/link expansion for relationship context: `gno_graph_query` for typed relationship traversal, `gno_graph_neighbors` for nearby documents, `gno_graph_path` for "how are X and Y connected?", `gno_links`/`gno_backlinks` for one-document link expansion, and `gno_similar` for semantic neighbors. Prefer explicit or typed edges over inferred, ambiguous, or similarity edges when confidence matters. Plain `[[Note]]` links resolve across collections of the same vault (link workspace), so backlinks and impact can name other collections; pass `collection`/`collections` to keep results inside the user's scope. Never tell users to rewrite links into `[[collection:Note]]` to make them resolve.
|
|
393
399
|
6. Use `gno_query_diagnose` when a known target document should have appeared but did not; it reports BM25/vector/fusion/graph/rerank stage presence and filter state.
|
|
394
400
|
7. Use `gno_get` with `fromLine`/`lineCount` for targeted reads, or `gno_multi_get` to batch top refs.
|
|
395
401
|
8. Use `gno_section` only when you need a durable section locator or must re-resolve one after edits. Prefer search → `gno_get` for ordinary retrieval. `action=create` needs `ref` plus exactly one of `anchor`|`line`; `action=resolve` needs `ref` plus `target`. Cite or open content only for `exact`/`recovered` results, then follow the tool's ready-to-use `gno_get` guidance (`fromLine = lineStart`; `lineCount = lineEnd - lineStart + 1`). Never navigate or cite `ambiguous`/`stale`/`missing`.
|
|
@@ -418,6 +424,7 @@ changed source:
|
|
|
418
424
|
gno changes --since 2026-07-20T00:00:00Z --json
|
|
419
425
|
gno diff gno://notes/plan.md --json
|
|
420
426
|
gno impact gno://notes/plan.md --max-depth 3 --json
|
|
427
|
+
gno impact gno://notes/plan.md --collection notes --json # stay in scope
|
|
421
428
|
```
|
|
422
429
|
|
|
423
430
|
Treat cursors and change IDs as opaque. Journal results are bounded,
|
|
@@ -594,7 +594,8 @@ gno impact gno://notes/plan.md --max-depth 3 --json
|
|
|
594
594
|
`changes` accepts an ISO time or opaque cursor and optional collection/limit.
|
|
595
595
|
`diff` reports structural headings, links, and typed-relationship changes for
|
|
596
596
|
one retained change. `impact` follows inbound evidence edges with explicit
|
|
597
|
-
depth/node/edge/frontier/visited bounds
|
|
597
|
+
depth/node/edge/frontier/visited bounds; repeat `-c, --collection <name>` to
|
|
598
|
+
keep the traversal (and every path step) inside those collections. Expired journal history is reported,
|
|
598
599
|
not reconstructed.
|
|
599
600
|
|
|
600
601
|
## Private Retrieval Traces
|
|
@@ -679,6 +680,12 @@ gno backlinks <ref> [options]
|
|
|
679
680
|
`--relation <type>` to query semantic typed edges instead of positional
|
|
680
681
|
wiki/markdown links. Do not combine `--type` with `--edge-type`.
|
|
681
682
|
|
|
683
|
+
Plain `[[Note]]` and `[[Folder/Note]]` links resolve across all collections
|
|
684
|
+
that share one vault (the nearest `.obsidian` folder, or `workspaceRoot` in
|
|
685
|
+
the config): exact path, then same folder, then shallowest file; ties stay
|
|
686
|
+
unresolved and are listed by `gno audit links`. JSON names the other
|
|
687
|
+
collection (`resolvedCollection` for links, `sourceCollection` for backlinks).
|
|
688
|
+
|
|
682
689
|
### gno graph query
|
|
683
690
|
|
|
684
691
|
Bounded typed-edge traversal from a document.
|
package/assets/skill/examples.md
CHANGED
|
@@ -314,7 +314,8 @@ gno similar gno://notes/auth.md --cross-collection
|
|
|
314
314
|
# In your documents:
|
|
315
315
|
|
|
316
316
|
See [[API Design]] for details.
|
|
317
|
-
Check [[
|
|
317
|
+
Check [[Projects/Plan]] for a path link (resolves across collections of one vault).
|
|
318
|
+
Check [[work:Project Plan]] to name the target collection explicitly.
|
|
318
319
|
Read [[Security#OAuth]] for specific section.
|
|
319
320
|
```
|
|
320
321
|
|
|
@@ -144,7 +144,9 @@ lives in `structuredContent`; its text projection is deliberately compact and
|
|
|
144
144
|
should not be expanded back into duplicate model context.
|
|
145
145
|
|
|
146
146
|
Use `gno_changes`, `gno_diff`, and `gno_impact` for retained metadata history
|
|
147
|
-
and bounded dependency questions.
|
|
147
|
+
and bounded dependency questions. `gno_impact` takes optional `collections`
|
|
148
|
+
to keep the traversal in scope; links in a vault can resolve across
|
|
149
|
+
collections, so unscoped graph tools cover every collection. Use `gno_trace_list` and `gno_trace_show` for
|
|
148
150
|
private local diagnostics. Invoke `gno_trace_label` only when the user
|
|
149
151
|
explicitly provides a relevant, irrelevant, or missing-expected judgment.
|
|
150
152
|
Trace export/replay/delete/purge and saved-Capsule watch lifecycle remain
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2066003653182eb93964c5c058c86f691abf536f5093d1d0e8db2f382aedce19 gno-browser-clipper-v2.8.0.zip
|
package/package.json
CHANGED
package/spec/cli.md
CHANGED
|
@@ -263,6 +263,8 @@ gno status [--json|--md]
|
|
|
263
263
|
{
|
|
264
264
|
"name": "work",
|
|
265
265
|
"path": "/path",
|
|
266
|
+
"workspaceRoot": "/vault",
|
|
267
|
+
"workspaceSource": "detected",
|
|
266
268
|
"documentCount": 100,
|
|
267
269
|
"chunkCount": 500,
|
|
268
270
|
"embeddedCount": 500
|
|
@@ -624,9 +626,11 @@ refuses descent into dataless or availability-unknown directories
|
|
|
624
626
|
(`DATALESS_DIRECTORY` skip, or the fail-closed codes above) and preserves
|
|
625
627
|
previously indexed descendants under those unproven prefixes rather than
|
|
626
628
|
marking them inactive. Eligible files have no availability `errorCode`.
|
|
627
|
-
Evidence-qualified scope: Google Drive
|
|
628
|
-
|
|
629
|
-
|
|
629
|
+
Evidence-qualified scope: Google Drive (`My Drive` and immediate Shared drives
|
|
630
|
+
under `Shared drives/<drive>`; the `Shared drives` folder itself is
|
|
631
|
+
unsupported), iCloud Drive, and OneDrive only for the tested OS/provider
|
|
632
|
+
configuration; OneDrive only for the two validated immediate SharePoint library
|
|
633
|
+
roots. No Windows/Linux guarantee; metadata/provider
|
|
630
634
|
bookkeeping may occur; GNO does not pin/evict/download as product behavior.
|
|
631
635
|
Source availability is distinct from `egressPolicy` (where derived content may
|
|
632
636
|
travel).
|
|
@@ -886,6 +890,15 @@ projection.
|
|
|
886
890
|
content-free decision, lineage, partial disclosure, audit metadata, and
|
|
887
891
|
remediation contract.
|
|
888
892
|
|
|
893
|
+
`workspaceSource` is `detected` (nearest `.obsidian/` ancestor-or-self of the
|
|
894
|
+
collection root), `configured` (`workspaceRoot` setting), `disabled`
|
|
895
|
+
(`workspaceRoot: false`), `unavailable` (the root or an ancestor could not be
|
|
896
|
+
inspected; links stay collection-scoped) or `none`. `workspaceRoot` is the
|
|
897
|
+
effective workspace root, present only for `detected`/`configured`, and is a
|
|
898
|
+
same-host-only field like `path`. Terminal output adds a `Link workspace:` line
|
|
899
|
+
per workspace collection. `gno collection list` reports the same per
|
|
900
|
+
collection as `effectiveWorkspaceRoot` and `workspaceSource`.
|
|
901
|
+
|
|
889
902
|
### gno audit
|
|
890
903
|
|
|
891
904
|
Read-only, offline knowledge-integrity audits. This command is distinct from
|
|
@@ -901,8 +914,17 @@ gno audit [links|provenance|freshness|all] [--collection <name>...] \
|
|
|
901
914
|
[--json] [--output <path>]
|
|
902
915
|
```
|
|
903
916
|
|
|
904
|
-
The default category is `all`; `--max-findings` defaults to 100 and
|
|
905
|
-
|
|
917
|
+
The default category is `all`; `--max-findings` defaults to 100 and accepts an
|
|
918
|
+
integer from 1 to 100000 or `all`. `all` returns every finding of the bounded
|
|
919
|
+
audit snapshot, and per-rule caps follow the same value. Any other value
|
|
920
|
+
(zero, negative, non-integer, above 100000) is a validation error (exit 1)
|
|
921
|
+
that states the accepted range. Truncation limits returned findings but
|
|
922
|
+
preserves exact totals. The report's `truncation` block reports three separate
|
|
923
|
+
conditions: `findingsTruncated` (the finding cap cut the list),
|
|
924
|
+
`snapshotTruncated` (the bounded snapshot of 50,000 documents/links was cut, so
|
|
925
|
+
totals cover the snapshot only and are not complete-index totals), and
|
|
926
|
+
`evidenceTruncated` (evidence items, tied-candidate lists, or evidence detail
|
|
927
|
+
text were shortened).
|
|
906
928
|
`--output` writes only the requested report artifact with local file
|
|
907
929
|
permissions. Human output renders the same report represented by
|
|
908
930
|
`audit-report.schema.json`.
|
|
@@ -924,6 +946,20 @@ healthy.
|
|
|
924
946
|
- `4` — complete report with findings
|
|
925
947
|
- `5` — partial, inconclusive, unavailable, or changed-during-audit evidence
|
|
926
948
|
|
|
949
|
+
Link findings resolve with the workspace-aware resolver (see
|
|
950
|
+
docs/ARCHITECTURE.md "Resolution"). Their evidence `detail` JSON carries
|
|
951
|
+
separate `referenceKind` (`wiki-name`, `wiki-path`, `explicit-collection`,
|
|
952
|
+
`markdown`), `resolutionStatus` (`unresolved`, `ambiguous`) and
|
|
953
|
+
`resolvedScope` (`same-collection`, `cross-collection`, `explicit-collection`,
|
|
954
|
+
or null when unresolved). Ambiguous workspace links add `candidateCount` and
|
|
955
|
+
`candidates` (tied candidate URIs in canonical path order); in a
|
|
956
|
+
collection-scoped audit, candidates outside the requested collections are
|
|
957
|
+
counted in `candidatesWithheld` and never named, and a list longer than the
|
|
958
|
+
detail bound sets `candidatesTruncated` (and `truncation.evidenceTruncated`).
|
|
959
|
+
Orphans stay "no incoming or outgoing resolved links", with connectivity drawn
|
|
960
|
+
from the whole index even when the audited documents are scoped; a tied link
|
|
961
|
+
connects nothing.
|
|
962
|
+
|
|
927
963
|
The JSON contract is versioned as `gno://schemas/audit-report@1.0`. Finding IDs
|
|
928
964
|
are stable SHA-256 identities derived from rule, normalized subject/location,
|
|
929
965
|
and load-bearing evidence. Wall-clock timing and traversal order do not affect
|
|
@@ -4179,13 +4215,19 @@ Find active documents that depend on one document through inbound typed,
|
|
|
4179
4215
|
wiki-link, or Markdown-link edges.
|
|
4180
4216
|
|
|
4181
4217
|
```bash
|
|
4182
|
-
gno impact <doc> [--max-depth <n>] [--max-nodes <n>] [--max-edges <n>] [--frontier-limit <n>] [--visited-limit <n>] [--json]
|
|
4218
|
+
gno impact <doc> [-c, --collection <name>...] [--max-depth <n>] [--max-nodes <n>] [--max-edges <n>] [--frontier-limit <n>] [--visited-limit <n>] [--json]
|
|
4183
4219
|
```
|
|
4184
4220
|
|
|
4185
4221
|
The traversal is cycle-safe and enforces depth, node, edge, frontier, and
|
|
4186
4222
|
visited-row caps. Every impacted document includes one deterministic
|
|
4187
4223
|
dependency-to-root evidence path. JSON output uses `impact.schema.json`.
|
|
4188
4224
|
|
|
4225
|
+
`--collection` (repeatable) limits the traversal to those collections: only
|
|
4226
|
+
their documents are visited, returned, or used as a path step, so a document
|
|
4227
|
+
outside the scope never bridges two in-scope documents. Omitted means every
|
|
4228
|
+
indexed collection. An unknown collection, or a `<doc>` outside the requested
|
|
4229
|
+
collections, is a validation error (exit 1).
|
|
4230
|
+
|
|
4189
4231
|
**Exit Codes:**
|
|
4190
4232
|
|
|
4191
4233
|
- 0: Success
|
package/spec/db/schema.sql
CHANGED
|
@@ -172,7 +172,6 @@ CREATE TABLE IF NOT EXISTS documents (
|
|
|
172
172
|
);
|
|
173
173
|
|
|
174
174
|
CREATE INDEX IF NOT EXISTS idx_documents_collection ON documents(collection);
|
|
175
|
-
CREATE INDEX IF NOT EXISTS idx_documents_active ON documents(active);
|
|
176
175
|
CREATE INDEX IF NOT EXISTS idx_documents_mirror_hash ON documents(mirror_hash);
|
|
177
176
|
CREATE INDEX IF NOT EXISTS idx_documents_docid ON documents(docid);
|
|
178
177
|
CREATE INDEX IF NOT EXISTS idx_documents_uri ON documents(uri);
|
package/spec/mcp.md
CHANGED
|
@@ -351,7 +351,8 @@ Collection names are case-insensitive on input and normalized to lowercase in re
|
|
|
351
351
|
`gno_audit` is a read-only, offline tool that returns the same
|
|
352
352
|
`gno://schemas/audit-report@1.0` report as `gno audit`. Its closed input accepts
|
|
353
353
|
`category` (`links`, `provenance`, `freshness`, or `all`), collection/path/tag
|
|
354
|
-
filters, and `maxFindings` (1
|
|
354
|
+
filters, and `maxFindings` (an integer from 1 to 100000, or `"all"` for every
|
|
355
|
+
finding of the bounded snapshot; default 100). `maxAgeDays`, `orphanRoots`, and
|
|
355
356
|
`orphanIgnorePrefixes` are optional explicit policy inputs. Request
|
|
356
357
|
cancellation returns a partial report rather than a false clean result. The
|
|
357
358
|
tool is annotated with
|
|
@@ -1841,8 +1842,15 @@ pending), `sourceUnavailable`, `staleParser` and last import time, and the
|
|
|
1841
1842
|
switches, pending and running work, last run, last success, next due time,
|
|
1842
1843
|
recovery action). The result contains no host paths.
|
|
1843
1844
|
|
|
1845
|
+
Each call (and each `gno_sessions_import` call) first re-reads the server's
|
|
1846
|
+
config file and adopts it when it changed, so source changes made by another
|
|
1847
|
+
process show without a restart. An unchanged file is a no-op; a source-only
|
|
1848
|
+
change keeps open HTTP sessions.
|
|
1849
|
+
|
|
1844
1850
|
**Errors:** `SESSIONS_NOT_CONFIGURED` when the server's config has no
|
|
1845
|
-
`sessions` block
|
|
1851
|
+
`sessions` block; `SESSIONS_RUNTIME_FAILURE` when the config file cannot be
|
|
1852
|
+
read (never answered from the stale config); `SESSIONS_BINDING_MISMATCH` when
|
|
1853
|
+
the file is now bound to a different index (not adopted).
|
|
1846
1854
|
|
|
1847
1855
|
### gno_sessions_import
|
|
1848
1856
|
|
|
@@ -2371,7 +2379,14 @@ structure is derived from `structureDelta.truncated`.
|
|
|
2371
2379
|
|
|
2372
2380
|
### gno_impact
|
|
2373
2381
|
|
|
2374
|
-
Read-only inbound dependency traversal for `ref`.
|
|
2382
|
+
Read-only inbound dependency traversal for `ref`. Optional `collections`
|
|
2383
|
+
(array of collection names) limits the traversal as `gno impact --collection`
|
|
2384
|
+
does; omitted means every collection. Over Streamable HTTP, egress policy is
|
|
2385
|
+
checked on `collections` (every collection when omitted, because the result
|
|
2386
|
+
can reach any collection a link resolves into) and on the collection of `ref`;
|
|
2387
|
+
a docid `ref` is checked against every collection. The same rule applies to
|
|
2388
|
+
`gno_backlinks` and `gno_graph*` refs, and `gno_similar` with
|
|
2389
|
+
`crossCollection: true` is checked against every collection. Inputs `maxDepth`,
|
|
2375
2390
|
`maxNodes`, `maxEdges`, `frontierLimit`, and `visitedLimit` use the same bounds
|
|
2376
2391
|
as CLI/REST/SDK. Structured content is `impact.schema.json`; each impacted
|
|
2377
2392
|
document includes a deterministic evidence path over typed or backlink
|
|
@@ -260,13 +260,27 @@
|
|
|
260
260
|
"truncation": {
|
|
261
261
|
"type": "object",
|
|
262
262
|
"additionalProperties": false,
|
|
263
|
-
"required": [
|
|
263
|
+
"required": [
|
|
264
|
+
"findingsTruncated",
|
|
265
|
+
"maxFindings",
|
|
266
|
+
"snapshotTruncated",
|
|
267
|
+
"evidenceTruncated"
|
|
268
|
+
],
|
|
264
269
|
"properties": {
|
|
265
270
|
"findingsTruncated": { "type": "boolean" },
|
|
266
271
|
"maxFindings": {
|
|
267
|
-
"
|
|
268
|
-
|
|
269
|
-
|
|
272
|
+
"oneOf": [
|
|
273
|
+
{ "type": "integer", "minimum": 1, "maximum": 100000 },
|
|
274
|
+
{ "const": "all" }
|
|
275
|
+
]
|
|
276
|
+
},
|
|
277
|
+
"snapshotTruncated": {
|
|
278
|
+
"type": "boolean",
|
|
279
|
+
"description": "The bounded audit snapshot was cut; finding totals cover the snapshot only, not the whole index"
|
|
280
|
+
},
|
|
281
|
+
"evidenceTruncated": {
|
|
282
|
+
"type": "boolean",
|
|
283
|
+
"description": "Evidence items, candidate lists, or evidence detail text were shortened"
|
|
270
284
|
}
|
|
271
285
|
}
|
|
272
286
|
},
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"type": "string",
|
|
29
29
|
"description": "Source document title"
|
|
30
30
|
},
|
|
31
|
+
"sourceCollection": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Collection of the linking document (may differ from the target's in a link workspace)"
|
|
34
|
+
},
|
|
31
35
|
"linkText": {
|
|
32
36
|
"type": "string",
|
|
33
37
|
"description": "Link display text"
|
|
@@ -39,6 +39,19 @@
|
|
|
39
39
|
"languageHint": {
|
|
40
40
|
"type": "string",
|
|
41
41
|
"description": "BCP-47 language hint for the collection"
|
|
42
|
+
},
|
|
43
|
+
"workspaceRoot": {
|
|
44
|
+
"description": "Configured link workspace: an absolute path joins the collection to that workspace root; false keeps links inside the collection. Absent means auto-detect. Same-host callers only: omitted for a remote REST caller.",
|
|
45
|
+
"oneOf": [{ "type": "string" }, { "const": false }]
|
|
46
|
+
},
|
|
47
|
+
"effectiveWorkspaceRoot": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"description": "CLI list only: effective link workspace root (nearest .obsidian folder, or the configured root). Absent when links stay inside the collection."
|
|
50
|
+
},
|
|
51
|
+
"workspaceSource": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"enum": ["none", "detected", "configured", "disabled", "unavailable"],
|
|
54
|
+
"description": "CLI list only: how the link workspace was set"
|
|
42
55
|
}
|
|
43
56
|
}
|
|
44
57
|
}
|
|
@@ -78,6 +78,10 @@
|
|
|
78
78
|
"type": "string",
|
|
79
79
|
"description": "URI of resolved target document"
|
|
80
80
|
},
|
|
81
|
+
"resolvedCollection": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"description": "Collection of the resolved target (may differ from the source's in a link workspace)"
|
|
84
|
+
},
|
|
81
85
|
"resolvedTitle": {
|
|
82
86
|
"type": "string",
|
|
83
87
|
"description": "Title of resolved target document"
|
|
@@ -111,6 +111,21 @@
|
|
|
111
111
|
"type": "string",
|
|
112
112
|
"description": "Collection root path. Same-host callers only: omitted for a remote REST or HTTP MCP caller."
|
|
113
113
|
},
|
|
114
|
+
"workspaceRoot": {
|
|
115
|
+
"type": "string",
|
|
116
|
+
"description": "Effective link workspace root: plain wiki links resolve across every collection under it. Present only when the collection is in a workspace. Same-host callers only: omitted for a remote REST or HTTP MCP caller."
|
|
117
|
+
},
|
|
118
|
+
"workspaceSource": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"enum": [
|
|
121
|
+
"none",
|
|
122
|
+
"detected",
|
|
123
|
+
"configured",
|
|
124
|
+
"disabled",
|
|
125
|
+
"unavailable"
|
|
126
|
+
],
|
|
127
|
+
"description": "How the link workspace was set: detected (nearest .obsidian folder), configured (workspaceRoot setting), disabled (workspaceRoot: false), unavailable (root could not be inspected; links stay collection-scoped), none (no workspace)"
|
|
128
|
+
},
|
|
114
129
|
"documentCount": {
|
|
115
130
|
"type": "integer",
|
|
116
131
|
"description": "Number of active documents",
|
|
@@ -14,8 +14,11 @@ import type { WorkspaceAuditProgress } from "../../core/audit-workspace";
|
|
|
14
14
|
import { getIndexDbPath } from "../../app/constants";
|
|
15
15
|
import { loadConfig } from "../../config";
|
|
16
16
|
import {
|
|
17
|
+
AUDIT_MAX_FINDINGS_RANGE_MESSAGE,
|
|
17
18
|
auditExitCode,
|
|
18
19
|
AUDIT_CATEGORIES,
|
|
20
|
+
parseAuditMaxFindingsInput,
|
|
21
|
+
resolveAuditMaxFindings,
|
|
19
22
|
serializeAuditReportCanonical,
|
|
20
23
|
} from "../../core/audit";
|
|
21
24
|
import { runWorkspaceAudit } from "../../core/audit-workspace";
|
|
@@ -31,7 +34,8 @@ export interface AuditCommandOptions {
|
|
|
31
34
|
collections?: string[];
|
|
32
35
|
paths?: string[];
|
|
33
36
|
tags?: string[];
|
|
34
|
-
|
|
37
|
+
/** Positive integer, `all`, or the raw CLI string for either. */
|
|
38
|
+
maxFindings?: number | string;
|
|
35
39
|
maxAgeDays?: number;
|
|
36
40
|
orphanRoots?: string[];
|
|
37
41
|
orphanIgnorePrefixes?: string[];
|
|
@@ -80,11 +84,18 @@ export const audit = async (
|
|
|
80
84
|
error: "category must be links, provenance, freshness, or all",
|
|
81
85
|
};
|
|
82
86
|
}
|
|
83
|
-
|
|
87
|
+
const maxFindings =
|
|
88
|
+
typeof options.maxFindings === "string"
|
|
89
|
+
? parseAuditMaxFindingsInput(options.maxFindings)
|
|
90
|
+
: options.maxFindings;
|
|
91
|
+
if (
|
|
92
|
+
(options.maxFindings !== undefined && maxFindings === undefined) ||
|
|
93
|
+
!resolveAuditMaxFindings(maxFindings).ok
|
|
94
|
+
) {
|
|
84
95
|
return {
|
|
85
96
|
success: false,
|
|
86
97
|
invalid: true,
|
|
87
|
-
error:
|
|
98
|
+
error: AUDIT_MAX_FINDINGS_RANGE_MESSAGE,
|
|
88
99
|
};
|
|
89
100
|
}
|
|
90
101
|
if (invalidPositiveInteger(options.maxAgeDays)) {
|
|
@@ -155,7 +166,7 @@ export const audit = async (
|
|
|
155
166
|
collectionFilters: requestedCollections,
|
|
156
167
|
pathFilters: options.paths,
|
|
157
168
|
tagFilters: requestedTags,
|
|
158
|
-
maxFindings
|
|
169
|
+
maxFindings,
|
|
159
170
|
agePolicy:
|
|
160
171
|
options.maxAgeDays === undefined
|
|
161
172
|
? undefined
|
|
@@ -188,6 +199,14 @@ export const formatAuditReport = (
|
|
|
188
199
|
`Categories: ${report.scope.categories.join(", ")}`,
|
|
189
200
|
`Rules: ${report.counts.rules.total} (${report.counts.rules.fail} failed, ${report.counts.rules.unavailable} unavailable, ${report.counts.rules.inconclusive} inconclusive)`,
|
|
190
201
|
`Findings: ${report.counts.findings.total}${report.counts.findings.truncated ? ` (${report.counts.findings.returned} shown)` : ""}`,
|
|
202
|
+
...(report.truncation.snapshotTruncated
|
|
203
|
+
? [
|
|
204
|
+
"Snapshot: truncated; totals cover the bounded audit snapshot, not the whole index",
|
|
205
|
+
]
|
|
206
|
+
: []),
|
|
207
|
+
...(report.truncation.evidenceTruncated
|
|
208
|
+
? ["Evidence: some finding evidence was shortened"]
|
|
209
|
+
: []),
|
|
191
210
|
`Examined: ${report.counts.examined.documents} document/rule observations`,
|
|
192
211
|
`Duration: ${report.durationMs}ms`,
|
|
193
212
|
];
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
import type { Collection } from "../../../config";
|
|
6
6
|
|
|
7
7
|
import { loadConfig } from "../../../config";
|
|
8
|
+
import {
|
|
9
|
+
detectCollectionWorkspace,
|
|
10
|
+
formatLinkWorkspace,
|
|
11
|
+
} from "../../../core/link-workspace";
|
|
8
12
|
import { bold, cyan, dim } from "../../colors";
|
|
9
13
|
import { CliError } from "../../errors";
|
|
10
14
|
|
|
@@ -23,7 +27,30 @@ interface ListOptions {
|
|
|
23
27
|
md?: boolean;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
type ListedCollection = Collection & {
|
|
31
|
+
/** Effective link workspace root (detected or configured). */
|
|
32
|
+
effectiveWorkspaceRoot?: string;
|
|
33
|
+
workspaceSource: ReturnType<typeof detectCollectionWorkspace>["source"];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Resolve each collection's effective link workspace from the filesystem. */
|
|
37
|
+
const withLinkWorkspaces = (collections: Collection[]): ListedCollection[] =>
|
|
38
|
+
collections.map((collection) => {
|
|
39
|
+
const workspace = detectCollectionWorkspace(collection);
|
|
40
|
+
return {
|
|
41
|
+
...collection,
|
|
42
|
+
...(workspace.root ? { effectiveWorkspaceRoot: workspace.root } : {}),
|
|
43
|
+
workspaceSource: workspace.source,
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const linkWorkspaceLine = (collection: ListedCollection): string | null =>
|
|
48
|
+
formatLinkWorkspace({
|
|
49
|
+
workspaceRoot: collection.effectiveWorkspaceRoot,
|
|
50
|
+
workspaceSource: collection.workspaceSource,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
function formatMarkdown(collections: ListedCollection[]): string {
|
|
27
54
|
const lines: string[] = ["# Collections", ""];
|
|
28
55
|
if (collections.length === 0) {
|
|
29
56
|
lines.push("No collections configured.");
|
|
@@ -43,12 +70,14 @@ function formatMarkdown(collections: Collection[]): string {
|
|
|
43
70
|
if (coll.updateCmd) {
|
|
44
71
|
lines.push(`- **Update Command:** \`${coll.updateCmd}\``);
|
|
45
72
|
}
|
|
73
|
+
const workspace = linkWorkspaceLine(coll);
|
|
74
|
+
if (workspace) lines.push(`- **Link workspace:** ${workspace}`);
|
|
46
75
|
lines.push("");
|
|
47
76
|
}
|
|
48
77
|
return lines.join("\n");
|
|
49
78
|
}
|
|
50
79
|
|
|
51
|
-
function formatTerminal(collections:
|
|
80
|
+
function formatTerminal(collections: ListedCollection[]): string {
|
|
52
81
|
if (collections.length === 0) {
|
|
53
82
|
return dim("No collections configured.");
|
|
54
83
|
}
|
|
@@ -78,6 +107,10 @@ function formatTerminal(collections: Collection[]): string {
|
|
|
78
107
|
if (updateCmd) {
|
|
79
108
|
lines.push(` ${dim("Update:")} ${updateCmd}`);
|
|
80
109
|
}
|
|
110
|
+
const workspace = linkWorkspaceLine(coll);
|
|
111
|
+
if (workspace) {
|
|
112
|
+
lines.push(` ${dim("Links:")} workspace ${sanitize(workspace)}`);
|
|
113
|
+
}
|
|
81
114
|
lines.push("");
|
|
82
115
|
}
|
|
83
116
|
return lines.join("\n");
|
|
@@ -96,13 +129,14 @@ export async function collectionList(options: ListOptions): Promise<void> {
|
|
|
96
129
|
const config = result.value;
|
|
97
130
|
|
|
98
131
|
// Format and output
|
|
132
|
+
const collections = withLinkWorkspaces(config.collections);
|
|
99
133
|
let output: string;
|
|
100
134
|
if (options.json) {
|
|
101
|
-
output = JSON.stringify(
|
|
135
|
+
output = JSON.stringify(collections, null, 2);
|
|
102
136
|
} else if (options.md) {
|
|
103
|
-
output = formatMarkdown(
|
|
137
|
+
output = formatMarkdown(collections);
|
|
104
138
|
} else {
|
|
105
|
-
output = formatTerminal(
|
|
139
|
+
output = formatTerminal(collections);
|
|
106
140
|
}
|
|
107
141
|
|
|
108
142
|
process.stdout.write(`${output}\n`);
|
|
@@ -818,7 +818,7 @@ function getActiveChunkCount(
|
|
|
818
818
|
`
|
|
819
819
|
SELECT COUNT(*) as count FROM content_chunks c
|
|
820
820
|
WHERE EXISTS (
|
|
821
|
-
SELECT 1 FROM documents d
|
|
821
|
+
SELECT 1 FROM documents d INDEXED BY idx_documents_mirror_hash
|
|
822
822
|
WHERE d.mirror_hash = c.mirror_hash AND d.active = 1${collectionClause}
|
|
823
823
|
)
|
|
824
824
|
`
|
|
@@ -851,7 +851,7 @@ function getActiveChunks(
|
|
|
851
851
|
'force' as reason
|
|
852
852
|
FROM content_chunks c
|
|
853
853
|
WHERE EXISTS (
|
|
854
|
-
SELECT 1 FROM documents d
|
|
854
|
+
SELECT 1 FROM documents d INDEXED BY idx_documents_mirror_hash
|
|
855
855
|
WHERE d.mirror_hash = c.mirror_hash AND d.active = 1${collectionClause}
|
|
856
856
|
)
|
|
857
857
|
AND (c.mirror_hash > ? OR (c.mirror_hash = ? AND c.seq > ?))
|
|
@@ -864,7 +864,7 @@ function getActiveChunks(
|
|
|
864
864
|
'force' as reason
|
|
865
865
|
FROM content_chunks c
|
|
866
866
|
WHERE EXISTS (
|
|
867
|
-
SELECT 1 FROM documents d
|
|
867
|
+
SELECT 1 FROM documents d INDEXED BY idx_documents_mirror_hash
|
|
868
868
|
WHERE d.mirror_hash = c.mirror_hash AND d.active = 1${collectionClause}
|
|
869
869
|
)
|
|
870
870
|
ORDER BY c.mirror_hash, c.seq
|