things-api 0.8.0 → 0.10.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 +31 -11
- 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/commands/area.d.ts +34 -2
- package/dist/cli/commands/area.js +140 -28
- 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/mcp.js +23 -4
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/project.d.ts +23 -1
- package/dist/cli/commands/project.js +82 -15
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/reads.d.ts +6 -125
- package/dist/cli/commands/reads.js +649 -657
- 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 +2 -3
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/show.d.ts +1 -1
- package/dist/cli/commands/show.js +169 -18
- package/dist/cli/commands/show.js.map +1 -1
- package/dist/cli/commands/snapshot.js +1 -1
- package/dist/cli/commands/snapshot.js.map +1 -1
- package/dist/cli/commands/todo.d.ts +1 -1
- package/dist/cli/commands/todo.js +21 -9
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +378 -148
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/did-you-mean.d.ts +29 -0
- package/dist/cli/did-you-mean.js +53 -0
- package/dist/cli/did-you-mean.js.map +1 -0
- 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 +67 -7
- package/dist/cli/glyphs.js +202 -19
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.d.ts +54 -0
- package/dist/cli/help.js +355 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/main.js +36 -21
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/period.d.ts +39 -0
- package/dist/cli/period.js +141 -0
- package/dist/cli/period.js.map +1 -0
- package/dist/cli/read-driver.d.ts +83 -0
- package/dist/cli/read-driver.js +215 -0
- package/dist/cli/read-driver.js.map +1 -0
- package/dist/cli/render.d.ts +246 -0
- package/dist/cli/render.js +806 -0
- package/dist/cli/render.js.map +1 -0
- package/dist/cli/resolve-invocation.d.ts +116 -0
- package/dist/cli/resolve-invocation.js +261 -0
- package/dist/cli/resolve-invocation.js.map +1 -0
- package/dist/cli/shell-quote.d.ts +9 -0
- package/dist/cli/shell-quote.js +12 -0
- package/dist/cli/shell-quote.js.map +1 -0
- package/dist/cli/tag-filters.d.ts +59 -0
- package/dist/cli/tag-filters.js +57 -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 +138 -0
- package/dist/cli/verb-hint.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 +146 -24
- package/dist/client.js +106 -16
- 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 +136 -1
- 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 +30 -4
- package/dist/index.js +35 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -1
- package/dist/mcp/server.js +850 -128
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/entities.d.ts +40 -7
- package/dist/model/entities.js.map +1 -1
- package/dist/model/mappers.d.ts +7 -0
- package/dist/model/mappers.js +20 -3
- package/dist/model/mappers.js.map +1 -1
- package/dist/model/occurrences.d.ts +6 -1
- package/dist/model/occurrences.js +9 -5
- package/dist/model/occurrences.js.map +1 -1
- package/dist/model/recurrence.d.ts +17 -8
- package/dist/model/recurrence.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 +49 -13
- package/dist/read/area-view.js.map +1 -1
- package/dist/read/caps.d.ts +14 -0
- package/dist/read/caps.js +21 -0
- package/dist/read/caps.js.map +1 -0
- 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 +9 -4
- package/dist/read/log-boundary.js.map +1 -1
- package/dist/read/predicates.d.ts +61 -0
- package/dist/read/predicates.js +78 -0
- package/dist/read/predicates.js.map +1 -0
- package/dist/read/project-view.d.ts +12 -1
- package/dist/read/project-view.js +39 -8
- package/dist/read/project-view.js.map +1 -1
- package/dist/read/queries.d.ts +156 -8
- package/dist/read/queries.js +261 -38
- package/dist/read/queries.js.map +1 -1
- package/dist/read/search-rank.d.ts +36 -0
- package/dist/read/search-rank.js +31 -0
- package/dist/read/search-rank.js.map +1 -0
- 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/show-target.d.ts +13 -4
- package/dist/read/show-target.js +11 -2
- package/dist/read/show-target.js.map +1 -1
- package/dist/read/sidebar-order.d.ts +19 -0
- package/dist/read/sidebar-order.js +93 -0
- package/dist/read/sidebar-order.js.map +1 -0
- 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/truncation.js +217 -0
- package/dist/read/truncation.js.map +1 -0
- package/dist/read/views.d.ts +177 -19
- package/dist/read/views.js +390 -213
- package/dist/read/views.js.map +1 -1
- package/dist/surface-copy.d.ts +42 -0
- package/dist/surface-copy.js +55 -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 +63 -0
- package/dist/write/accessibility-probe.js.map +1 -0
- package/dist/write/automation-probe.d.ts +7 -0
- package/dist/write/automation-probe.js +8 -1
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/batch.js +4 -2
- package/dist/write/batch.js.map +1 -1
- package/dist/write/capabilities.d.ts +8 -0
- package/dist/write/capabilities.js +13 -5
- package/dist/write/capabilities.js.map +1 -1
- package/dist/write/commands.d.ts +2 -0
- package/dist/write/commands.js +562 -48
- 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 +64 -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 +19 -0
- package/dist/write/pipeline.js +109 -26
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +68 -3
- package/dist/write/pre-state.js +102 -3
- package/dist/write/pre-state.js.map +1 -1
- 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 +494 -80
- package/dist/write/undo.js.map +1 -1
- package/dist/write/vectors/registry.d.ts +17 -1
- package/dist/write/vectors/registry.js +18 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/types.d.ts +119 -3
- package/dist/write/vectors/ui-certification.d.ts +48 -0
- package/dist/write/vectors/ui-certification.js +46 -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 +70 -0
- package/dist/write/vectors/ui-recipes.js +558 -0
- package/dist/write/vectors/ui-recipes.js.map +1 -0
- package/dist/write/vectors/ui.d.ts +137 -0
- package/dist/write/vectors/ui.js +656 -0
- package/dist/write/vectors/ui.js.map +1 -0
- package/dist/write/verify/delta.d.ts +31 -3
- package/dist/write/verify/delta.js +22 -6
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.js +1 -0
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +1 -1
- 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/write/lock.d.ts
CHANGED
|
@@ -1,10 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advisory mutation lockfile: serializes mutations across concurrent CLI
|
|
3
|
+
* invocations so create-probe verification is never ambiguous (design §4).
|
|
4
|
+
* Stale locks (dead pid) are stolen; live locks are awaited with backoff.
|
|
5
|
+
*
|
|
6
|
+
* The steal is atomic: a stealer `rename`s the stale lockfile to a private
|
|
7
|
+
* temp name (rename succeeds for exactly one racer; every other racer gets
|
|
8
|
+
* ENOENT and falls back to the wait/retry loop), then re-reads the renamed
|
|
9
|
+
* file to confirm the holder is still dead before discarding it. This closes
|
|
10
|
+
* the TOCTOU window an unconditional unlink+recreate would leave open, where
|
|
11
|
+
* two processes could both observe a dead holder and both end up believing
|
|
12
|
+
* they hold the lock.
|
|
13
|
+
*/
|
|
14
|
+
import { mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
1
15
|
export declare class MutationLockError extends Error {
|
|
2
16
|
constructor(message: string);
|
|
3
17
|
}
|
|
4
18
|
export interface MutationLock {
|
|
5
19
|
release(): void;
|
|
6
20
|
}
|
|
7
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Injectable filesystem + environment seam. Production uses the real node:fs
|
|
23
|
+
* calls; unit tests substitute this to drive the concurrent steal paths
|
|
24
|
+
* deterministically. Not part of the public contract — callers pass only the
|
|
25
|
+
* documented options below.
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export interface LockDeps {
|
|
29
|
+
mkdirSync: typeof mkdirSync;
|
|
30
|
+
readFileSync: typeof readFileSync;
|
|
31
|
+
writeFileSync: typeof writeFileSync;
|
|
32
|
+
renameSync: typeof renameSync;
|
|
33
|
+
unlinkSync: typeof unlinkSync;
|
|
34
|
+
pidAlive: (pid: number) => boolean;
|
|
35
|
+
pid: number;
|
|
36
|
+
now: () => string;
|
|
37
|
+
uniqueSuffix: () => string;
|
|
38
|
+
/** Test-only barrier, awaited after a dead holder is observed and before
|
|
39
|
+
* the steal `rename`. Inert (absent) in production. */
|
|
40
|
+
onBeforeSteal?: () => Promise<void> | void;
|
|
41
|
+
}
|
|
42
|
+
export interface AcquireMutationLockOptions {
|
|
8
43
|
waitMs?: number;
|
|
9
44
|
sleep?: (ms: number) => Promise<void>;
|
|
10
|
-
}
|
|
45
|
+
/** @internal test seam — see {@link LockDeps}. */
|
|
46
|
+
deps?: LockDeps;
|
|
47
|
+
}
|
|
48
|
+
export declare function acquireMutationLock(path: string, options?: AcquireMutationLockOptions): Promise<MutationLock>;
|
package/dist/write/lock.js
CHANGED
|
@@ -2,8 +2,16 @@
|
|
|
2
2
|
* Advisory mutation lockfile: serializes mutations across concurrent CLI
|
|
3
3
|
* invocations so create-probe verification is never ambiguous (design §4).
|
|
4
4
|
* Stale locks (dead pid) are stolen; live locks are awaited with backoff.
|
|
5
|
+
*
|
|
6
|
+
* The steal is atomic: a stealer `rename`s the stale lockfile to a private
|
|
7
|
+
* temp name (rename succeeds for exactly one racer; every other racer gets
|
|
8
|
+
* ENOENT and falls back to the wait/retry loop), then re-reads the renamed
|
|
9
|
+
* file to confirm the holder is still dead before discarding it. This closes
|
|
10
|
+
* the TOCTOU window an unconditional unlink+recreate would leave open, where
|
|
11
|
+
* two processes could both observe a dead holder and both end up believing
|
|
12
|
+
* they hold the lock.
|
|
5
13
|
*/
|
|
6
|
-
import { mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
7
15
|
import { dirname } from "node:path";
|
|
8
16
|
export class MutationLockError extends Error {
|
|
9
17
|
constructor(message) {
|
|
@@ -20,19 +28,37 @@ function pidAlive(pid) {
|
|
|
20
28
|
return false;
|
|
21
29
|
}
|
|
22
30
|
}
|
|
31
|
+
let stealCounter = 0;
|
|
32
|
+
function realDeps() {
|
|
33
|
+
return {
|
|
34
|
+
mkdirSync,
|
|
35
|
+
readFileSync,
|
|
36
|
+
writeFileSync,
|
|
37
|
+
renameSync,
|
|
38
|
+
unlinkSync,
|
|
39
|
+
pidAlive,
|
|
40
|
+
pid: process.pid,
|
|
41
|
+
now: () => new Date().toISOString(),
|
|
42
|
+
uniqueSuffix: () => `${Date.now().toString(36)}-${(stealCounter++).toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function errCode(err) {
|
|
46
|
+
return err.code;
|
|
47
|
+
}
|
|
23
48
|
export async function acquireMutationLock(path, options = {}) {
|
|
24
49
|
const waitMs = options.waitMs ?? 30_000;
|
|
25
50
|
const sleep = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
51
|
+
const deps = options.deps ?? realDeps();
|
|
26
52
|
const deadline = Date.now() + waitMs;
|
|
27
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
53
|
+
deps.mkdirSync(dirname(path), { recursive: true });
|
|
28
54
|
for (;;) {
|
|
29
55
|
try {
|
|
30
|
-
const payload = { pid:
|
|
31
|
-
writeFileSync(path, JSON.stringify(payload), { flag: "wx" });
|
|
56
|
+
const payload = { pid: deps.pid, ts: deps.now() };
|
|
57
|
+
deps.writeFileSync(path, JSON.stringify(payload), { flag: "wx" });
|
|
32
58
|
return {
|
|
33
59
|
release() {
|
|
34
60
|
try {
|
|
35
|
-
unlinkSync(path);
|
|
61
|
+
deps.unlinkSync(path);
|
|
36
62
|
}
|
|
37
63
|
catch {
|
|
38
64
|
// already gone — fine
|
|
@@ -41,30 +67,81 @@ export async function acquireMutationLock(path, options = {}) {
|
|
|
41
67
|
};
|
|
42
68
|
}
|
|
43
69
|
catch (err) {
|
|
44
|
-
if (err
|
|
70
|
+
if (errCode(err) !== "EEXIST")
|
|
45
71
|
throw err;
|
|
46
72
|
let holder = null;
|
|
47
73
|
try {
|
|
48
|
-
holder = JSON.parse(readFileSync(path, "utf8"));
|
|
74
|
+
holder = JSON.parse(deps.readFileSync(path, "utf8"));
|
|
49
75
|
}
|
|
50
76
|
catch {
|
|
51
77
|
holder = null; // torn write — treat as stale
|
|
52
78
|
}
|
|
53
|
-
if (holder === null || !pidAlive(holder.pid)) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// raced another steal — loop and retry
|
|
59
|
-
}
|
|
79
|
+
if (holder === null || !deps.pidAlive(holder.pid)) {
|
|
80
|
+
await stealStale(path, deps);
|
|
81
|
+
// Whatever the steal outcome, re-loop: an empty slot lets us create a
|
|
82
|
+
// fresh lock via `wx`; a slot re-taken by another process sends us
|
|
83
|
+
// back through the holder check (and, for a live holder, the wait).
|
|
60
84
|
continue;
|
|
61
85
|
}
|
|
62
86
|
if (Date.now() >= deadline) {
|
|
63
87
|
throw new MutationLockError(`another mutation is in progress (pid ${holder.pid} since ${holder.ts}); ` +
|
|
64
88
|
`waited ${waitMs}ms for ${path}`);
|
|
65
89
|
}
|
|
90
|
+
// lock-acquisition retries are inherently sequential polling against the same lockfile
|
|
66
91
|
await sleep(150);
|
|
67
92
|
}
|
|
68
93
|
}
|
|
69
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Atomically claim and discard a lockfile whose holder appears dead. Exactly
|
|
97
|
+
* one concurrent stealer wins the `rename`; the rest get ENOENT and return to
|
|
98
|
+
* retry. After winning, the renamed file is re-read: if a live lock had been
|
|
99
|
+
* installed at `path` in the meantime (so the file we just moved is actually
|
|
100
|
+
* live), it is restored to `path` — via `wx`, so a lock re-created by a third
|
|
101
|
+
* process is never clobbered — and we back off instead of stealing it.
|
|
102
|
+
*/
|
|
103
|
+
async function stealStale(path, deps) {
|
|
104
|
+
const temp = `${path}.steal-${deps.pid}-${deps.uniqueSuffix()}`;
|
|
105
|
+
if (deps.onBeforeSteal)
|
|
106
|
+
await deps.onBeforeSteal();
|
|
107
|
+
try {
|
|
108
|
+
deps.renameSync(path, temp);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
if (errCode(err) === "ENOENT")
|
|
112
|
+
return; // lost the rename race — retry
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
// We won the rename and now own `temp`. Confirm the holder is still dead.
|
|
116
|
+
let stolen = null;
|
|
117
|
+
try {
|
|
118
|
+
stolen = JSON.parse(deps.readFileSync(temp, "utf8"));
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
stolen = null; // torn write — genuinely stale
|
|
122
|
+
}
|
|
123
|
+
if (stolen !== null && deps.pidAlive(stolen.pid)) {
|
|
124
|
+
// A live lock slipped in between our read and our rename: this file is not
|
|
125
|
+
// stale after all. Put it back for its holder (only if the slot is free)
|
|
126
|
+
// and back off.
|
|
127
|
+
try {
|
|
128
|
+
deps.writeFileSync(path, JSON.stringify(stolen), { flag: "wx" });
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// slot already re-taken — leave the newcomer's lock intact
|
|
132
|
+
}
|
|
133
|
+
tryUnlink(deps, temp);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Confirmed stale — drop it so the next loop turn can create a fresh lock.
|
|
137
|
+
tryUnlink(deps, temp);
|
|
138
|
+
}
|
|
139
|
+
function tryUnlink(deps, path) {
|
|
140
|
+
try {
|
|
141
|
+
deps.unlinkSync(path);
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// already gone — fine
|
|
145
|
+
}
|
|
146
|
+
}
|
|
70
147
|
//# sourceMappingURL=lock.js.map
|
package/dist/write/lock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/write/lock.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/write/lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ProjectCreateRepeatingParams, RepeatRuleParams } from "./operations.ts";
|
|
2
|
+
import { type MutationResult, type WriteDeps, type WriteOptions } from "./pipeline.ts";
|
|
3
|
+
export declare function runMakeRepeatingProject(deps: WriteDeps, params: RepeatRuleParams, options?: WriteOptions): Promise<MutationResult>;
|
|
4
|
+
export declare function runCreateRepeatingProject(deps: WriteDeps, params: ProjectCreateRepeatingParams, options?: WriteOptions): Promise<MutationResult>;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { resolveProjectWriteTarget } from "../read/queries.js";
|
|
2
|
+
import { assertRepeatRule } from "./commands.js";
|
|
3
|
+
import { classifyProjectRepeat, loadTarget } from "./pre-state.js";
|
|
4
|
+
import { fingerprintLabel, runMutation, } from "./pipeline.js";
|
|
5
|
+
/** The two-key GUI-drive block, shared by both orchestrators (mirrors H-UI-DRIVE). */
|
|
6
|
+
function blockedUiDrive(op) {
|
|
7
|
+
return {
|
|
8
|
+
kind: "blocked",
|
|
9
|
+
op,
|
|
10
|
+
reason: "hazard",
|
|
11
|
+
hazard: "H-UI-DRIVE",
|
|
12
|
+
detail: "this operation drives the local Things app through the Accessibility API — the project " +
|
|
13
|
+
"row-selection, menu press, and Repeat dialog all run through the Accessibility tree",
|
|
14
|
+
remediation: "pass dangerouslyDriveGui (--dangerously-drive-gui) to proceed; the vector also requires " +
|
|
15
|
+
"`things config set ui-enabled true` and Accessibility granted to this process (see docs/setup.md)",
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Translate a refusal taxonomy into a blocked result (the guard's user-facing shape). */
|
|
19
|
+
function blockedRefusal(tax) {
|
|
20
|
+
if (tax.refusal === "not-a-project") {
|
|
21
|
+
return {
|
|
22
|
+
kind: "blocked",
|
|
23
|
+
op: "project.make-repeating",
|
|
24
|
+
reason: "hazard",
|
|
25
|
+
hazard: "H-UNKNOWN-DESTINATION",
|
|
26
|
+
detail: `${tax.detail} — project.make-repeating needs an existing project`,
|
|
27
|
+
remediation: "verify the uuid with `things projects`, or use `things todo make-repeating` for a to-do",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const remediation = tax.refusal === "ambiguous-row"
|
|
31
|
+
? "rename one of the same-titled projects so the target's row is unambiguous"
|
|
32
|
+
: tax.refusal === "already-repeating"
|
|
33
|
+
? "the project already repeats — use `things project reschedule-repeat` to change its rule"
|
|
34
|
+
: "target an open, un-trashed project";
|
|
35
|
+
return {
|
|
36
|
+
kind: "blocked",
|
|
37
|
+
op: "project.make-repeating",
|
|
38
|
+
reason: "hazard",
|
|
39
|
+
hazard: "H-PROJECT-REPEAT",
|
|
40
|
+
detail: tax.detail,
|
|
41
|
+
remediation,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** A per-run txn id (matches the pipeline's leg/summary grouping). */
|
|
45
|
+
function newTxnId(now) {
|
|
46
|
+
return `txn-${now.getTime().toString(36)}-${process.pid.toString(36)}`;
|
|
47
|
+
}
|
|
48
|
+
/** Forward the caller's audit/timeout knobs onto a delegated leg. */
|
|
49
|
+
function legOptions(base, txn, vector) {
|
|
50
|
+
const out = { txn };
|
|
51
|
+
if (vector !== undefined)
|
|
52
|
+
out.vector = vector;
|
|
53
|
+
if (base.actor !== undefined)
|
|
54
|
+
out.actor = base.actor;
|
|
55
|
+
if (base.verifyTimeoutMs !== undefined)
|
|
56
|
+
out.verifyTimeoutMs = base.verifyTimeoutMs;
|
|
57
|
+
if (base.maxDisruption !== undefined)
|
|
58
|
+
out.maxDisruption = base.maxDisruption;
|
|
59
|
+
if (base.dangerouslyDriveGui !== undefined)
|
|
60
|
+
out.dangerouslyDriveGui = base.dangerouslyDriveGui;
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
export async function runMakeRepeatingProject(deps, params, options = {}) {
|
|
64
|
+
const uuid = resolveProjectWriteTarget(deps.db, params.uuid);
|
|
65
|
+
// Validate the rule BEFORE any coercion — a bad rule must never leave a
|
|
66
|
+
// coerced-to-someday project stranded.
|
|
67
|
+
assertRepeatRule(params);
|
|
68
|
+
const target = loadTarget(deps.db, uuid);
|
|
69
|
+
const tax = classifyProjectRepeat(deps.db, target);
|
|
70
|
+
if (tax.kind === "refuse")
|
|
71
|
+
return blockedRefusal(tax);
|
|
72
|
+
// The GUI-drive ack gates the coercion decision too: block before touching
|
|
73
|
+
// anything if it is missing (the delegated drive would block anyway, but the
|
|
74
|
+
// anytime path must not coerce first only to be blocked at the drive).
|
|
75
|
+
if (options.dangerouslyDriveGui !== true && options.dryRun !== true) {
|
|
76
|
+
return blockedUiDrive("project.make-repeating");
|
|
77
|
+
}
|
|
78
|
+
const driveParams = {
|
|
79
|
+
uuid,
|
|
80
|
+
frequency: params.frequency,
|
|
81
|
+
interval: params.interval,
|
|
82
|
+
...(params.afterCompletion !== undefined && { afterCompletion: params.afterCompletion }),
|
|
83
|
+
...(params.weekdays !== undefined && { weekdays: params.weekdays }),
|
|
84
|
+
...(params.monthly !== undefined && { monthly: params.monthly }),
|
|
85
|
+
...(params.yearly !== undefined && { yearly: params.yearly }),
|
|
86
|
+
...(params.ends !== undefined && { ends: params.ends }),
|
|
87
|
+
...(params.reminder !== undefined && { reminder: params.reminder }),
|
|
88
|
+
...(params.deadline !== undefined && { deadline: params.deadline }),
|
|
89
|
+
...(params.startDaysEarlier !== undefined && { startDaysEarlier: params.startDaysEarlier }),
|
|
90
|
+
};
|
|
91
|
+
if (options.dryRun === true) {
|
|
92
|
+
const coercion = tax.kind === "anytime"
|
|
93
|
+
? `coerce to Someday (update-project?id=${uuid}&when=someday) → verified → `
|
|
94
|
+
: "";
|
|
95
|
+
const view = tax.kind === "area" ? `area ${tax.containerReveal}` : "Someday";
|
|
96
|
+
return {
|
|
97
|
+
kind: "dry-run",
|
|
98
|
+
op: "project.make-repeating",
|
|
99
|
+
plan: {
|
|
100
|
+
op: "project.make-repeating",
|
|
101
|
+
vector: "ui",
|
|
102
|
+
tier: 3,
|
|
103
|
+
invocation: `${coercion}reveal ${view} → select the project row (AXSelectedRows) → Items ▸ Repeat… → ` +
|
|
104
|
+
`frequency=${params.frequency}, interval=${params.interval} → OK`,
|
|
105
|
+
expectedDelta: {
|
|
106
|
+
mode: "create",
|
|
107
|
+
probe: { title: tax.title, type: "project", sinceEpoch: 0 },
|
|
108
|
+
assert: [{ field: "repeating.isTemplate", equals: true }],
|
|
109
|
+
},
|
|
110
|
+
hazardsChecked: ["H-UNKNOWN-DESTINATION", "H-PROJECT-REPEAT", "H-UI-DRIVE"],
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
// area / someday: no coercion — the single pure-AX drive IS the mutation.
|
|
115
|
+
if (tax.kind === "area" || tax.kind === "someday") {
|
|
116
|
+
return runMutation(deps, "project.make-repeating", driveParams, { ...options, vector: "ui" });
|
|
117
|
+
}
|
|
118
|
+
// area-less anytime: coerce to Someday (cleanup-free, UIC4-c/d) then drive,
|
|
119
|
+
// grouped as one txn with a single undoable SUMMARY record.
|
|
120
|
+
const startedAt = deps.now?.() ?? new Date();
|
|
121
|
+
const txnId = newTxnId(startedAt);
|
|
122
|
+
const coerce = await runMutation(deps, "project.update", { uuid, when: "someday" }, legOptions(options, { id: txnId, role: "leg" }, "url-scheme"));
|
|
123
|
+
if (coerce.kind !== "ok") {
|
|
124
|
+
// Nothing was promoted; the coercion itself failed or was blocked — surface it.
|
|
125
|
+
return coerce.kind === "blocked"
|
|
126
|
+
? coerce
|
|
127
|
+
: {
|
|
128
|
+
kind: "verify-failed",
|
|
129
|
+
op: "project.make-repeating",
|
|
130
|
+
reason: coerce.kind === "verify-failed" ? coerce.reason : "mismatch",
|
|
131
|
+
expected: coerce.kind === "verify-failed"
|
|
132
|
+
? coerce.expected
|
|
133
|
+
: { mode: "update", uuid, assert: [] },
|
|
134
|
+
observed: coerce.kind === "verify-failed" ? coerce.observed : null,
|
|
135
|
+
detail: "the Someday coercion (the intermediate step for an area-less Anytime project) failed — " +
|
|
136
|
+
"the project was NOT made repeating and its schedule is unchanged",
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const drive = await runMutation(deps, "project.make-repeating", driveParams, legOptions(options, { id: txnId, role: "leg" }, "ui"));
|
|
140
|
+
if (drive.kind !== "ok") {
|
|
141
|
+
// Non-atomic residue: the project IS now in Someday but was not promoted.
|
|
142
|
+
// make-repeating normalizes start to someday anyway (UIC4-c), so this is not
|
|
143
|
+
// a corruption — just an incomplete op. Report it honestly.
|
|
144
|
+
return drive;
|
|
145
|
+
}
|
|
146
|
+
appendSummary(deps, {
|
|
147
|
+
startedAt,
|
|
148
|
+
uuid: drive.uuid,
|
|
149
|
+
txnId,
|
|
150
|
+
invocation: `make-repeating(project, coerced from anytime) id=${uuid} → template ${drive.uuid ?? "?"}`,
|
|
151
|
+
});
|
|
152
|
+
return { ...drive, ...(drive.warnings !== undefined && { warnings: drive.warnings }) };
|
|
153
|
+
}
|
|
154
|
+
export async function runCreateRepeatingProject(deps, params, options = {}) {
|
|
155
|
+
// create-repeating carries only the base rule vocabulary (the promote can be
|
|
156
|
+
// followed by a reschedule for a richer rule); validate just that.
|
|
157
|
+
assertRepeatRule({ frequency: params.frequency, interval: params.interval });
|
|
158
|
+
// The promote drives the GUI — block before creating anything if the ack is missing.
|
|
159
|
+
if (options.dangerouslyDriveGui !== true && options.dryRun !== true) {
|
|
160
|
+
return blockedUiDrive("project.create-repeating");
|
|
161
|
+
}
|
|
162
|
+
// Seed a pure-AX taxonomy: an area lands a selectable AREA-view row; otherwise
|
|
163
|
+
// create in Someday (UIC4-f) so the promote skips the anytime-header problem.
|
|
164
|
+
const seedWhen = params.area === undefined ? "someday" : undefined;
|
|
165
|
+
if (options.dryRun === true) {
|
|
166
|
+
const where = params.area !== undefined ? "the target area (Anytime)" : "Someday";
|
|
167
|
+
return {
|
|
168
|
+
kind: "dry-run",
|
|
169
|
+
op: "project.create-repeating",
|
|
170
|
+
plan: {
|
|
171
|
+
op: "project.create-repeating",
|
|
172
|
+
vector: "ui",
|
|
173
|
+
tier: 3,
|
|
174
|
+
invocation: `create project "${params.title}" in ${where} (persists on its own) → then make-repeating ` +
|
|
175
|
+
`(select row → Items ▸ Repeat… → frequency=${params.frequency}, interval=${params.interval})`,
|
|
176
|
+
expectedDelta: {
|
|
177
|
+
mode: "create",
|
|
178
|
+
probe: { title: params.title, type: "project", sinceEpoch: 0 },
|
|
179
|
+
assert: [{ field: "repeating.isTemplate", equals: true }],
|
|
180
|
+
},
|
|
181
|
+
hazardsChecked: ["H-UI-DRIVE"],
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const startedAt = deps.now?.() ?? new Date();
|
|
186
|
+
const txnId = newTxnId(startedAt);
|
|
187
|
+
const add = await runMutation(deps, "project.add", {
|
|
188
|
+
title: params.title,
|
|
189
|
+
...(params.notes !== undefined && { notes: params.notes }),
|
|
190
|
+
...(params.area !== undefined && { area: params.area }),
|
|
191
|
+
...(seedWhen !== undefined && { when: seedWhen }),
|
|
192
|
+
...(params.deadline !== undefined && { deadline: params.deadline }),
|
|
193
|
+
...(params.todos !== undefined && { todos: params.todos }),
|
|
194
|
+
}, legOptions(options, { id: txnId, role: "leg" }, "url-scheme"));
|
|
195
|
+
if (add.kind !== "ok" || add.uuid === null) {
|
|
196
|
+
return add.kind === "ok"
|
|
197
|
+
? {
|
|
198
|
+
kind: "verify-failed",
|
|
199
|
+
op: "project.create-repeating",
|
|
200
|
+
reason: "mismatch",
|
|
201
|
+
expected: {
|
|
202
|
+
mode: "create",
|
|
203
|
+
probe: { title: params.title, type: "project", sinceEpoch: 0 },
|
|
204
|
+
assert: [],
|
|
205
|
+
},
|
|
206
|
+
observed: null,
|
|
207
|
+
detail: "the project was created but its uuid was not discovered — cannot promote it to repeating",
|
|
208
|
+
}
|
|
209
|
+
: add;
|
|
210
|
+
}
|
|
211
|
+
const promote = await runMakeRepeatingProject(deps, { uuid: add.uuid, frequency: params.frequency, interval: params.interval }, legOptions(options, { id: txnId, role: "leg" }, "ui"));
|
|
212
|
+
if (promote.kind !== "ok") {
|
|
213
|
+
// Honest: the project was created (and persists) but the promote did not land.
|
|
214
|
+
return promote;
|
|
215
|
+
}
|
|
216
|
+
appendSummary(deps, {
|
|
217
|
+
startedAt,
|
|
218
|
+
uuid: promote.uuid,
|
|
219
|
+
txnId,
|
|
220
|
+
op: "project.create-repeating",
|
|
221
|
+
invocation: `create-repeating project "${params.title}" → template ${promote.uuid ?? "?"}`,
|
|
222
|
+
});
|
|
223
|
+
return { ...promote, op: "project.create-repeating" };
|
|
224
|
+
}
|
|
225
|
+
// --------------------------------------------------------------------- audit
|
|
226
|
+
function appendSummary(deps, args) {
|
|
227
|
+
const fp = deps.fingerprint();
|
|
228
|
+
const record = {
|
|
229
|
+
v: 1,
|
|
230
|
+
ts: args.startedAt.toISOString(),
|
|
231
|
+
actor: deps.config.actor,
|
|
232
|
+
host: deps.config.host,
|
|
233
|
+
op: args.op ?? "project.make-repeating",
|
|
234
|
+
uuid: args.uuid,
|
|
235
|
+
vector: "ui",
|
|
236
|
+
disruption: 3,
|
|
237
|
+
invocation: args.invocation,
|
|
238
|
+
requested: {},
|
|
239
|
+
txn: { id: args.txnId, role: "summary" },
|
|
240
|
+
pre: null,
|
|
241
|
+
observed: args.uuid !== null ? { uuid: args.uuid } : null,
|
|
242
|
+
result: "ok",
|
|
243
|
+
verify: null,
|
|
244
|
+
durationMs: (deps.now?.() ?? new Date()).getTime() - args.startedAt.getTime(),
|
|
245
|
+
env: {
|
|
246
|
+
pkg: deps.pkgVersion ?? "0.0.1",
|
|
247
|
+
dbVersion: fp.observation.databaseVersion,
|
|
248
|
+
fingerprint: fingerprintLabel(fp, deps.config),
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
deps.audit.append(record);
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=make-repeating-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"make-repeating-project.js","sourceRoot":"","sources":["../../src/write/make-repeating-project.ts"],"names":[],"mappings":"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"}
|