things-api 0.9.0 → 0.11.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 +57 -12
- package/dist/audit/log.js +56 -2
- package/dist/audit/log.js.map +1 -1
- package/dist/audit/schema.d.ts +26 -8
- package/dist/audit/schema.js +42 -1
- package/dist/audit/schema.js.map +1 -1
- package/dist/cli/clock.d.ts +8 -0
- package/dist/cli/clock.js +24 -0
- package/dist/cli/clock.js.map +1 -0
- package/dist/cli/commands/area.d.ts +26 -3
- package/dist/cli/commands/area.js +129 -75
- package/dist/cli/commands/area.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +1 -1
- package/dist/cli/commands/doctor.js +44 -5
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/install-skill.d.ts +45 -0
- package/dist/cli/commands/install-skill.js +207 -0
- package/dist/cli/commands/install-skill.js.map +1 -0
- package/dist/cli/commands/mcp.js +23 -4
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/project.d.ts +18 -1
- package/dist/cli/commands/project.js +74 -35
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.d.ts +15 -2
- package/dist/cli/commands/reads.js +459 -165
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/repeat-flags.d.ts +20 -0
- package/dist/cli/commands/repeat-flags.js +76 -0
- package/dist/cli/commands/repeat-flags.js.map +1 -0
- package/dist/cli/commands/setup.js +8 -4
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/show.js +53 -30
- package/dist/cli/commands/show.js.map +1 -1
- package/dist/cli/commands/todo.d.ts +1 -1
- package/dist/cli/commands/todo.js +20 -13
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +388 -161
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/did-you-mean.d.ts +1 -1
- package/dist/cli/excess-args.d.ts +15 -0
- package/dist/cli/excess-args.js +51 -0
- package/dist/cli/excess-args.js.map +1 -0
- package/dist/cli/glyphs.d.ts +55 -2
- package/dist/cli/glyphs.js +114 -21
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.d.ts +54 -0
- package/dist/cli/help.js +405 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/main.js +64 -26
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/move-hint.d.ts +45 -0
- package/dist/cli/move-hint.js +196 -0
- package/dist/cli/move-hint.js.map +1 -0
- package/dist/cli/period.d.ts +9 -8
- package/dist/cli/period.js +56 -30
- package/dist/cli/period.js.map +1 -1
- package/dist/cli/read-driver.d.ts +26 -19
- package/dist/cli/read-driver.js +77 -33
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/render.d.ts +92 -28
- package/dist/cli/render.js +333 -103
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/resolve-invocation.d.ts +42 -4
- package/dist/cli/resolve-invocation.js +97 -14
- package/dist/cli/resolve-invocation.js.map +1 -1
- package/dist/cli/skill-check.d.ts +21 -0
- package/dist/cli/skill-check.js +82 -0
- package/dist/cli/skill-check.js.map +1 -0
- package/dist/cli/skill.d.ts +62 -0
- package/dist/cli/skill.js +142 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/cli/tag-filters.d.ts +63 -0
- package/dist/cli/tag-filters.js +59 -0
- package/dist/cli/tag-filters.js.map +1 -0
- package/dist/cli/verb-hint.d.ts +25 -0
- package/dist/cli/verb-hint.js +163 -0
- package/dist/cli/verb-hint.js.map +1 -0
- package/dist/cli/version.d.ts +4 -0
- package/dist/cli/version.js +18 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/width.d.ts +135 -0
- package/dist/cli/width.js +313 -0
- package/dist/cli/width.js.map +1 -0
- package/dist/client.d.ts +160 -24
- package/dist/client.js +132 -19
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +97 -17
- package/dist/contracts.js +44 -1
- package/dist/contracts.js.map +1 -1
- package/dist/db/fingerprint.d.ts +12 -0
- package/dist/db/fingerprint.js +15 -1
- package/dist/db/fingerprint.js.map +1 -1
- package/dist/db/locate.js +1 -1
- package/dist/db/locate.js.map +1 -1
- package/dist/diagnose.d.ts +63 -0
- package/dist/diagnose.js +38 -1
- package/dist/diagnose.js.map +1 -1
- package/dist/index.d.ts +36 -5
- package/dist/index.js +38 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -1
- package/dist/mcp/server.js +1038 -436
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/clock.d.ts +61 -0
- package/dist/model/clock.js +71 -0
- package/dist/model/clock.js.map +1 -0
- package/dist/model/dates.d.ts +26 -3
- package/dist/model/dates.js +84 -3
- package/dist/model/dates.js.map +1 -1
- package/dist/model/entities.d.ts +48 -10
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.d.ts +9 -2
- package/dist/model/mappers.js +32 -9
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/serialize.d.ts +28 -0
- package/dist/model/serialize.js +80 -0
- package/dist/model/serialize.js.map +1 -0
- package/dist/model/when-sugar.d.ts +47 -0
- package/dist/model/when-sugar.js +45 -0
- package/dist/model/when-sugar.js.map +1 -0
- package/dist/read/area-view.d.ts +8 -1
- package/dist/read/area-view.js +55 -17
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/detail.d.ts +1 -1
- package/dist/read/detail.js +11 -4
- package/dist/read/detail.js.map +1 -1
- package/dist/read/filter-contract.d.ts +117 -0
- package/dist/read/filter-contract.js +78 -0
- package/dist/read/filter-contract.js.map +1 -0
- package/dist/read/log-boundary.d.ts +1 -1
- package/dist/read/log-boundary.js +13 -3
- package/dist/read/log-boundary.js.map +1 -1
- package/dist/read/predicates.d.ts +30 -0
- package/dist/read/predicates.js +30 -0
- package/dist/read/predicates.js.map +1 -1
- package/dist/read/project-view.d.ts +12 -1
- package/dist/read/project-view.js +45 -12
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/queries.d.ts +152 -7
- package/dist/read/queries.js +277 -36
- package/dist/read/queries.js.map +1 -1
- package/dist/read/sections.d.ts +51 -0
- package/dist/read/sections.js +37 -0
- package/dist/read/sections.js.map +1 -0
- package/dist/read/sidebar-order.js +2 -1
- package/dist/read/sidebar-order.js.map +1 -1
- package/dist/read/snapshot.d.ts +1 -1
- package/dist/read/snapshot.js +9 -2
- package/dist/read/snapshot.js.map +1 -1
- package/dist/read/tags.d.ts +27 -3
- package/dist/read/tags.js +83 -12
- package/dist/read/tags.js.map +1 -1
- package/dist/read/truncation.d.ts +71 -0
- package/dist/read/{pagination.js → truncation.js} +103 -94
- package/dist/read/truncation.js.map +1 -0
- package/dist/read/views.d.ts +147 -22
- package/dist/read/views.js +282 -80
- package/dist/read/views.js.map +1 -1
- package/dist/surface-copy.d.ts +19 -0
- package/dist/surface-copy.js +32 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/sync-health.d.ts +78 -0
- package/dist/sync-health.js +312 -0
- package/dist/sync-health.js.map +1 -0
- package/dist/write/accessibility-probe.d.ts +12 -0
- package/dist/write/accessibility-probe.js +71 -0
- package/dist/write/accessibility-probe.js.map +1 -0
- package/dist/write/automation-probe.d.ts +8 -1
- package/dist/write/automation-probe.js +16 -1
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/batch.js +5 -2
- package/dist/write/batch.js.map +1 -1
- package/dist/write/capabilities.d.ts +8 -0
- package/dist/write/capabilities.js +13 -6
- package/dist/write/capabilities.js.map +1 -1
- package/dist/write/commands.d.ts +3 -1
- package/dist/write/commands.js +602 -49
- package/dist/write/commands.js.map +1 -1
- package/dist/write/edit-checklist.js +3 -2
- package/dist/write/edit-checklist.js.map +1 -1
- package/dist/write/guards.d.ts +2 -7
- package/dist/write/guards.js +87 -6
- package/dist/write/guards.js.map +1 -1
- package/dist/write/heading.js +2 -0
- package/dist/write/heading.js.map +1 -1
- package/dist/write/lock.d.ts +40 -2
- package/dist/write/lock.js +91 -14
- package/dist/write/lock.js.map +1 -1
- package/dist/write/make-repeating-project.d.ts +4 -0
- package/dist/write/make-repeating-project.js +253 -0
- package/dist/write/make-repeating-project.js.map +1 -0
- package/dist/write/operations.d.ts +145 -1
- package/dist/write/operations.js +48 -0
- package/dist/write/operations.js.map +1 -1
- package/dist/write/pipeline.d.ts +73 -2
- package/dist/write/pipeline.js +218 -43
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/planner.js +8 -1
- package/dist/write/planner.js.map +1 -1
- package/dist/write/pre-state.d.ts +105 -3
- package/dist/write/pre-state.js +144 -3
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/recurrence-rule-blob.d.ts +65 -0
- package/dist/write/recurrence-rule-blob.js +150 -0
- package/dist/write/recurrence-rule-blob.js.map +1 -0
- package/dist/write/reopen.js +3 -2
- package/dist/write/reopen.js.map +1 -1
- package/dist/write/reorder.js +27 -17
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/repeat-rule.d.ts +22 -0
- package/dist/write/repeat-rule.js +258 -0
- package/dist/write/repeat-rule.js.map +1 -0
- package/dist/write/reversibility.js +49 -0
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/tag-refs.d.ts +47 -0
- package/dist/write/tag-refs.js +126 -0
- package/dist/write/tag-refs.js.map +1 -0
- package/dist/write/undo.d.ts +74 -5
- package/dist/write/undo.js +493 -80
- package/dist/write/undo.js.map +1 -1
- package/dist/write/vectors/registry.d.ts +15 -1
- package/dist/write/vectors/registry.js +65 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/simulator.d.ts +44 -0
- package/dist/write/vectors/simulator.js +1136 -0
- package/dist/write/vectors/simulator.js.map +1 -0
- package/dist/write/vectors/types.d.ts +154 -3
- package/dist/write/vectors/ui-certification.d.ts +54 -0
- package/dist/write/vectors/ui-certification.js +43 -0
- package/dist/write/vectors/ui-certification.js.map +1 -0
- package/dist/write/vectors/ui-drag.d.ts +188 -0
- package/dist/write/vectors/ui-drag.js +1095 -0
- package/dist/write/vectors/ui-drag.js.map +1 -0
- package/dist/write/vectors/ui-recipes.d.ts +83 -0
- package/dist/write/vectors/ui-recipes.js +610 -0
- package/dist/write/vectors/ui-recipes.js.map +1 -0
- package/dist/write/vectors/ui.d.ts +152 -0
- package/dist/write/vectors/ui.js +704 -0
- package/dist/write/vectors/ui.js.map +1 -0
- package/dist/write/verify/delta.d.ts +141 -4
- package/dist/write/verify/delta.js +199 -21
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.d.ts +7 -1
- package/dist/write/verify/poller.js +21 -1
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +18 -3
- package/skills/things-cli/SKILL.md +53 -0
- package/skills/things-cli/references/contracts.md +41 -0
- package/skills/things-cli/references/gui.md +11 -0
- package/skills/things-cli/references/model.md +51 -0
- package/dist/cli/exit-codes.d.ts +0 -26
- package/dist/cli/exit-codes.js +0 -26
- package/dist/cli/exit-codes.js.map +0 -1
- package/dist/cli/output.d.ts +0 -42
- package/dist/cli/output.js +0 -16
- package/dist/cli/output.js.map +0 -1
- package/dist/read/pagination.d.ts +0 -104
- package/dist/read/pagination.js.map +0 -1
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { normalizeNameKey, stripThingsUri } from "../read/queries.js";
|
|
2
|
+
function allTags(db) {
|
|
3
|
+
return db.prepare("SELECT uuid, title, parent FROM TMTag").all();
|
|
4
|
+
}
|
|
5
|
+
/** Dedup key for a per-parent planned title (parent title + title). */
|
|
6
|
+
function planKey(parentTitle, title) {
|
|
7
|
+
return `${parentTitle ?? ""}${title}`;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Title-match tiers within a candidate row set: exact -> case-insensitive ->
|
|
11
|
+
* normalized (dash/space-forgiving). Returns the rows of the FIRST tier that
|
|
12
|
+
* matches at all.
|
|
13
|
+
*/
|
|
14
|
+
function titleMatches(rows, title) {
|
|
15
|
+
const exact = rows.filter((r) => r.title === title);
|
|
16
|
+
if (exact.length > 0)
|
|
17
|
+
return exact;
|
|
18
|
+
const lower = title.toLowerCase();
|
|
19
|
+
const ci = rows.filter((r) => r.title.toLowerCase() === lower);
|
|
20
|
+
if (ci.length > 0)
|
|
21
|
+
return ci;
|
|
22
|
+
const key = normalizeNameKey(title);
|
|
23
|
+
if (key === "")
|
|
24
|
+
return [];
|
|
25
|
+
return rows.filter((r) => normalizeNameKey(r.title) === key);
|
|
26
|
+
}
|
|
27
|
+
function resolveOne(rows, refRaw) {
|
|
28
|
+
const ref = stripThingsUri(refRaw);
|
|
29
|
+
// Literal title (literal-over-path: this matches `sl/ash` as a whole). A name
|
|
30
|
+
// matching ≥1 tag is "known" — pass the NAME through; the app resolves it.
|
|
31
|
+
const literal = titleMatches(rows, ref);
|
|
32
|
+
if (literal.length >= 1)
|
|
33
|
+
return { kind: "title", title: literal[0].title };
|
|
34
|
+
// Path-qualified `parent/child` — resolve the chain from the root. Duplicate
|
|
35
|
+
// names never refuse: descend into the first match at each level.
|
|
36
|
+
if (ref.includes("/")) {
|
|
37
|
+
const segs = ref.split("/").map((s) => s.trim());
|
|
38
|
+
if (segs.some((s) => s === ""))
|
|
39
|
+
return { kind: "missing" };
|
|
40
|
+
let scope = rows.filter((r) => r.parent === null);
|
|
41
|
+
let leaf = null;
|
|
42
|
+
for (const seg of segs) {
|
|
43
|
+
const hits = titleMatches(scope, seg);
|
|
44
|
+
if (hits.length === 0)
|
|
45
|
+
return { kind: "missing" };
|
|
46
|
+
leaf = hits[0];
|
|
47
|
+
scope = rows.filter((r) => r.parent === leaf.uuid);
|
|
48
|
+
}
|
|
49
|
+
if (leaf !== null)
|
|
50
|
+
return { kind: "title", title: leaf.title };
|
|
51
|
+
}
|
|
52
|
+
return { kind: "missing" };
|
|
53
|
+
}
|
|
54
|
+
export function resolveTagRefs(db, refs) {
|
|
55
|
+
const rows = allTags(db);
|
|
56
|
+
const titles = [];
|
|
57
|
+
const seen = new Set();
|
|
58
|
+
const missing = [];
|
|
59
|
+
for (const ref of refs) {
|
|
60
|
+
const r = resolveOne(rows, ref);
|
|
61
|
+
if (r.kind === "title") {
|
|
62
|
+
if (!seen.has(r.title)) {
|
|
63
|
+
seen.add(r.title);
|
|
64
|
+
titles.push(r.title);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
missing.push(ref);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return { titles, missing };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Ordered `make new tag` steps to satisfy `--create-tags`: only the tags that
|
|
75
|
+
* are genuinely MISSING, with mkdir-p intermediates for a `parent/child` path
|
|
76
|
+
* (parents first so each child's parent resolves). A ref that already resolves
|
|
77
|
+
* yields no step (idempotent — the TAGW1-c coalesce also makes re-creation a
|
|
78
|
+
* no-op).
|
|
79
|
+
*/
|
|
80
|
+
export function planTagCreation(db, refs) {
|
|
81
|
+
const rows = allTags(db);
|
|
82
|
+
const steps = [];
|
|
83
|
+
// Titles known to exist OR already planned this call, per hierarchy level,
|
|
84
|
+
// so a repeated segment across refs is planned once.
|
|
85
|
+
const planned = new Set();
|
|
86
|
+
for (const refRaw of refs) {
|
|
87
|
+
const ref = stripThingsUri(refRaw);
|
|
88
|
+
if (resolveOne(rows, ref).kind === "title")
|
|
89
|
+
continue;
|
|
90
|
+
if (ref.includes("/")) {
|
|
91
|
+
const segs = ref.split("/").map((s) => s.trim());
|
|
92
|
+
if (segs.some((s) => s === ""))
|
|
93
|
+
continue;
|
|
94
|
+
let scope = rows.filter((r) => r.parent === null);
|
|
95
|
+
let parentTitle;
|
|
96
|
+
for (const seg of segs) {
|
|
97
|
+
const hits = titleMatches(scope, seg);
|
|
98
|
+
if (hits.length >= 1) {
|
|
99
|
+
const hit = hits[0];
|
|
100
|
+
parentTitle = hit.title;
|
|
101
|
+
scope = rows.filter((r) => r.parent === hit.uuid);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Missing -> plan it and descend into a now-empty scope so the
|
|
105
|
+
// remaining segments are all created too.
|
|
106
|
+
const k = planKey(parentTitle, seg);
|
|
107
|
+
if (!planned.has(k)) {
|
|
108
|
+
planned.add(k);
|
|
109
|
+
steps.push(parentTitle === undefined ? { title: seg } : { title: seg, parent: parentTitle });
|
|
110
|
+
}
|
|
111
|
+
parentTitle = seg;
|
|
112
|
+
scope = [];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const k = planKey(undefined, ref);
|
|
118
|
+
if (!planned.has(k)) {
|
|
119
|
+
planned.add(k);
|
|
120
|
+
steps.push({ title: ref });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return steps;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=tag-refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag-refs.js","sourceRoot":"","sources":["../../src/write/tag-refs.ts"],"names":[],"mappings":"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"}
|
package/dist/write/undo.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AuditRecord } from "../audit/schema.ts";
|
|
2
2
|
import type { AnyTask } from "../model/entities.ts";
|
|
3
|
-
import type
|
|
3
|
+
import { type OperationKind } from "./operations.ts";
|
|
4
4
|
import { type MutationResult, type WriteDeps } from "./pipeline.ts";
|
|
5
5
|
import { type ReorderResult } from "./reorder.ts";
|
|
6
6
|
export interface UndoStep {
|
|
@@ -21,6 +21,18 @@ export interface UndoStep {
|
|
|
21
21
|
detail: string;
|
|
22
22
|
remediation: string;
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* STRUCTURAL axes this step overwrites (getField paths into the decoded
|
|
26
|
+
* target: `status`, `trashed`, `project`/`project.uuid`, `area`/`area.uuid`,
|
|
27
|
+
* `heading.uuid`, `start`/`startDate`/`todaySection`). Before executing,
|
|
28
|
+
* `checkStepPrecondition` verifies the target's CURRENT value on each still
|
|
29
|
+
* equals the recorded `observed` after-value — an out-of-band move/status/
|
|
30
|
+
* schedule change already there blocks rather than being clobbered. Set only
|
|
31
|
+
* for the PRIMARY-target step and only for axes whose after-state `observed`
|
|
32
|
+
* captured (fields absent from `observed` are skipped). Content fields stay
|
|
33
|
+
* on the separate CLOBBER_FIELDS path; the two are checked together.
|
|
34
|
+
*/
|
|
35
|
+
guardFields?: string[];
|
|
24
36
|
};
|
|
25
37
|
}
|
|
26
38
|
export interface UndoPlan {
|
|
@@ -30,6 +42,7 @@ export interface UndoPlan {
|
|
|
30
42
|
op: string;
|
|
31
43
|
uuid: string | null;
|
|
32
44
|
actor: string;
|
|
45
|
+
token: string;
|
|
33
46
|
};
|
|
34
47
|
kind: "invertible" | "irreversible";
|
|
35
48
|
steps: UndoStep[];
|
|
@@ -47,19 +60,75 @@ export interface UndoItemResult {
|
|
|
47
60
|
export interface UndoOptions {
|
|
48
61
|
/** How many trailing mutations to undo (default 1). */
|
|
49
62
|
last?: number;
|
|
63
|
+
/**
|
|
64
|
+
* SELECTION filter — undo only mutations recorded under this actor. An exact
|
|
65
|
+
* actor string (e.g. "mcp:claude-code", "mike") or "*" for all actors.
|
|
66
|
+
* Undefined means all (the CLI's global default); the MCP surface defaults it
|
|
67
|
+
* to the connecting client's own derived actor (`mcp:<client>`).
|
|
68
|
+
*
|
|
69
|
+
* Matching is EXACT: `by: "mike"` selects records whose actor is exactly
|
|
70
|
+
* "mike" and never an undo record (`undo:mike`) — inverse mutations are their
|
|
71
|
+
* own actor and are never themselves undo targets. NOT the same as `actor`
|
|
72
|
+
* below, which names who the NEW inverse mutation is attributed to.
|
|
73
|
+
*/
|
|
74
|
+
by?: string;
|
|
75
|
+
/**
|
|
76
|
+
* EXACT selection by undo token (from a mutation result's `undoToken`).
|
|
77
|
+
* Undoes precisely that one record, immune to interleaving. Mutually
|
|
78
|
+
* exclusive with `last`/`by` (enforced at the call surfaces).
|
|
79
|
+
*/
|
|
80
|
+
txn?: string;
|
|
50
81
|
dryRun?: boolean;
|
|
51
82
|
/** Required for inverses that delete areas/tags permanently. */
|
|
52
83
|
dangerouslyPermanent?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Proceed even when the target changed OUTSIDE things-api since the recorded
|
|
86
|
+
* change — bypasses the precondition guard uniformly (both the content-field
|
|
87
|
+
* and the structural axis checks), overwriting whatever an out-of-band edit
|
|
88
|
+
* left. Does NOT bypass the checklist item-level refusal (a separate plan-time
|
|
89
|
+
* mechanism with no faithful forced inverse). "The world moved, overwrite
|
|
90
|
+
* anyway."
|
|
91
|
+
*/
|
|
92
|
+
acknowledgeOutOfBandChanges?: boolean;
|
|
53
93
|
verifyTimeoutMs?: number;
|
|
94
|
+
/** Author RECORDED for the inverse mutation (as `undo:<actor>`); see `by`. */
|
|
54
95
|
actor?: string;
|
|
55
96
|
}
|
|
56
97
|
/** Parse every audit record from the monthly JSONL files, oldest first. */
|
|
57
98
|
export declare function readAuditRecords(dir: string): AuditRecord[];
|
|
99
|
+
export interface UndoSelector {
|
|
100
|
+
/** How many trailing targets to take (default 1); ignored when `txn` is set. */
|
|
101
|
+
last?: number;
|
|
102
|
+
/** Actor filter: exact actor string, or "*"/undefined for all. */
|
|
103
|
+
by?: string;
|
|
104
|
+
/** Exact undo-token selection: returns the single matching target (or none). */
|
|
105
|
+
txn?: string;
|
|
106
|
+
}
|
|
107
|
+
export interface AuditIntegrity {
|
|
108
|
+
/** Intent records with no later matching final record — a write MAY have landed unrecorded. */
|
|
109
|
+
orphanedIntents: number;
|
|
110
|
+
/** Newest orphaned intent's timestamp (ISO), or null when there are none. */
|
|
111
|
+
newestOrphanIntent: string | null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Detect crashed writes: INTENT records left without a matching final record.
|
|
115
|
+
* A mutation writes an intent immediately before touching the app and a final
|
|
116
|
+
* record after read-after-write; the two share ts+op+actor+host. An intent
|
|
117
|
+
* with no non-intent sibling on that key means the process died mid-write — the
|
|
118
|
+
* app may have applied the change, but no result was recorded, so the change is
|
|
119
|
+
* invisible to undo. Surfaced by `things doctor` so the user can reconcile.
|
|
120
|
+
*/
|
|
121
|
+
export declare function scanAuditIntegrity(records: AuditRecord[]): AuditIntegrity;
|
|
58
122
|
/**
|
|
59
|
-
* The
|
|
60
|
-
*
|
|
123
|
+
* The undoable targets to unwind, NEWEST FIRST (undo unwinds a stack).
|
|
124
|
+
*
|
|
125
|
+
* - `txn` wins when present: the ONE record whose undo token matches (or an
|
|
126
|
+
* empty array — the caller distinguishes not-found from already-undone).
|
|
127
|
+
* - otherwise the last `last` records, optionally narrowed to actor `by`
|
|
128
|
+
* (exact match; "*"/undefined = every actor). `by` NEVER matches an
|
|
129
|
+
* `undo:<actor>` record — those are excluded from undoability entirely.
|
|
61
130
|
*/
|
|
62
|
-
export declare function selectUndoTargets(records: AuditRecord[],
|
|
131
|
+
export declare function selectUndoTargets(records: AuditRecord[], selector?: UndoSelector): AuditRecord[];
|
|
63
132
|
/**
|
|
64
133
|
* Operations with NO validated inverse surface — reported irreversible on
|
|
65
134
|
* sight, before any per-record analysis. The reversibility matrix cross-checks
|