daftari 1.13.1 → 1.15.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/CHANGELOG.md +92 -0
- package/README.md +1 -0
- package/dist/curation/lint.d.ts +26 -1
- package/dist/curation/lint.d.ts.map +1 -1
- package/dist/curation/lint.js +129 -74
- package/dist/curation/lint.js.map +1 -1
- package/dist/curation/tension-blast.d.ts +37 -0
- package/dist/curation/tension-blast.d.ts.map +1 -0
- package/dist/curation/tension-blast.js +223 -0
- package/dist/curation/tension-blast.js.map +1 -0
- package/dist/curation/tension-clusters.d.ts +18 -0
- package/dist/curation/tension-clusters.d.ts.map +1 -0
- package/dist/curation/tension-clusters.js +157 -0
- package/dist/curation/tension-clusters.js.map +1 -0
- package/dist/curation/tension.d.ts +25 -1
- package/dist/curation/tension.d.ts.map +1 -1
- package/dist/curation/tension.js +258 -15
- package/dist/curation/tension.js.map +1 -1
- package/dist/curation/vault-docs.d.ts +14 -0
- package/dist/curation/vault-docs.d.ts.map +1 -0
- package/dist/curation/vault-docs.js +90 -0
- package/dist/curation/vault-docs.js.map +1 -0
- package/dist/tools/curation.d.ts +7 -1
- package/dist/tools/curation.d.ts.map +1 -1
- package/dist/tools/curation.js +238 -10
- package/dist/tools/curation.js.map +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +8 -4
- package/dist/tools/search.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,98 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.15.0] - 2026-05-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Blast radius of stale tensions** (Step 5 of the Tension Graph plan,
|
|
15
|
+
cross-feature integration). `vault_lint`'s tension health surface now
|
|
16
|
+
reports `blastRadiusOfStaleTensions`: the cardinality of the
|
|
17
|
+
deduplicated `primary_blast` set (sources channel only — the same
|
|
18
|
+
primary set `vault_tension_blast` returns) over the union of contested
|
|
19
|
+
docs from every entry where `resolved: false` AND
|
|
20
|
+
`agingTier === "stale"`. Renders as "Blast radius of stale tensions: N
|
|
21
|
+
downstream documents". When there are no stale unresolved tensions the
|
|
22
|
+
metric is 0; the line always renders for consistency with the rest of
|
|
23
|
+
the tension health section. Reuses `computeBlast` from
|
|
24
|
+
`tension-blast.ts` — advisory link edges still participate in BFS
|
|
25
|
+
traversal, but the published metric stays disciplined to the primary
|
|
26
|
+
channel.
|
|
27
|
+
|
|
28
|
+
- **Tension blast radius** (Phase 3 of the Tension Graph plan). New
|
|
29
|
+
`vault_tension_blast` tool computes the transitive closure of
|
|
30
|
+
downstream documents that cite or link a contested document — or the
|
|
31
|
+
union over a contested cluster. Accepts exactly one of `document` or
|
|
32
|
+
`cluster_id`. Two confidence channels: `primary_blast` (via `sources`
|
|
33
|
+
frontmatter) is authoritative; `advisory_blast` (via in-vault markdown
|
|
34
|
+
links) is suggestive. `superseded_by` is not a blast edge — the doc
|
|
35
|
+
that supersedes a contested doc is the replacement, not an inheritor.
|
|
36
|
+
|
|
37
|
+
- **Tension clusters** (Phase 2 of the Tension Graph plan). New
|
|
38
|
+
`vault_tension_clusters` tool computes connected components of the
|
|
39
|
+
tension graph over unresolved, non-accepted tensions. Cluster IDs are
|
|
40
|
+
content-addressed (`cluster:` + first 8 hex chars of sha256 of
|
|
41
|
+
canonical-sorted member paths) — stable across runs for unchanged
|
|
42
|
+
membership; a different ID encodes a different membership. `vault_lint`
|
|
43
|
+
reports cluster count, max size, and flags clusters that are large
|
|
44
|
+
(>5 docs, smell) or aged (oldest tension >90 days, tech debt).
|
|
45
|
+
|
|
46
|
+
- **Tension aging tiers** (Phase 4 of the Tension Graph plan). Tensions
|
|
47
|
+
in the tension log now report aging tiers (Fresh 0–30d / Aging 31–90d
|
|
48
|
+
/ Stale 90+d) in `vault_lint`, with kind-specific lint copy at the
|
|
49
|
+
stale tier. Unspecified tensions and tensions resolved with kind
|
|
50
|
+
`accepted` are excluded from the aging pipeline — the former because
|
|
51
|
+
they predate classification, the latter because explicitly accepted
|
|
52
|
+
persistent disagreements are stable epistemic features rather than
|
|
53
|
+
debt.
|
|
54
|
+
|
|
55
|
+
## [1.14.0] - 2026-05-31
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- **Multi-vault MCP router** (`packages/router/`, published as
|
|
60
|
+
`daftari-router` v0.1.0). One MCP connection that spans N daftari
|
|
61
|
+
vaults: read/write tools dispatch to the named vault; search, status,
|
|
62
|
+
lint, themes, index, and reindex fan out across every child and merge
|
|
63
|
+
results. Vault selection via explicit `vault:` arg or vault-prefixed
|
|
64
|
+
paths (e.g. `devops:runbooks/k8s.md`). Catalog seeded from the first
|
|
65
|
+
child; heterogeneous tool surfaces are warned to stderr. Phase 1 — no
|
|
66
|
+
HTTP transport, no auth, no cross-vault lint, no score normalization
|
|
67
|
+
across heterogeneous embedding models. See
|
|
68
|
+
[docs/multi-vault-howto.md](docs/multi-vault-howto.md) for the
|
|
69
|
+
task-oriented walkthrough and
|
|
70
|
+
[packages/router/README.md](packages/router/README.md) for the
|
|
71
|
+
reference.
|
|
72
|
+
|
|
73
|
+
- **Tension taxonomy and resolution** (Phase 1 of the Tension Graph plan).
|
|
74
|
+
Tensions now carry a `kind` (temporal | factual | interpretive |
|
|
75
|
+
unspecified). New tool `vault_tension_resolve` records how a tension was
|
|
76
|
+
closed (superseded | corrected | accepted | invalid) with optional
|
|
77
|
+
rationale and references. `vault_lint` reports tension counts by kind
|
|
78
|
+
and resolution kind, and surfaces a separate "stable acknowledged"
|
|
79
|
+
count for explicitly accepted persistent disagreements. Legacy entries
|
|
80
|
+
without a `kind` field read as `unspecified` and produce no warnings.
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
|
|
84
|
+
- **`vault_reindex` coalesces with an in-flight indexing pass** instead
|
|
85
|
+
of returning a busy error. When a reindex is already running (e.g. the
|
|
86
|
+
startup-time background pass kicked off when daftari boots a fresh
|
|
87
|
+
vault), `vault_reindex` now awaits it and then runs the caller's
|
|
88
|
+
requested reindex against a hot cache. Previously, an agent that
|
|
89
|
+
asked for a reindex during that startup window got a "still indexing"
|
|
90
|
+
refusal — a footgun the router stress-tested into a real test failure.
|
|
91
|
+
|
|
92
|
+
### Fixed
|
|
93
|
+
|
|
94
|
+
- Test helper `temp-vault.ts` `cpSync` filter now skips `.git/` as well
|
|
95
|
+
as `.daftari/`. The sample-vault fixture is itself a real git repo;
|
|
96
|
+
without this, the fixture's `.git` was being copied into every temp
|
|
97
|
+
vault, making `isGitRepo(vault)` return true for what was supposed to
|
|
98
|
+
be a fresh directory. Three pre-existing test-helper failures in
|
|
99
|
+
`test/utils/git.test.ts` and `test/tools/write.test.ts` are fixed in
|
|
100
|
+
passing.
|
|
101
|
+
|
|
10
102
|
## [1.13.1] - 2026-05-30
|
|
11
103
|
|
|
12
104
|
### Changed
|
package/README.md
CHANGED
|
@@ -346,6 +346,7 @@ Design tenets: functions and types, no classes; tool handlers return
|
|
|
346
346
|
Python package that exposes the 14 daftari tools as LangChain `BaseTool`s
|
|
347
347
|
for use with LangGraph / `create_react_agent`. Sync + async, schemas pulled
|
|
348
348
|
live from `tools/list`.
|
|
349
|
+
- [`packages/router`](packages/router) — multi-vault MCP router that fans out across N Daftari vaults
|
|
349
350
|
|
|
350
351
|
## Privacy
|
|
351
352
|
|
package/dist/curation/lint.d.ts
CHANGED
|
@@ -1,20 +1,45 @@
|
|
|
1
1
|
import { type Result } from "../frontmatter/types.js";
|
|
2
|
+
import { type ResolutionKind, type TensionKind } from "./tension.js";
|
|
2
3
|
export declare const LINT_CHECKS: readonly ["staleFiles", "orphanFiles", "oldDrafts", "stagnantLowConfidence", "deprecatedStillLinked", "unansweredQuestions"];
|
|
3
4
|
export type LintCheckName = (typeof LINT_CHECKS)[number];
|
|
4
5
|
export interface LintFinding {
|
|
5
6
|
path: string;
|
|
6
7
|
detail: string;
|
|
7
8
|
}
|
|
9
|
+
export interface TensionAging {
|
|
10
|
+
fresh: number;
|
|
11
|
+
aging: number;
|
|
12
|
+
stale: number;
|
|
13
|
+
staleByKind: Record<TensionKind, number>;
|
|
14
|
+
staleMessages: Partial<Record<Exclude<TensionKind, "unspecified">, string>>;
|
|
15
|
+
}
|
|
16
|
+
export interface TensionClustersHealth {
|
|
17
|
+
count: number;
|
|
18
|
+
maxSize: number;
|
|
19
|
+
large: number;
|
|
20
|
+
aged: number;
|
|
21
|
+
}
|
|
22
|
+
export interface TensionHealth {
|
|
23
|
+
total: number;
|
|
24
|
+
byKind: Record<TensionKind, number>;
|
|
25
|
+
resolvedLifetime: number;
|
|
26
|
+
byResolutionKind: Record<ResolutionKind, number>;
|
|
27
|
+
stableAcknowledged: number;
|
|
28
|
+
unspecifiedLegacy: number;
|
|
29
|
+
aging: TensionAging;
|
|
30
|
+
clusters: TensionClustersHealth;
|
|
31
|
+
blastRadiusOfStaleTensions: number;
|
|
32
|
+
}
|
|
8
33
|
export interface LintReport {
|
|
9
34
|
generatedAt: string;
|
|
10
35
|
checks: Record<LintCheckName, LintFinding[]>;
|
|
11
36
|
totalFindings: number;
|
|
37
|
+
tensionHealth: TensionHealth;
|
|
12
38
|
}
|
|
13
39
|
export interface LintOptions {
|
|
14
40
|
now?: Date;
|
|
15
41
|
draftMaxDays?: number;
|
|
16
42
|
lowConfidenceMaxDays?: number;
|
|
17
43
|
}
|
|
18
|
-
export declare function extractLinks(content: string): string[];
|
|
19
44
|
export declare function runLint(vaultRoot: string, opts?: LintOptions): Promise<Result<LintReport, Error>>;
|
|
20
45
|
//# sourceMappingURL=lint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/curation/lint.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/curation/lint.ts"],"names":[],"mappings":"AAOA,OAAO,EAAM,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,EAIL,KAAK,cAAc,EAGnB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAWtB,eAAO,MAAM,WAAW,8HAOd,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAyBD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzC,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7E;AAOD,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,EAAE,qBAAqB,CAAC;IAMhC,0BAA0B,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AA8BD,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAqHpC"}
|
package/dist/curation/lint.js
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
// runs six checks. It only ever *reports*: no file is edited, no status is
|
|
5
5
|
// changed, nothing is auto-fixed. The output is a structured report grouped by
|
|
6
6
|
// check, for a human (or an agent acting on a human's behalf) to triage.
|
|
7
|
-
import { posix } from "node:path";
|
|
8
|
-
import { parseDocument } from "../frontmatter/parser.js";
|
|
9
7
|
import { ok } from "../frontmatter/types.js";
|
|
10
|
-
import { listFiles, readFile, resolveVaultPath } from "../storage/local.js";
|
|
11
8
|
import { DRAFT_MAX_DAYS, LOW_CONFIDENCE_MAX_DAYS } from "./decay.js";
|
|
12
9
|
import { ageInDays, computeStaleness } from "./staleness.js";
|
|
10
|
+
import { agingTier, listTensions, RESOLUTION_KINDS, STALE_TIER_LINT_COPY, TENSION_KINDS, } from "./tension.js";
|
|
11
|
+
import { buildReverseLinkMap, buildReverseSourceMap, computeBlast } from "./tension-blast.js";
|
|
12
|
+
import { computeTensionClusters } from "./tension-clusters.js";
|
|
13
|
+
import { buildPathIndexes, extractLinks, loadDocuments, resolveLink, } from "./vault-docs.js";
|
|
13
14
|
export const LINT_CHECKS = [
|
|
14
15
|
"staleFiles",
|
|
15
16
|
"orphanFiles",
|
|
@@ -18,45 +19,6 @@ export const LINT_CHECKS = [
|
|
|
18
19
|
"deprecatedStillLinked",
|
|
19
20
|
"unansweredQuestions",
|
|
20
21
|
];
|
|
21
|
-
// --- link extraction ------------------------------------------------------
|
|
22
|
-
// Pulls every internal link target out of a markdown body: both [[wikilinks]]
|
|
23
|
-
// and [text](target) markdown links. External URLs and anchors are dropped.
|
|
24
|
-
export function extractLinks(content) {
|
|
25
|
-
const targets = [];
|
|
26
|
-
for (const m of content.matchAll(/\[\[([^\]]+)\]\]/g)) {
|
|
27
|
-
// A wikilink may carry a |display alias and/or a #heading anchor.
|
|
28
|
-
const raw = m[1].split("|")[0]?.split("#")[0]?.trim();
|
|
29
|
-
if (raw)
|
|
30
|
-
targets.push(raw);
|
|
31
|
-
}
|
|
32
|
-
for (const m of content.matchAll(/\[[^\]]*\]\(([^)\s]+)\)/g)) {
|
|
33
|
-
const raw = m[1].split("#")[0]?.trim();
|
|
34
|
-
if (!raw)
|
|
35
|
-
continue;
|
|
36
|
-
if (/^(https?:|mailto:|#)/i.test(raw))
|
|
37
|
-
continue;
|
|
38
|
-
targets.push(raw);
|
|
39
|
-
}
|
|
40
|
-
return targets;
|
|
41
|
-
}
|
|
42
|
-
// Resolves a raw link target to a vault-relative path, or null if it points
|
|
43
|
-
// nowhere. Tries, in order: the target as-is, with a .md suffix, resolved
|
|
44
|
-
// relative to the linking file's directory, then a bare basename match (the
|
|
45
|
-
// common [[note-name]] wikilink form).
|
|
46
|
-
function resolveLink(rawTarget, fromPath, byPath, byBasename) {
|
|
47
|
-
const withMd = (p) => (p.endsWith(".md") ? p : `${p}.md`);
|
|
48
|
-
if (byPath.has(rawTarget))
|
|
49
|
-
return rawTarget;
|
|
50
|
-
if (byPath.has(withMd(rawTarget)))
|
|
51
|
-
return withMd(rawTarget);
|
|
52
|
-
const relual = posix.normalize(posix.join(posix.dirname(fromPath), rawTarget));
|
|
53
|
-
if (byPath.has(relual))
|
|
54
|
-
return relual;
|
|
55
|
-
if (byPath.has(withMd(relual)))
|
|
56
|
-
return withMd(relual);
|
|
57
|
-
const base = posix.basename(rawTarget).replace(/\.md$/, "");
|
|
58
|
-
return byBasename.get(base) ?? null;
|
|
59
|
-
}
|
|
60
22
|
// --- question matching ----------------------------------------------------
|
|
61
23
|
// Normalizes a question for cross-document matching: trimmed, lower-cased,
|
|
62
24
|
// internal whitespace collapsed. Exact (normalized) equality is the matching
|
|
@@ -65,39 +27,9 @@ function normalizeQuestion(q) {
|
|
|
65
27
|
return q.trim().toLowerCase().replace(/\s+/g, " ");
|
|
66
28
|
}
|
|
67
29
|
// --- check orchestration --------------------------------------------------
|
|
68
|
-
async function loadDocuments(vaultRoot) {
|
|
69
|
-
const list = await listFiles(vaultRoot);
|
|
70
|
-
if (!list.ok)
|
|
71
|
-
return list;
|
|
72
|
-
const docs = [];
|
|
73
|
-
for (const relPath of list.value) {
|
|
74
|
-
const resolved = resolveVaultPath(vaultRoot, relPath);
|
|
75
|
-
if (!resolved.ok)
|
|
76
|
-
continue;
|
|
77
|
-
const file = await readFile(resolved.value);
|
|
78
|
-
if (!file.ok)
|
|
79
|
-
continue;
|
|
80
|
-
const parsed = parseDocument(file.value);
|
|
81
|
-
if (!parsed.ok)
|
|
82
|
-
continue;
|
|
83
|
-
docs.push({
|
|
84
|
-
path: relPath,
|
|
85
|
-
frontmatter: parsed.value.frontmatter,
|
|
86
|
-
content: parsed.value.content,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
return ok(docs);
|
|
90
|
-
}
|
|
91
30
|
// Maps each document to the set of documents that link to it.
|
|
92
31
|
function buildInboundMap(docs) {
|
|
93
|
-
const byPath =
|
|
94
|
-
const byBasename = new Map();
|
|
95
|
-
for (const d of docs) {
|
|
96
|
-
const base = posix.basename(d.path).replace(/\.md$/, "");
|
|
97
|
-
// First write wins, so a basename collision resolves deterministically.
|
|
98
|
-
if (!byBasename.has(base))
|
|
99
|
-
byBasename.set(base, d.path);
|
|
100
|
-
}
|
|
32
|
+
const { byPath, byBasename } = buildPathIndexes(docs);
|
|
101
33
|
const inbound = new Map();
|
|
102
34
|
for (const d of docs) {
|
|
103
35
|
for (const raw of extractLinks(d.content)) {
|
|
@@ -205,6 +137,129 @@ export async function runLint(vaultRoot, opts = {}) {
|
|
|
205
137
|
}
|
|
206
138
|
}
|
|
207
139
|
const totalFindings = LINT_CHECKS.reduce((n, name) => n + checks[name].length, 0);
|
|
208
|
-
|
|
140
|
+
const tensionHealth = await computeTensionHealth(vaultRoot, docs, now);
|
|
141
|
+
if (!tensionHealth.ok)
|
|
142
|
+
return tensionHealth;
|
|
143
|
+
return ok({
|
|
144
|
+
generatedAt: now.toISOString(),
|
|
145
|
+
checks,
|
|
146
|
+
totalFindings,
|
|
147
|
+
tensionHealth: tensionHealth.value,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// Aggregates the tension log into the Phase 1 health summary plus the Phase 4
|
|
151
|
+
// aging breakdown. A missing log is not an error — every counter is zero.
|
|
152
|
+
//
|
|
153
|
+
// Aging scope: tiers are counted over the active surface only. An entry
|
|
154
|
+
// contributes to fresh / aging / stale iff it is unresolved AND `agingTier`
|
|
155
|
+
// returns a non-null tier (which already excludes `unspecified`). Resolved
|
|
156
|
+
// entries — including `resolution.kind: accepted` — do not appear in any
|
|
157
|
+
// aging tier; they show up in the Phase 1 stable-acknowledged and resolved
|
|
158
|
+
// totals instead.
|
|
159
|
+
async function computeTensionHealth(vaultRoot, docs, now) {
|
|
160
|
+
const tensions = await listTensions(vaultRoot);
|
|
161
|
+
if (!tensions.ok)
|
|
162
|
+
return tensions;
|
|
163
|
+
const byKind = Object.fromEntries(TENSION_KINDS.map((k) => [k, 0]));
|
|
164
|
+
const byResolutionKind = Object.fromEntries(RESOLUTION_KINDS.map((k) => [k, 0]));
|
|
165
|
+
const staleByKind = Object.fromEntries(TENSION_KINDS.map((k) => [k, 0]));
|
|
166
|
+
let total = 0;
|
|
167
|
+
let resolvedLifetime = 0;
|
|
168
|
+
let stableAcknowledged = 0;
|
|
169
|
+
let unspecifiedLegacy = 0;
|
|
170
|
+
let fresh = 0;
|
|
171
|
+
let aging = 0;
|
|
172
|
+
let stale = 0;
|
|
173
|
+
for (const t of tensions.value) {
|
|
174
|
+
total += 1;
|
|
175
|
+
byKind[t.kind] += 1;
|
|
176
|
+
if (t.kind === "unspecified")
|
|
177
|
+
unspecifiedLegacy += 1;
|
|
178
|
+
if (t.resolution) {
|
|
179
|
+
resolvedLifetime += 1;
|
|
180
|
+
byResolutionKind[t.resolution.kind] += 1;
|
|
181
|
+
if (t.resolution.kind === "accepted")
|
|
182
|
+
stableAcknowledged += 1;
|
|
183
|
+
}
|
|
184
|
+
if (t.resolved)
|
|
185
|
+
continue;
|
|
186
|
+
const tier = agingTier(t, now);
|
|
187
|
+
if (tier === "fresh")
|
|
188
|
+
fresh += 1;
|
|
189
|
+
else if (tier === "aging")
|
|
190
|
+
aging += 1;
|
|
191
|
+
else if (tier === "stale") {
|
|
192
|
+
stale += 1;
|
|
193
|
+
staleByKind[t.kind] += 1;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Render kind-specific stale-tier copy only for kinds with a nonzero count.
|
|
197
|
+
// `unspecified` never produces a message even if the count somehow appears
|
|
198
|
+
// (it can't, since unspecified entries get tier null — defense in depth).
|
|
199
|
+
const staleMessages = {};
|
|
200
|
+
for (const kind of ["temporal", "factual", "interpretive"]) {
|
|
201
|
+
if (staleByKind[kind] > 0) {
|
|
202
|
+
staleMessages[kind] = STALE_TIER_LINT_COPY[kind];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Cluster surface (Phase 2). computeTensionClusters applies the same scope
|
|
206
|
+
// filter the cluster tool does — unresolved AND non-accepted — so the lint
|
|
207
|
+
// metrics line up exactly with what `vault_tension_clusters` reports.
|
|
208
|
+
const clusterResult = computeTensionClusters(tensions.value, now);
|
|
209
|
+
let maxSize = 0;
|
|
210
|
+
let large = 0;
|
|
211
|
+
let aged = 0;
|
|
212
|
+
for (const c of clusterResult.clusters) {
|
|
213
|
+
if (c.size > maxSize)
|
|
214
|
+
maxSize = c.size;
|
|
215
|
+
if (c.size > 5)
|
|
216
|
+
large += 1;
|
|
217
|
+
if (c.oldest_tension_age_days > 90)
|
|
218
|
+
aged += 1;
|
|
219
|
+
}
|
|
220
|
+
const clusters = {
|
|
221
|
+
count: clusterResult.cluster_count,
|
|
222
|
+
maxSize,
|
|
223
|
+
large,
|
|
224
|
+
aged,
|
|
225
|
+
};
|
|
226
|
+
// Step 5 of the tension graph plan (2026-05-31). Collect every contested
|
|
227
|
+
// doc from every entry where `resolved: false` AND `agingTier === "stale"`,
|
|
228
|
+
// then reuse computeBlast to walk the dependency graph from that union as
|
|
229
|
+
// seeds. We report the count of the `primary_blast` channel — the same
|
|
230
|
+
// sources-only primary set that vault_tension_blast returns. Advisory link
|
|
231
|
+
// edges still participate in BFS traversal (so a doc reached via a link
|
|
232
|
+
// edge can still gain `source` classification from a separate incoming
|
|
233
|
+
// source edge), but the published metric is the primary count only — the
|
|
234
|
+
// top-level lint metric stays disciplined against advisory inflation.
|
|
235
|
+
const staleSeeds = new Set();
|
|
236
|
+
for (const t of tensions.value) {
|
|
237
|
+
if (t.resolved)
|
|
238
|
+
continue;
|
|
239
|
+
if (agingTier(t, now) !== "stale")
|
|
240
|
+
continue;
|
|
241
|
+
if (t.sourceA)
|
|
242
|
+
staleSeeds.add(t.sourceA);
|
|
243
|
+
if (t.sourceB)
|
|
244
|
+
staleSeeds.add(t.sourceB);
|
|
245
|
+
}
|
|
246
|
+
const reverseSource = buildReverseSourceMap(docs);
|
|
247
|
+
const reverseLink = buildReverseLinkMap(docs);
|
|
248
|
+
const blast = computeBlast({
|
|
249
|
+
seeds: [...staleSeeds],
|
|
250
|
+
reverseSource,
|
|
251
|
+
reverseLink,
|
|
252
|
+
});
|
|
253
|
+
return ok({
|
|
254
|
+
total,
|
|
255
|
+
byKind,
|
|
256
|
+
resolvedLifetime,
|
|
257
|
+
byResolutionKind,
|
|
258
|
+
stableAcknowledged,
|
|
259
|
+
unspecifiedLegacy,
|
|
260
|
+
aging: { fresh, aging, stale, staleByKind, staleMessages },
|
|
261
|
+
clusters,
|
|
262
|
+
blastRadiusOfStaleTensions: blast.primary_blast,
|
|
263
|
+
});
|
|
209
264
|
}
|
|
210
265
|
//# sourceMappingURL=lint.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/curation/lint.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,+EAA+E;AAC/E,yEAAyE;AAEzE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/curation/lint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type Result } from "../frontmatter/types.js";
|
|
2
|
+
import { type LoadedDoc } from "./vault-docs.js";
|
|
3
|
+
export type BlastDependencyType = "source" | "link";
|
|
4
|
+
export interface BlastDownstreamEntry {
|
|
5
|
+
path: string;
|
|
6
|
+
dependency_type: BlastDependencyType;
|
|
7
|
+
distance: number;
|
|
8
|
+
}
|
|
9
|
+
export interface TensionBlastResult {
|
|
10
|
+
contested_document: string | null;
|
|
11
|
+
cluster_id: string | null;
|
|
12
|
+
cluster_documents: string[];
|
|
13
|
+
downstream: BlastDownstreamEntry[];
|
|
14
|
+
primary_blast: number;
|
|
15
|
+
advisory_blast: number;
|
|
16
|
+
max_depth: number;
|
|
17
|
+
}
|
|
18
|
+
export interface TensionBlastInput {
|
|
19
|
+
document?: string;
|
|
20
|
+
cluster_id?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function buildReverseSourceMap(docs: LoadedDoc[]): Map<string, Set<string>>;
|
|
23
|
+
export declare function buildReverseLinkMap(docs: LoadedDoc[]): Map<string, Set<string>>;
|
|
24
|
+
export interface ComputeBlastArgs {
|
|
25
|
+
seeds: string[];
|
|
26
|
+
reverseSource: Map<string, Set<string>>;
|
|
27
|
+
reverseLink: Map<string, Set<string>>;
|
|
28
|
+
}
|
|
29
|
+
export interface ComputeBlastOutput {
|
|
30
|
+
downstream: BlastDownstreamEntry[];
|
|
31
|
+
primary_blast: number;
|
|
32
|
+
advisory_blast: number;
|
|
33
|
+
max_depth: number;
|
|
34
|
+
}
|
|
35
|
+
export declare function computeBlast(args: ComputeBlastArgs): ComputeBlastOutput;
|
|
36
|
+
export declare function computeTensionBlast(vaultRoot: string, input: TensionBlastInput): Promise<Result<TensionBlastResult, Error>>;
|
|
37
|
+
//# sourceMappingURL=tension-blast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tension-blast.d.ts","sourceRoot":"","sources":["../../src/curation/tension-blast.ts"],"names":[],"mappings":"AAuCA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAGL,KAAK,SAAS,EAGf,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,mBAAmB,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAQD,MAAM,WAAW,kBAAkB;IACjC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAYjF;AAKD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAY/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,oBAAoB,EAAE,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,CA8DvE;AAKD,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAoE5C"}
|