daftari 1.28.0 → 1.30.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 +197 -0
- package/README.md +167 -28
- package/dist/asof/git-read.d.ts +17 -0
- package/dist/asof/git-read.d.ts.map +1 -0
- package/dist/asof/git-read.js +163 -0
- package/dist/asof/git-read.js.map +1 -0
- package/dist/asof/index.d.ts +2 -0
- package/dist/asof/index.d.ts.map +1 -0
- package/dist/asof/index.js +151 -0
- package/dist/asof/index.js.map +1 -0
- package/dist/asof/report.d.ts +11 -0
- package/dist/asof/report.d.ts.map +1 -0
- package/dist/asof/report.js +119 -0
- package/dist/asof/report.js.map +1 -0
- package/dist/asof/snapshot.d.ts +72 -0
- package/dist/asof/snapshot.d.ts.map +1 -0
- package/dist/asof/snapshot.js +207 -0
- package/dist/asof/snapshot.js.map +1 -0
- package/dist/backfill/apply.js +2 -2
- package/dist/backfill/apply.js.map +1 -1
- package/dist/backfill/plan.js +2 -2
- package/dist/backfill/plan.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -0
- package/dist/cli.js.map +1 -1
- package/dist/consolidate/call-budget.d.ts +3 -0
- package/dist/consolidate/call-budget.d.ts.map +1 -0
- package/dist/consolidate/call-budget.js +37 -0
- package/dist/consolidate/call-budget.js.map +1 -0
- package/dist/consolidate/constants.d.ts +1 -0
- package/dist/consolidate/constants.d.ts.map +1 -1
- package/dist/consolidate/constants.js +5 -0
- package/dist/consolidate/constants.js.map +1 -1
- package/dist/consolidate/index.d.ts.map +1 -1
- package/dist/consolidate/index.js +96 -27
- package/dist/consolidate/index.js.map +1 -1
- package/dist/court/docket.d.ts +39 -0
- package/dist/court/docket.d.ts.map +1 -0
- package/dist/court/docket.js +103 -0
- package/dist/court/docket.js.map +1 -0
- package/dist/court/index.d.ts +2 -0
- package/dist/court/index.d.ts.map +1 -0
- package/dist/court/index.js +169 -0
- package/dist/court/index.js.map +1 -0
- package/dist/court/precedent.d.ts +18 -0
- package/dist/court/precedent.d.ts.map +1 -0
- package/dist/court/precedent.js +84 -0
- package/dist/court/precedent.js.map +1 -0
- package/dist/court/report.d.ts +10 -0
- package/dist/court/report.d.ts.map +1 -0
- package/dist/court/report.js +77 -0
- package/dist/court/report.js.map +1 -0
- package/dist/curation/staged-actions.d.ts.map +1 -1
- package/dist/curation/staged-actions.js +15 -6
- package/dist/curation/staged-actions.js.map +1 -1
- package/dist/curation/staleness.js +1 -1
- package/dist/curation/staleness.js.map +1 -1
- package/dist/curation/tension-access.d.ts +7 -0
- package/dist/curation/tension-access.d.ts.map +1 -0
- package/dist/curation/tension-access.js +44 -0
- package/dist/curation/tension-access.js.map +1 -0
- package/dist/curation/tension-blast.d.ts +2 -1
- package/dist/curation/tension-blast.d.ts.map +1 -1
- package/dist/curation/tension-blast.js +2 -2
- package/dist/curation/tension-blast.js.map +1 -1
- package/dist/curation/tension-clusters.d.ts +1 -1
- package/dist/curation/tension-clusters.d.ts.map +1 -1
- package/dist/curation/tension-clusters.js +5 -2
- package/dist/curation/tension-clusters.js.map +1 -1
- package/dist/curation/tension.d.ts +1 -0
- package/dist/curation/tension.d.ts.map +1 -1
- package/dist/curation/tension.js +18 -10
- package/dist/curation/tension.js.map +1 -1
- package/dist/curation/vault-docs.js +1 -1
- package/dist/curation/vault-docs.js.map +1 -1
- package/dist/eval/llm-openrouter.d.ts +9 -0
- package/dist/eval/llm-openrouter.d.ts.map +1 -0
- package/dist/eval/llm-openrouter.js +171 -0
- package/dist/eval/llm-openrouter.js.map +1 -0
- package/dist/frontmatter/parser.d.ts +1 -0
- package/dist/frontmatter/parser.d.ts.map +1 -1
- package/dist/frontmatter/parser.js +12 -0
- package/dist/frontmatter/parser.js.map +1 -1
- package/dist/frontmatter/schema.d.ts.map +1 -1
- package/dist/frontmatter/schema.js +19 -2
- package/dist/frontmatter/schema.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/search/contested.d.ts +18 -0
- package/dist/search/contested.d.ts.map +1 -0
- package/dist/search/contested.js +119 -0
- package/dist/search/contested.js.map +1 -0
- package/dist/search/hybrid.d.ts +5 -0
- package/dist/search/hybrid.d.ts.map +1 -1
- package/dist/search/hybrid.js +112 -9
- package/dist/search/hybrid.js.map +1 -1
- package/dist/search/reindex.d.ts.map +1 -1
- package/dist/search/reindex.js +16 -13
- package/dist/search/reindex.js.map +1 -1
- package/dist/search/watcher.js +2 -2
- package/dist/search/watcher.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +4 -0
- package/dist/server.js.map +1 -1
- package/dist/sleep/cycle.d.ts +59 -0
- package/dist/sleep/cycle.d.ts.map +1 -0
- package/dist/sleep/cycle.js +127 -0
- package/dist/sleep/cycle.js.map +1 -0
- package/dist/sleep/index.d.ts +3 -0
- package/dist/sleep/index.d.ts.map +1 -0
- package/dist/sleep/index.js +129 -0
- package/dist/sleep/index.js.map +1 -0
- package/dist/sleep/report.d.ts +11 -0
- package/dist/sleep/report.d.ts.map +1 -0
- package/dist/sleep/report.js +87 -0
- package/dist/sleep/report.js.map +1 -0
- package/dist/storage/index-db.d.ts +2 -0
- package/dist/storage/index-db.d.ts.map +1 -1
- package/dist/storage/index-db.js +106 -19
- package/dist/storage/index-db.js.map +1 -1
- package/dist/storage/local.d.ts +6 -1
- package/dist/storage/local.d.ts.map +1 -1
- package/dist/storage/local.js +30 -4
- package/dist/storage/local.js.map +1 -1
- package/dist/tools/curation.d.ts.map +1 -1
- package/dist/tools/curation.js +60 -3
- package/dist/tools/curation.js.map +1 -1
- package/dist/tools/edges.js +2 -2
- package/dist/tools/edges.js.map +1 -1
- package/dist/tools/read.js +2 -2
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/receipt.d.ts +65 -0
- package/dist/tools/receipt.d.ts.map +1 -0
- package/dist/tools/receipt.js +248 -0
- package/dist/tools/receipt.js.map +1 -0
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +40 -8
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/staged-actions.js +1 -1
- package/dist/tools/staged-actions.js.map +1 -1
- package/dist/tools/themes.d.ts +1 -0
- package/dist/tools/themes.d.ts.map +1 -1
- package/dist/tools/themes.js +159 -45
- package/dist/tools/themes.js.map +1 -1
- package/dist/tools/witness.d.ts +9 -0
- package/dist/tools/witness.d.ts.map +1 -0
- package/dist/tools/witness.js +66 -0
- package/dist/tools/witness.js.map +1 -0
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +101 -53
- package/dist/tools/write.js.map +1 -1
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +48 -2
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +15 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/redos.d.ts +2 -0
- package/dist/utils/redos.d.ts.map +1 -0
- package/dist/utils/redos.js +101 -0
- package/dist/utils/redos.js.map +1 -0
- package/dist/utils/vault-gitignore.d.ts +1 -1
- package/dist/utils/vault-gitignore.d.ts.map +1 -1
- package/dist/utils/vault-gitignore.js +2 -0
- package/dist/utils/vault-gitignore.js.map +1 -1
- package/dist/witness/track-record.d.ts +42 -0
- package/dist/witness/track-record.d.ts.map +1 -0
- package/dist/witness/track-record.js +189 -0
- package/dist/witness/track-record.js.map +1 -0
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,203 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.30.0] - 2026-07-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`vault_receipt` — the epistemic receipt.** A new read-only MCP tool that
|
|
15
|
+
compiles, for the set of documents an answer cites, a single attachable
|
|
16
|
+
artifact: per-source status / confidence / provenance / freshness (decay),
|
|
17
|
+
the exact content-version hash, a filesystem-walked resolution of the
|
|
18
|
+
supersession chain (`resolved` / `restricted` / `dangling` / `cycle`), and
|
|
19
|
+
every unresolved tension touching the source — plus a deterministic summary
|
|
20
|
+
(`byStatus`, `openTensions`, oldest/newest `updated`, sorted
|
|
21
|
+
machine-readable flags such as `cites-stale`, `cites-contested`,
|
|
22
|
+
`cites-superseded`, `supersession-unresolved`; empty flags mean current,
|
|
23
|
+
grounded, and uncontested), the vault's git HEAD as an as-of anchor, and a
|
|
24
|
+
recomputable SHA-256 over the whole receipt. Discipline: the receipt only
|
|
25
|
+
reads (frontmatter, tension log, git); flags are deterministic derivations;
|
|
26
|
+
the optional caller-supplied `claim` rides verbatim and is never
|
|
27
|
+
interpolated into Daftari-authored text. RBAC mirrors the read path: a
|
|
28
|
+
receipt over an unreadable collection is denied, an unreadable supersession
|
|
29
|
+
hop degrades to `restricted`, and a tension is visible only when both
|
|
30
|
+
sources' collections are readable (the `vault_status` precedent). README
|
|
31
|
+
tool list updated to the full 26-tool surface (the "14 tools" count
|
|
32
|
+
predated the edge / staged-action / tension-graph tools).
|
|
33
|
+
|
|
34
|
+
- **`daftari asof` — belief archaeology.** A read-only CLI report over the
|
|
35
|
+
vault's git history: `daftari asof <ref-or-date>` resolves a git ref or a
|
|
36
|
+
`YYYY-MM-DD` date (the last commit on or before that day) and reports the
|
|
37
|
+
vault's belief state at that point plus the drift since — documents
|
|
38
|
+
added/removed, `status`/`confidence` transitions, body-change counts, and
|
|
39
|
+
tensions opened or resolved (the committed `.daftari/tensions.md` is parsed
|
|
40
|
+
at both points with the live parser via the newly exported
|
|
41
|
+
`parseTensionLog`). `--doc <path>` adds a single-document trajectory
|
|
42
|
+
(frontmatter then vs now, every commit touching it since); `--blast <path>`
|
|
43
|
+
adds a **counterfactual replay** — the blast radius of the document
|
|
44
|
+
computed over the tree *as of the commit* (reusing `computeBlast` and the
|
|
45
|
+
reverse source/link maps from `vault_tension_blast`), each downstream
|
|
46
|
+
document annotated with its status today ("this fact turned out wrong — who
|
|
47
|
+
had inherited it, and where are they now?"). Strictly read-only plumbing:
|
|
48
|
+
`git ls-tree` + one `git cat-file --batch` process for the whole historical
|
|
49
|
+
tree — no checkout, no worktree, no index, no API key. Historical trees are
|
|
50
|
+
filtered with the live loader's exclusion rules (dotfiles, `.daftari/`,
|
|
51
|
+
`node_modules`, `.obsidian/`, `.trash/`) so then/now diffs can't report
|
|
52
|
+
phantom drift. Markdown to stdout, `--output` / `--output-json` to files;
|
|
53
|
+
audit-convention exit codes (0 report, 2 config/usage, 3 runtime). Pairs
|
|
54
|
+
with `vault_receipt`: a receipt's `vaultHead` is the anchor to hand back to
|
|
55
|
+
`asof`.
|
|
56
|
+
|
|
57
|
+
- **`daftari court` — the Tension Court.** Common-law memory over the
|
|
58
|
+
tension log. `daftari court` compiles a **docket**: every open tension
|
|
59
|
+
briefed and ranked by priority (aging tier stale→fresh, then blast size,
|
|
60
|
+
then age) — both sides' claims verbatim with the present status and decay
|
|
61
|
+
of their documents ("gone" when a side was deleted), the union blast
|
|
62
|
+
radius a ruling would settle (reusing `computeBlast` and the
|
|
63
|
+
reverse-source/link maps from `vault_tension_blast`), tension-cluster
|
|
64
|
+
membership, and **precedents**: past rulings retrieved by a deterministic
|
|
65
|
+
three-tier match (shared-document > collection-pair > same-kind; newest
|
|
66
|
+
first within a tier, capped at 3, no LLM). `--tension <id>` renders a
|
|
67
|
+
single case's full brief including precedent rationales verbatim.
|
|
68
|
+
`daftari court rule <id> --kind superseded|corrected|accepted|invalid
|
|
69
|
+
[--rationale …] [--references …] [--by …]` records the ruling through the
|
|
70
|
+
same `resolveTension` write path as `vault_tension_resolve`; the rationale
|
|
71
|
+
is recorded verbatim and cited by future dockets — a ruling is precedent
|
|
72
|
+
the moment it lands, because a precedent IS a resolved tension. The court
|
|
73
|
+
retrieves and briefs; it never decides, and a ruling never edits the
|
|
74
|
+
disputed documents. Markdown to stdout, `--output` / `--output-json`;
|
|
75
|
+
audit-convention exit codes (0/2/3).
|
|
76
|
+
|
|
77
|
+
- **`daftari sleep` — circadian memory** (positioning idea 6, gate cleared by
|
|
78
|
+
the CB7 result). A nightly metabolic pass composing machinery that already
|
|
79
|
+
exists — deterministic, LLM-free, and write-free with respect to documents:
|
|
80
|
+
sweeps expired staged actions, scores every document's decay, and builds
|
|
81
|
+
the **wake list** (canonical accumulation docs past TTL with downstream
|
|
82
|
+
dependents, ranked by blast radius via the `vault_tension_blast` reverse
|
|
83
|
+
maps), written to a gitignored `.daftari/wake-queue.jsonl` snapshot for an
|
|
84
|
+
external agent to re-verify against sources — the vault never re-verifies
|
|
85
|
+
on its own. The domain split is honored: generative docs going stale are
|
|
86
|
+
expected — counted, never woken; expired docs with no dependents are
|
|
87
|
+
reported as quiet decay, not woken. The **Morning Report** surfaces tension
|
|
88
|
+
aging and the court docket head, the ratification queue with
|
|
89
|
+
soon-to-expire proposals, and the rubber-stamp monitor (zero rejections
|
|
90
|
+
over ≥10 decisions prints a warning — the circadian design's kill-condition
|
|
91
|
+
instrumentation). Scheduling stays the OS's job (cron example in
|
|
92
|
+
`--help`); daftari ships the cycle, not a daemon. Markdown to stdout,
|
|
93
|
+
`--output` / `--output-json`, `--wake-limit` (report rows only — the queue
|
|
94
|
+
always carries the full list, no silent caps), `--no-queue`;
|
|
95
|
+
audit-convention exit codes. `.daftari/wake-queue.jsonl` added to the vault
|
|
96
|
+
gitignore template.
|
|
97
|
+
|
|
98
|
+
- **`vault_witness` — agent track records + the wager layer** (positioning
|
|
99
|
+
ideas 4 and 9, gate cleared by the CB7 result). A read-only MCP tool that
|
|
100
|
+
aggregates the vault's own ledgers — provenance log, tension log, staged
|
|
101
|
+
actions — into a per-principal track record, priced by a provisional,
|
|
102
|
+
exported wager schedule (`low` 0 / `medium` 1 / `high` 3; survival credit
|
|
103
|
+
1; gone-doc burn 1 — calibration constants, like the §11.5 impact table).
|
|
104
|
+
Per principal: write volume and span (the longitudinal series for idea 9's
|
|
105
|
+
kill condition), docs authored (first provenance entry wins; authenticated
|
|
106
|
+
`principal` outranks the free-text `agent` claim), live claims with open
|
|
107
|
+
exposure, contested claims with stake at risk, the settled book (claims
|
|
108
|
+
corrected by ruling, retired, or deleted burn their stake; claims
|
|
109
|
+
maintained through a full TTL cycle earn credit; `balance` is the
|
|
110
|
+
difference), proposal outcomes, and tensions logged. Includes the
|
|
111
|
+
flat-curve monitor (idea 4's kill condition): one principal at ≥95% of
|
|
112
|
+
writes flags the records as uninformative instead of reporting them as
|
|
113
|
+
signal. RBAC follows the `vault_status` precedent — everything is scoped
|
|
114
|
+
to readable collections. Advisory and deterministic; nothing is enforced,
|
|
115
|
+
no document is touched, edge-observer attribution is deferred (the edge
|
|
116
|
+
log's collapse keeps observers internal). Tool surface is now 27.
|
|
117
|
+
|
|
118
|
+
- **`vault_search` hits carry unresolved tensions inline** (`contested` /
|
|
119
|
+
`contestedCount`). Each annotation is the full two-sided marker — both
|
|
120
|
+
claims, kind, counterpart, tension id — post-joined from
|
|
121
|
+
`.daftari/tensions.md` in the same enrichment pass as `currentSource`,
|
|
122
|
+
capped at 3 per hit with an honest total. RBAC-gated on the counterpart's
|
|
123
|
+
collection (unreadable ⇒ omitted entirely, and excluded from the count).
|
|
124
|
+
Measured motivation: the tension-graph feud benchmark (2026-07-04) — on
|
|
125
|
+
feuds where retrieval buries one side, agents surface the contradiction
|
|
126
|
+
~8% baseline vs ~46% with the tension inline; the dedicated-tool shape
|
|
127
|
+
loses to inline across all panel models. Tensions remain advisory and
|
|
128
|
+
never affect ranking.
|
|
129
|
+
|
|
130
|
+
- **OpenRouter LLM transport for `daftari consolidate`** (`--transport
|
|
131
|
+
anthropic|openrouter`, env fallback `DAFTARI_LLM_TRANSPORT`). A second
|
|
132
|
+
model-family client (`createOpenRouterClient`) implementing the same
|
|
133
|
+
`LlmClient` contract as the Anthropic client, promoted from the
|
|
134
|
+
decorrelation shim. On the openrouter transport the CLI gates on
|
|
135
|
+
`OPENROUTER_API_KEY` (not `ANTHROPIC_API_KEY`), defaults the model to
|
|
136
|
+
`anthropic/claude-haiku-4.5`, and accepts any OpenRouter slug via `--model`.
|
|
137
|
+
This is the substrate for the Stage-5 multi-model graduation gate (spec §12
|
|
138
|
+
amendment, 2026-07-02): single-family panel votes are ~92% error-correlated,
|
|
139
|
+
so `k_survived` needs a second model family before any auto-write tier can
|
|
140
|
+
graduate. `completeWithTools` is deliberately unsupported on this transport
|
|
141
|
+
(only `daftari eval` drives tools; eval stays on anthropic).
|
|
142
|
+
|
|
143
|
+
### Security
|
|
144
|
+
|
|
145
|
+
- **Tension tools now enforce the both-sides visibility rule** (#212).
|
|
146
|
+
`vault_tension_clusters` and `vault_tension_blast` compute over only the
|
|
147
|
+
tensions whose BOTH sides the caller can read — filtered before
|
|
148
|
+
aggregation, so counts, cluster sizes, and blast seeds reveal nothing
|
|
149
|
+
about hidden entries. `vault_tension_log` refuses to record claims naming
|
|
150
|
+
a document the caller cannot read (denial names the caller-supplied path
|
|
151
|
+
only); `vault_tension_resolve` returns the exact not-found error for
|
|
152
|
+
invisible tensions, checked before the loop-authored ratify rule. This
|
|
153
|
+
closes the bypass around #211's contested-annotation gate: one rule
|
|
154
|
+
(`collectionForPath` + `canSeeTension`) now governs every tension
|
|
155
|
+
surface. No-RBAC deployments are unaffected. Known residual (accepted):
|
|
156
|
+
sequential tension ids still reveal the total entry count to callers who
|
|
157
|
+
can log. A follow-up consolidation (`sourceReadable`, exported from
|
|
158
|
+
`tension-access.ts`) then unified the canonicalize → reject-escape →
|
|
159
|
+
`canRead` sequence into a single predicate adopted by all four call
|
|
160
|
+
sites — the tension log/blast gates above and #211's contested-annotation
|
|
161
|
+
filter in `contested.ts` — so one guard now backs every tension-graph tool surface,
|
|
162
|
+
including contested annotations on `vault_search` hits. Further
|
|
163
|
+
residuals (accepted, tracked in follow-ups): `vault_status` /
|
|
164
|
+
`vault_receipt` / court-precedent tension summaries still filter by
|
|
165
|
+
uncanonicalized top-level segment, and `vault_lint`'s tension-health
|
|
166
|
+
aggregates count all entries (counts only, no content).
|
|
167
|
+
|
|
168
|
+
### Internal
|
|
169
|
+
|
|
170
|
+
- **CB7 decision-divergence bench** (`integrations/consensus-bench`,
|
|
171
|
+
benchmark tooling only). Implements the
|
|
172
|
+
2026-07-11 CB7 design: instance assembly from existing artifacts (CB6
|
|
173
|
+
tension pairs, CO2 stale-trap diffs, consensus-box supersession chains as
|
|
174
|
+
settled controls — CB6 tension items excluded from the control set),
|
|
175
|
+
condition renderer with locked validity invariants (task text
|
|
176
|
+
byte-identical across memory conditions; the collapsed block carries one
|
|
177
|
+
value and no epistemic language; settled controls give the foil the
|
|
178
|
+
governing value), deterministic enum scorer (divergence, calibration,
|
|
179
|
+
hedge tax — no LLM judge on primary metrics), and `cb7-runner.mjs` for the
|
|
180
|
+
live panel run (`--gate` mode runs the second-rater leakage check).
|
|
181
|
+
M-collapsed for tensions holds the challenger position (recency /
|
|
182
|
+
last-write-wins) rather than the spec's CB6-foil-verdict, a deterministic
|
|
183
|
+
deviation recorded in the module.
|
|
184
|
+
|
|
185
|
+
## [1.29.0] - 2026-06-25
|
|
186
|
+
|
|
187
|
+
### Changed
|
|
188
|
+
|
|
189
|
+
- **`vault_search` now defaults to chunk-level BM25 lexical ranking** ([#160]).
|
|
190
|
+
The lexical half of hybrid search previously scored whole documents, which
|
|
191
|
+
diluted a relevant topic across long multi-topic documents; it now scores
|
|
192
|
+
per-chunk and keeps each document's best chunk. This recovers most of the
|
|
193
|
+
multi-document retrieval-recall gap (Recall Bench multi-day; replicated on
|
|
194
|
+
SQuAD human queries, hit@1 0.693→0.828) and produces measurably better
|
|
195
|
+
end-to-end answers where it out-retrieves the old ranker, with no regression
|
|
196
|
+
where it doesn't (SQuAD answer-quality ablation: composite +0.53/+0.29/+0.26
|
|
197
|
+
at K=1/5/10, all 95% CIs above zero, no hallucination increase). Title- and
|
|
198
|
+
tag-only retrieval is preserved by a tiered combine (body matches always rank
|
|
199
|
+
above title/tag-only matches). **This changes result ordering for existing
|
|
200
|
+
vaults.** Callers that need the previous behavior can pass
|
|
201
|
+
`lexicalGranularity: "document"`. Related-document search (`vault_search_related`)
|
|
202
|
+
is unchanged (still document-granularity). Index format is unchanged — no
|
|
203
|
+
reindex required.
|
|
204
|
+
|
|
205
|
+
[#160]: https://github.com/mavaali/daftari/pull/160
|
|
206
|
+
|
|
10
207
|
## [1.28.0] - 2026-06-22
|
|
11
208
|
|
|
12
209
|
### Added
|
package/README.md
CHANGED
|
@@ -10,33 +10,53 @@ Corrections were noted, not erased. The ledger got more valuable the longer it
|
|
|
10
10
|
was kept, because the accumulated record revealed patterns no single entry
|
|
11
11
|
could.
|
|
12
12
|
|
|
13
|
-
Daftari is
|
|
14
|
-
structured
|
|
15
|
-
cortex, not a clipboard.
|
|
16
|
-
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
model
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
13
|
+
Daftari is the **long-term memory cortex for your LLM agents** — a persistent,
|
|
14
|
+
structured vault they read, write, and curate over time, **portable across any
|
|
15
|
+
model.** A cortex, not a clipboard.
|
|
16
|
+
|
|
17
|
+
## Rent the brain, own the memory
|
|
18
|
+
|
|
19
|
+
LLMs are stateless; they forget. So memory is being bolted on everywhere — but
|
|
20
|
+
*inside the model*: ChatGPT memory, Claude projects, Copilot, Gemini. Memory is
|
|
21
|
+
becoming a feature of the provider, and whoever holds your memory holds you.
|
|
22
|
+
|
|
23
|
+
Daftari takes the other path. The model is the rented part — swappable, obsolete
|
|
24
|
+
in six months. Your memory is the durable asset, so it should belong to you and
|
|
25
|
+
travel with you: plain markdown on your disk, under git, readable in any editor,
|
|
26
|
+
queryable by any agent. **Compilation over retrieval** — the agent compiles an
|
|
27
|
+
answer once and writes it back, so every later read starts from the compiled
|
|
28
|
+
result instead of re-stitching chunks from zero.
|
|
29
|
+
|
|
30
|
+
## Not a second brain
|
|
31
|
+
|
|
32
|
+
Second brains are memory for a *human* to think with — you catch the stale fact,
|
|
33
|
+
you notice the contradiction. Daftari is memory for an *agent* to reason with:
|
|
34
|
+
the persistence layer for a consumer that acts on what it is handed and cannot
|
|
35
|
+
sanity-check it first. Same substrate (markdown, links); reversed purpose — and
|
|
36
|
+
a higher bar, because the reliability has to live in the memory, not the reader.
|
|
37
|
+
|
|
38
|
+
## It remembers — it doesn't resolve for you
|
|
39
|
+
|
|
40
|
+
Because the agent can't infer them, the vault carries three things and collapses
|
|
41
|
+
none:
|
|
42
|
+
|
|
43
|
+
- **what's current** — supersession follows a real edge to the latest source
|
|
44
|
+
- **what's grounded** — provenance on every entry; the vault never mints a value
|
|
45
|
+
- **what's contested** — contradictions surface as *tensions*, held open, not
|
|
46
|
+
flattened into a false answer
|
|
47
|
+
|
|
48
|
+
The daftar noted corrections rather than erasing them. Daftari keeps that as a
|
|
49
|
+
law:
|
|
50
|
+
|
|
51
|
+
> **A tension may never masquerade as a supersession.**
|
|
52
|
+
|
|
53
|
+
It resolves only by discovery — a real edge — never by invention. The agent
|
|
54
|
+
compiles; the vault preserves; *you* keep the judgment. See
|
|
55
|
+
[the manifesto](docs/manifesto.md) for the full argument.
|
|
36
56
|
|
|
37
57
|
## What it is
|
|
38
58
|
|
|
39
|
-
A directory of markdown files with YAML frontmatter, exposed to agents as
|
|
59
|
+
A directory of markdown files with YAML frontmatter, exposed to agents as 27
|
|
40
60
|
MCP tools over stdio. The vault is plain text: you can read it in any editor,
|
|
41
61
|
`git log` it, grep it. Daftari adds the machinery agents need to treat it as a
|
|
42
62
|
shared workspace.
|
|
@@ -50,7 +70,10 @@ Point any MCP client (Claude Desktop, Claude Code, an agent SDK) at it.
|
|
|
50
70
|
|
|
51
71
|
## The four layers
|
|
52
72
|
|
|
53
|
-
|
|
73
|
+
All four implement one idea — *resolve only by discovery, never by invention.*
|
|
74
|
+
Read [**The core idea**](docs/architecture.md#the-core-idea) first and the layers
|
|
75
|
+
become its consequences. Storage and access control are table stakes; the moat is
|
|
76
|
+
layers 3 and 4.
|
|
54
77
|
|
|
55
78
|
|Layer |What it does |Why it matters |
|
|
56
79
|
|---------------------|------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|
|
|
@@ -63,11 +86,31 @@ Storage and access control are table stakes. The moat is layers 3 and 4.
|
|
|
63
86
|
|
|
64
87
|
**Read:** `vault_read`, `vault_index`, `vault_status`
|
|
65
88
|
|
|
66
|
-
**
|
|
89
|
+
**Attest:** `vault_receipt` — compile an epistemic receipt for the documents
|
|
90
|
+
an answer cites: per-source status, confidence, provenance, freshness, exact
|
|
91
|
+
content-version hash, supersession-chain resolution, and open tensions, plus
|
|
92
|
+
deterministic summary flags, the vault's git HEAD as an as-of anchor, and a
|
|
93
|
+
recomputable hash over the whole receipt. Attach it to the answer so any
|
|
94
|
+
consumer can see what the answer stands on.
|
|
95
|
+
|
|
96
|
+
**Witness:** `vault_witness` — per-principal track records from the vault's
|
|
97
|
+
own ledgers, priced by the wager schedule: write volume, live claims with
|
|
98
|
+
open exposure, contested claims with stake at risk, the settled book
|
|
99
|
+
(burned vs credited), proposal outcomes, tensions logged. Advisory and
|
|
100
|
+
deterministic; includes the flat-curve monitor so a single-author vault is
|
|
101
|
+
reported as uninformative rather than as signal.
|
|
102
|
+
|
|
103
|
+
**Search:** `vault_search` (hybrid BM25 + vector; hits carry their unresolved
|
|
104
|
+
tensions inline and foreground the current source of superseded documents),
|
|
105
|
+
`vault_search_related`, `vault_themes` (thematic clustering), `vault_reindex`
|
|
106
|
+
|
|
107
|
+
**Write:** `vault_write`, `vault_append`, `vault_promote`, `vault_deprecate`, `vault_supersede`, `vault_merge`, `vault_set_confidence`
|
|
108
|
+
|
|
109
|
+
**Curate:** `vault_tension_log`, `vault_tension_resolve`, `vault_tension_clusters`, `vault_tension_blast`, `vault_lint`, `vault_provenance`
|
|
67
110
|
|
|
68
|
-
**
|
|
111
|
+
**Edges:** `vault_edge_observe`, `vault_edge_contest`, `vault_edges`
|
|
69
112
|
|
|
70
|
-
**
|
|
113
|
+
**Ratify:** `vault_stage_action`, `vault_ratify`
|
|
71
114
|
|
|
72
115
|
The curation engine is advisory: `vault_lint` reports problems and
|
|
73
116
|
`vault_tension_log` records contradictions. Neither auto-fixes anything. Every
|
|
@@ -382,6 +425,102 @@ fail_on:
|
|
|
382
425
|
transitive_staleness: 100 # default: generous; teams tune
|
|
383
426
|
```
|
|
384
427
|
|
|
428
|
+
## The vault as witness — and the wager layer
|
|
429
|
+
|
|
430
|
+
Every write already carries an identity, every proposal an outcome, every
|
|
431
|
+
tension a logger and a ruling. `vault_witness` aggregates that ledger into a
|
|
432
|
+
**track record per principal** — and prices it. Confidence is free to claim,
|
|
433
|
+
so the wager schedule makes it cost something: writing at `high` stakes 3
|
|
434
|
+
points, `medium` 1, `low` 0 (hedged claims are the honest default and are
|
|
435
|
+
never taxed). A claim later corrected by a ruling or retired by someone else
|
|
436
|
+
burns the stake; a claim maintained through a full TTL cycle earns credit.
|
|
437
|
+
The balance is arithmetic on recorded facts — advisory, provisional
|
|
438
|
+
constants, nothing enforced: routing a high-stakes write to the agent with
|
|
439
|
+
the earned balance is your policy, not the vault's. Both kill conditions
|
|
440
|
+
from the design travel with the tool: the flat-curve monitor (one author ≥95%
|
|
441
|
+
of writes → curves declared uninformative) and the longitudinal write-volume
|
|
442
|
+
series (if stake-fear suppresses honest claims, it shows up here first).
|
|
443
|
+
|
|
444
|
+
## Circadian memory
|
|
445
|
+
|
|
446
|
+
The vault sleeps. `daftari sleep` is the nightly metabolic pass — deterministic,
|
|
447
|
+
LLM-free, write-free (documents are never touched):
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
# In cron (any scheduler works; daftari ships the cycle, not a daemon):
|
|
451
|
+
0 3 * * * cd /path/to/vault && npx daftari sleep --output .daftari/morning-report.md
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
The cycle sweeps expired staged actions, scores every document's decay, and
|
|
455
|
+
builds the **wake list**: canonical accumulation documents past their TTL
|
|
456
|
+
with downstream dependents, ranked by blast radius. The list is written to
|
|
457
|
+
`.daftari/wake-queue.jsonl` for an external agent to consume — re-verify each
|
|
458
|
+
document against its sources, stage the diff — because the vault never
|
|
459
|
+
re-verifies on its own. Generative documents going stale are expected, not a
|
|
460
|
+
defect: counted, never woken.
|
|
461
|
+
|
|
462
|
+
The **Morning Report** ends where the human begins: tension aging and the
|
|
463
|
+
court docket head, the ratification queue with soon-to-expire proposals, and
|
|
464
|
+
the rubber-stamp monitor — zero rejections over a long decision history is
|
|
465
|
+
printed as a warning, not a compliment. The agent proposes overnight; you
|
|
466
|
+
ratify over coffee.
|
|
467
|
+
|
|
468
|
+
## Tension Court
|
|
469
|
+
|
|
470
|
+
Tensions wait in a log; the court turns them into decidable cases. `daftari
|
|
471
|
+
court` compiles a **docket** — every open tension briefed and ranked (stale
|
|
472
|
+
first, then by blast radius): both sides' claims, the present state of their
|
|
473
|
+
documents, the downstream stakes, cluster membership, and **precedents** —
|
|
474
|
+
past rulings on disputes that shared a document, a collection pair, or a
|
|
475
|
+
kind.
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
# The docket — a 5-minute weekly ritual
|
|
479
|
+
daftari court --vault ./my-vault
|
|
480
|
+
|
|
481
|
+
# One case's full brief (verbatim rationales from cited precedents)
|
|
482
|
+
daftari court --tension tension-abc123
|
|
483
|
+
|
|
484
|
+
# Rule. The rationale is recorded verbatim and cited by future dockets.
|
|
485
|
+
daftari court rule tension-abc123 --kind corrected \
|
|
486
|
+
--rationale "Vendor pricing page confirmed the entry tier on 2026-07-10."
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Rulings go through the same `resolveTension` write path as
|
|
490
|
+
`vault_tension_resolve` — a ruling records the closure, it never edits the
|
|
491
|
+
disputed documents. Precedent retrieval is deterministic (shared-document >
|
|
492
|
+
collection-pair > same-kind; no LLM): the court retrieves how this house has
|
|
493
|
+
resolved similar disputes before, and whether a precedent applies stays the
|
|
494
|
+
human's judgment. Memory grows case law.
|
|
495
|
+
|
|
496
|
+
## Belief archaeology
|
|
497
|
+
|
|
498
|
+
Git is the version layer, so the vault can answer **"what did we believe on
|
|
499
|
+
March 3?"** `daftari asof` is a read-only report over the repo's history — no
|
|
500
|
+
checkout, no index, no API key:
|
|
501
|
+
|
|
502
|
+
```bash
|
|
503
|
+
# The vault's belief state at a date (or any git ref), plus the drift since
|
|
504
|
+
daftari asof 2026-03-03 --vault ./my-vault
|
|
505
|
+
|
|
506
|
+
# One document's trajectory: frontmatter then vs now, commits in between
|
|
507
|
+
daftari asof HEAD~20 --doc pricing/helios-consumption-pricing.md
|
|
508
|
+
|
|
509
|
+
# Counterfactual replay: this fact turned out wrong — who had inherited it
|
|
510
|
+
# at the time, and where are they now?
|
|
511
|
+
daftari asof 2026-03-03 --blast pricing/helios-consumption-pricing.md
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
The default report shows the document and tension state at that point and
|
|
515
|
+
the drift since: documents added/removed, `status`/`confidence` transitions,
|
|
516
|
+
and tensions opened or resolved. `--blast` computes the blast radius of a
|
|
517
|
+
document over the tree *as of the commit* (same source/link edge semantics as
|
|
518
|
+
`vault_tension_blast`), annotating each downstream document with its status
|
|
519
|
+
today — the post-mortem view for a fact that was later corrected. Markdown to
|
|
520
|
+
stdout by default; `--output` / `--output-json` write files. Pairs with
|
|
521
|
+
`vault_receipt`: a receipt's `vaultHead` is exactly the anchor to hand back
|
|
522
|
+
to `asof`.
|
|
523
|
+
|
|
385
524
|
## Development
|
|
386
525
|
|
|
387
526
|
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Result } from "../frontmatter/types.js";
|
|
2
|
+
export interface AsofCommit {
|
|
3
|
+
hash: string;
|
|
4
|
+
date: string;
|
|
5
|
+
subject: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveAsofCommit(vaultRoot: string, refOrDate: string): Promise<Result<AsofCommit, Error>>;
|
|
8
|
+
export declare function listTreeDocs(vaultRoot: string, commit: string): Promise<Result<string[], Error>>;
|
|
9
|
+
export declare function readBlobsAt(vaultRoot: string, commit: string, paths: string[]): Promise<Result<Map<string, string>, Error>>;
|
|
10
|
+
export interface RangeCommit {
|
|
11
|
+
hash: string;
|
|
12
|
+
date: string;
|
|
13
|
+
author: string;
|
|
14
|
+
subject: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function logRangeForPath(vaultRoot: string, since: string, path: string): Promise<Result<RangeCommit[], Error>>;
|
|
17
|
+
//# sourceMappingURL=git-read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-read.d.ts","sourceRoot":"","sources":["../../src/asof/git-read.ts"],"names":[],"mappings":"AAWA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAqB/D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAQD,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAwBpC;AAaD,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC,CAMlC;AAMD,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAuD7C;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,CAAC,CAmBvC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// Read-only git plumbing for `daftari asof` — belief archaeology.
|
|
2
|
+
//
|
|
3
|
+
// Git is Daftari's version layer, so "what did we believe on March 3?" is a
|
|
4
|
+
// question git can already answer: resolve the date to a commit, read the
|
|
5
|
+
// tree at that commit, parse the same markdown the live tools parse. This
|
|
6
|
+
// module is strictly read-only — it never touches the work tree, never
|
|
7
|
+
// creates a worktree or checkout, and writes nothing to the repo. All reads
|
|
8
|
+
// go through `git ls-tree` / `git cat-file --batch` / `git log`.
|
|
9
|
+
import { execFile, spawn } from "node:child_process";
|
|
10
|
+
import { promisify } from "node:util";
|
|
11
|
+
import { err, ok } from "../frontmatter/types.js";
|
|
12
|
+
const run = promisify(execFile);
|
|
13
|
+
async function git(vaultRoot, args) {
|
|
14
|
+
try {
|
|
15
|
+
const { stdout } = await run("git", ["-C", vaultRoot, ...args], {
|
|
16
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
17
|
+
});
|
|
18
|
+
return ok(stdout);
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
const reason = e instanceof Error && "stderr" in e && typeof e.stderr === "string"
|
|
22
|
+
? e.stderr.trim() || e.message
|
|
23
|
+
: e instanceof Error
|
|
24
|
+
? e.message
|
|
25
|
+
: String(e);
|
|
26
|
+
return err(new Error(`git ${args[0]} failed: ${reason}`));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
30
|
+
// Resolves the user's `<ref-or-date>` to a commit. A YYYY-MM-DD date means
|
|
31
|
+
// "the last commit made on or before the end of that day" (committer date,
|
|
32
|
+
// local time — the same clock the commits were made on). Anything else is
|
|
33
|
+
// handed to rev-parse as a ref (HEAD~3, a branch, a hash, a tag).
|
|
34
|
+
export async function resolveAsofCommit(vaultRoot, refOrDate) {
|
|
35
|
+
if (typeof refOrDate !== "string" || refOrDate.trim().length === 0) {
|
|
36
|
+
return err(new Error("asof requires a non-empty ref or YYYY-MM-DD date"));
|
|
37
|
+
}
|
|
38
|
+
const input = refOrDate.trim();
|
|
39
|
+
let hash;
|
|
40
|
+
if (DATE_RE.test(input)) {
|
|
41
|
+
const listed = await git(vaultRoot, ["rev-list", "-1", `--before=${input} 23:59:59`, "HEAD"]);
|
|
42
|
+
if (!listed.ok)
|
|
43
|
+
return listed;
|
|
44
|
+
hash = listed.value.trim();
|
|
45
|
+
if (hash.length === 0) {
|
|
46
|
+
return err(new Error(`no commit exists on or before ${input}`));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const parsed = await git(vaultRoot, ["rev-parse", "--verify", `${input}^{commit}`]);
|
|
51
|
+
if (!parsed.ok)
|
|
52
|
+
return err(new Error(`cannot resolve '${input}' to a commit`));
|
|
53
|
+
hash = parsed.value.trim();
|
|
54
|
+
}
|
|
55
|
+
const meta = await git(vaultRoot, ["show", "-s", "--format=%H%x1f%cs%x1f%s", hash]);
|
|
56
|
+
if (!meta.ok)
|
|
57
|
+
return meta;
|
|
58
|
+
const [fullHash, date, subject] = meta.value.trim().split("\x1f");
|
|
59
|
+
return ok({ hash: fullHash ?? hash, date: date ?? "", subject: subject ?? "" });
|
|
60
|
+
}
|
|
61
|
+
// Path segments the live loader never sees (listFiles ignores dotfiles,
|
|
62
|
+
// .daftari, node_modules, .obsidian, .trash) — the historical tree must be
|
|
63
|
+
// filtered identically or then/now diffs would report phantom drift.
|
|
64
|
+
function isManagedDocPath(path) {
|
|
65
|
+
if (!path.endsWith(".md"))
|
|
66
|
+
return false;
|
|
67
|
+
const segments = path.split("/");
|
|
68
|
+
return segments.every((s) => !s.startsWith(".") && s !== "node_modules");
|
|
69
|
+
}
|
|
70
|
+
// Vault-relative paths of the managed markdown documents in the tree at
|
|
71
|
+
// `commit`, sorted (matching listFiles' sorted output).
|
|
72
|
+
export async function listTreeDocs(vaultRoot, commit) {
|
|
73
|
+
const listed = await git(vaultRoot, ["ls-tree", "-r", "--name-only", "-z", commit]);
|
|
74
|
+
if (!listed.ok)
|
|
75
|
+
return listed;
|
|
76
|
+
const paths = listed.value.split("\0").filter((p) => p.length > 0 && isManagedDocPath(p));
|
|
77
|
+
paths.sort();
|
|
78
|
+
return ok(paths);
|
|
79
|
+
}
|
|
80
|
+
// Reads many blobs from one commit in a single `git cat-file --batch`
|
|
81
|
+
// process. Returns a map of path → file content; a path that does not exist
|
|
82
|
+
// at the commit is simply absent from the map. One spawn total, so reading a
|
|
83
|
+
// 3,500-file historical tree costs one process, not 3,500.
|
|
84
|
+
export async function readBlobsAt(vaultRoot, commit, paths) {
|
|
85
|
+
if (paths.length === 0)
|
|
86
|
+
return ok(new Map());
|
|
87
|
+
return new Promise((resolvePromise) => {
|
|
88
|
+
const child = spawn("git", ["-C", vaultRoot, "cat-file", "--batch"], {
|
|
89
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
90
|
+
});
|
|
91
|
+
const stdoutChunks = [];
|
|
92
|
+
const stderrChunks = [];
|
|
93
|
+
child.stdout.on("data", (c) => stdoutChunks.push(c));
|
|
94
|
+
child.stderr.on("data", (c) => stderrChunks.push(c));
|
|
95
|
+
child.on("error", (e) => {
|
|
96
|
+
resolvePromise(err(new Error(`git cat-file failed to spawn: ${e.message}`)));
|
|
97
|
+
});
|
|
98
|
+
child.on("close", (code) => {
|
|
99
|
+
if (code !== 0) {
|
|
100
|
+
const reason = Buffer.concat(stderrChunks).toString("utf-8").trim();
|
|
101
|
+
resolvePromise(err(new Error(`git cat-file exited ${code}: ${reason}`)));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Batch output, per requested object, in request order:
|
|
105
|
+
// "<oid> <type> <size>\n" + <size> bytes + "\n" — found
|
|
106
|
+
// "<input> missing\n" — absent
|
|
107
|
+
// Sizes are BYTE counts, so parsing walks the raw Buffer, decoding
|
|
108
|
+
// each content slice to UTF-8 only after it is bounded.
|
|
109
|
+
const out = Buffer.concat(stdoutChunks);
|
|
110
|
+
const contents = new Map();
|
|
111
|
+
let offset = 0;
|
|
112
|
+
for (const path of paths) {
|
|
113
|
+
const nl = out.indexOf(0x0a, offset);
|
|
114
|
+
if (nl === -1) {
|
|
115
|
+
resolvePromise(err(new Error("git cat-file: truncated batch output")));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const header = out.subarray(offset, nl).toString("utf-8");
|
|
119
|
+
offset = nl + 1;
|
|
120
|
+
if (header.endsWith(" missing"))
|
|
121
|
+
continue;
|
|
122
|
+
const parts = header.split(" ");
|
|
123
|
+
const size = Number(parts[2]);
|
|
124
|
+
if (!Number.isFinite(size) || size < 0) {
|
|
125
|
+
resolvePromise(err(new Error(`git cat-file: unparseable header: ${header}`)));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
contents.set(path, out.subarray(offset, offset + size).toString("utf-8"));
|
|
129
|
+
offset += size + 1; // skip the trailing \n after the content
|
|
130
|
+
}
|
|
131
|
+
resolvePromise(ok(contents));
|
|
132
|
+
});
|
|
133
|
+
for (const path of paths)
|
|
134
|
+
child.stdin.write(`${commit}:${path}\n`);
|
|
135
|
+
child.stdin.end();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// Commits in `<since>..HEAD` touching `path`, newest first. The trajectory
|
|
139
|
+
// view uses this to show every revision a document went through since the
|
|
140
|
+
// as-of point.
|
|
141
|
+
export async function logRangeForPath(vaultRoot, since, path) {
|
|
142
|
+
const result = await git(vaultRoot, [
|
|
143
|
+
"log",
|
|
144
|
+
"--format=%H%x1f%cs%x1f%aN%x1f%s%x1e",
|
|
145
|
+
`${since}..HEAD`,
|
|
146
|
+
"--",
|
|
147
|
+
path,
|
|
148
|
+
]);
|
|
149
|
+
if (!result.ok)
|
|
150
|
+
return result;
|
|
151
|
+
const commits = [];
|
|
152
|
+
for (const record of result.value.split("\x1e")) {
|
|
153
|
+
const trimmed = record.trim();
|
|
154
|
+
if (!trimmed)
|
|
155
|
+
continue;
|
|
156
|
+
const [hash, date, author, subject] = trimmed.split("\x1f");
|
|
157
|
+
if (!hash)
|
|
158
|
+
continue;
|
|
159
|
+
commits.push({ hash, date: date ?? "", author: author ?? "", subject: subject ?? "" });
|
|
160
|
+
}
|
|
161
|
+
return ok(commits);
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=git-read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-read.js","sourceRoot":"","sources":["../../src/asof/git-read.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/asof/index.ts"],"names":[],"mappings":"AA2DA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqF7D"}
|