things-api 0.18.0 → 0.19.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 +16 -9
- package/deputy/AppIcon.icns +0 -0
- package/deputy/VERSION +1 -1
- package/deputy/helpers-Info.plist +4 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/CodeResources +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Info.plist +3 -1
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/MacOS/things-reader +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/Resources/AppIcon.icns +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Helpers/things-reader.app/Contents/_CodeSignature/CodeResources +15 -2
- package/deputy/prebuilt/Things API Helper.app/Contents/Info.plist +5 -1
- package/deputy/prebuilt/Things API Helper.app/Contents/MacOS/things-deputy +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/Resources/AppIcon.icns +0 -0
- package/deputy/prebuilt/Things API Helper.app/Contents/_CodeSignature/CodeResources +14 -2
- package/deputy/reader/Info.plist +2 -0
- package/deputy/reader/entitlements.plist +30 -0
- package/deputy/reader/main.swift +129 -40
- package/deputy/src/server.swift +25 -2
- package/deputy/src/tcc.swift +58 -0
- package/dist/audit/schema.d.ts +13 -1
- package/dist/audit/schema.js.map +1 -1
- package/dist/capability.d.ts +160 -0
- package/dist/capability.js +416 -0
- package/dist/capability.js.map +1 -0
- package/dist/cli/commands/doctor.js +127 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/helpers.js +178 -51
- package/dist/cli/commands/helpers.js.map +1 -1
- package/dist/cli/commands/op-result.js +6 -0
- package/dist/cli/commands/op-result.js.map +1 -1
- package/dist/cli/commands/reads.js +47 -1
- package/dist/cli/commands/reads.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +9 -0
- package/dist/cli/commands/setup.js +63 -83
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/writes.d.ts +1 -1
- package/dist/cli/commands/writes.js +241 -107
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/dry-run.d.ts +1 -1
- package/dist/cli/dry-run.js +1 -1
- package/dist/cli/glyphs.d.ts +23 -4
- package/dist/cli/glyphs.js +46 -19
- package/dist/cli/glyphs.js.map +1 -1
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +49 -27
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/period.d.ts +3 -1
- package/dist/cli/period.js +1 -1
- package/dist/cli/period.js.map +1 -1
- package/dist/cli/read-driver.js +26 -1
- package/dist/cli/read-driver.js.map +1 -1
- package/dist/cli/render.d.ts +31 -4
- package/dist/cli/render.js +127 -15
- package/dist/cli/render.js.map +1 -1
- package/dist/client.d.ts +22 -2
- package/dist/client.js +36 -13
- package/dist/client.js.map +1 -1
- package/dist/contracts.d.ts +6 -2
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/deputy/install.d.ts +219 -5
- package/dist/deputy/install.js +803 -31
- package/dist/deputy/install.js.map +1 -1
- package/dist/deputy/notices.js +2 -2
- package/dist/deputy/notices.js.map +1 -1
- package/dist/deputy/protocol.d.ts +59 -5
- package/dist/deputy/protocol.js +48 -11
- package/dist/deputy/protocol.js.map +1 -1
- package/dist/deputy/routing.d.ts +21 -0
- package/dist/deputy/routing.js +111 -27
- package/dist/deputy/routing.js.map +1 -1
- package/dist/diagnose.d.ts +14 -1
- package/dist/diagnose.js +46 -6
- package/dist/diagnose.js.map +1 -1
- package/dist/direct-setup.d.ts +78 -0
- package/dist/direct-setup.js +484 -0
- package/dist/direct-setup.js.map +1 -0
- package/dist/host-access.d.ts +63 -0
- package/dist/host-access.js +165 -0
- package/dist/host-access.js.map +1 -0
- package/dist/index.d.ts +20 -5
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +27 -1
- package/dist/mcp/server.js +285 -100
- package/dist/mcp/server.js.map +1 -1
- package/dist/op-result.d.ts +9 -0
- package/dist/op-result.js +5 -0
- package/dist/op-result.js.map +1 -1
- package/dist/read/filter-contract.d.ts +1 -1
- package/dist/read/filter-contract.js +4 -0
- package/dist/read/filter-contract.js.map +1 -1
- package/dist/read/shape.js +4 -0
- package/dist/read/shape.js.map +1 -1
- package/dist/read/views.d.ts +29 -0
- package/dist/read/views.js +60 -0
- package/dist/read/views.js.map +1 -1
- package/dist/session-grant.d.ts +48 -0
- package/dist/session-grant.js +170 -0
- package/dist/session-grant.js.map +1 -0
- package/dist/surface-copy.d.ts +8 -0
- package/dist/surface-copy.js +8 -0
- package/dist/surface-copy.js.map +1 -1
- package/dist/wizard.d.ts +58 -0
- package/dist/wizard.js +167 -0
- package/dist/wizard.js.map +1 -0
- package/dist/write/availability.d.ts +1 -1
- package/dist/write/availability.js +3 -3
- package/dist/write/availability.js.map +1 -1
- package/dist/write/batch.d.ts +20 -0
- package/dist/write/batch.js +94 -15
- package/dist/write/batch.js.map +1 -1
- package/dist/write/capabilities.d.ts +9 -0
- package/dist/write/capabilities.js +2 -0
- package/dist/write/capabilities.js.map +1 -1
- package/dist/write/clear-reminder.js +1 -1
- package/dist/write/clear-reminder.js.map +1 -1
- package/dist/write/commands.d.ts +12 -1
- package/dist/write/commands.js +112 -224
- package/dist/write/commands.js.map +1 -1
- package/dist/write/failure-hints.d.ts +3 -1
- package/dist/write/failure-hints.js.map +1 -1
- package/dist/write/guards.js +19 -2
- package/dist/write/guards.js.map +1 -1
- package/dist/write/lock.d.ts +16 -13
- package/dist/write/lock.js +55 -0
- package/dist/write/lock.js.map +1 -1
- package/dist/write/make-repeating-project.js +9 -13
- package/dist/write/make-repeating-project.js.map +1 -1
- package/dist/write/operations.d.ts +36 -21
- package/dist/write/operations.js +7 -0
- package/dist/write/operations.js.map +1 -1
- package/dist/write/opid.d.ts +14 -0
- package/dist/write/opid.js +22 -0
- package/dist/write/opid.js.map +1 -1
- package/dist/write/param-schema.d.ts +124 -0
- package/dist/write/param-schema.js +747 -0
- package/dist/write/param-schema.js.map +1 -0
- package/dist/write/pipeline.d.ts +76 -2
- package/dist/write/pipeline.js +190 -2
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +8 -0
- package/dist/write/pre-state.js +29 -2
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/promote-clone.js +539 -439
- package/dist/write/promote-clone.js.map +1 -1
- package/dist/write/reorder.js +25 -8
- package/dist/write/reorder.js.map +1 -1
- package/dist/write/repeat-rule.d.ts +28 -1
- package/dist/write/repeat-rule.js +54 -4
- package/dist/write/repeat-rule.js.map +1 -1
- package/dist/write/resolution-timestamps.d.ts +11 -0
- package/dist/write/resolution-timestamps.js +83 -38
- package/dist/write/resolution-timestamps.js.map +1 -1
- package/dist/write/reversibility.js +4 -0
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/template-mutation.d.ts +137 -0
- package/dist/write/template-mutation.js +451 -0
- package/dist/write/template-mutation.js.map +1 -0
- package/dist/write/undo.js +10 -20
- package/dist/write/undo.js.map +1 -1
- package/dist/write/update-fields.d.ts +151 -0
- package/dist/write/update-fields.js +427 -0
- package/dist/write/update-fields.js.map +1 -0
- package/dist/write/vectors/applescript.js +3 -0
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/registry.d.ts +1 -1
- package/dist/write/vectors/registry.js +10 -2
- package/dist/write/vectors/registry.js.map +1 -1
- package/dist/write/vectors/shortcuts.js +2 -2
- package/dist/write/vectors/shortcuts.js.map +1 -1
- package/dist/write/vectors/simulator.js +7 -2
- package/dist/write/vectors/simulator.js.map +1 -1
- package/dist/write/vectors/types.d.ts +57 -0
- package/dist/write/vectors/ui-recipes.d.ts +19 -0
- package/dist/write/vectors/ui-recipes.js +30 -0
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +13 -0
- package/dist/write/vectors/ui.js +62 -13
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +21 -0
- package/dist/write/verify/delta.js.map +1 -1
- package/package.json +2 -1
- package/schema/envelope.schema.json +5 -3
- package/scripts/build-helpers.sh +5 -0
- package/skills/things-cli/SKILL.md +5 -3
- package/skills/things-cli/references/contracts.md +1 -0
- package/skills/things-cli/references/data-model.md +3 -0
- package/skills/things-cli/references/errors.md +1 -1
- package/skills/things-cli/references/gui.md +1 -0
- package/skills/things-cli/references/repeating.md +6 -0
- package/skills/things-cli/references/tag-cleanup.md +64 -0
package/dist/write/lock.d.ts
CHANGED
|
@@ -1,16 +1,3 @@
|
|
|
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
1
|
import { mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
15
2
|
export declare class MutationLockError extends Error {
|
|
16
3
|
constructor(message: string);
|
|
@@ -18,6 +5,22 @@ export declare class MutationLockError extends Error {
|
|
|
18
5
|
export interface MutationLock {
|
|
19
6
|
release(): void;
|
|
20
7
|
}
|
|
8
|
+
/** True when an enclosing composite already holds `path` on this async context. */
|
|
9
|
+
export declare function mutationLockHeld(path: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Run `body` holding ONE mutation lock for its whole duration — the COMPOSITE
|
|
12
|
+
* scope. Every {@link acquireMutationLock} reached from inside (each leg, and
|
|
13
|
+
* any nested composite) is a reentrant no-op, so the composite serializes
|
|
14
|
+
* against other writers as a WHOLE rather than leg by leg.
|
|
15
|
+
*
|
|
16
|
+
* Already inside a hold on the same path (a composite invoked as another
|
|
17
|
+
* composite's leg): `body` runs directly on the enclosing hold — never a second
|
|
18
|
+
* acquisition, which would deadlock against its own holder.
|
|
19
|
+
*
|
|
20
|
+
* Throws {@link MutationLockError} if the lock cannot be taken, exactly as the
|
|
21
|
+
* per-leg acquisition does; the caller shapes that into its own refusal.
|
|
22
|
+
*/
|
|
23
|
+
export declare function withMutationLock<T>(path: string, body: () => Promise<T>, options?: AcquireMutationLockOptions): Promise<T>;
|
|
21
24
|
/**
|
|
22
25
|
* Injectable filesystem + environment seam. Production uses the real node:fs
|
|
23
26
|
* calls; unit tests substitute this to drive the concurrent steal paths
|
package/dist/write/lock.js
CHANGED
|
@@ -10,7 +10,17 @@
|
|
|
10
10
|
* the TOCTOU window an unconditional unlink+recreate would leave open, where
|
|
11
11
|
* two processes could both observe a dead holder and both end up believing
|
|
12
12
|
* they hold the lock.
|
|
13
|
+
*
|
|
14
|
+
* SCOPE (2026-08-23): the lock has two scopes, not one. The base case is
|
|
15
|
+
* PER-LEG — one mutation, acquired and released by the pipeline. A COMPOSITE (a
|
|
16
|
+
* single verb the engine executes as several mutations — the promote verbs run
|
|
17
|
+
* clone → trash → promote) instead holds ONE lock across all of its legs via
|
|
18
|
+
* {@link withMutationLock}, and its legs' own acquisitions become reentrant
|
|
19
|
+
* no-ops. Without that, two concurrent composites interleave at leg boundaries
|
|
20
|
+
* — A's clone, B's clone, A's promote — and no single-writer guarantee survives
|
|
21
|
+
* the whole verb.
|
|
13
22
|
*/
|
|
23
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
14
24
|
import { mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
15
25
|
import { dirname } from "node:path";
|
|
16
26
|
export class MutationLockError extends Error {
|
|
@@ -28,6 +38,45 @@ function pidAlive(pid) {
|
|
|
28
38
|
return false;
|
|
29
39
|
}
|
|
30
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* The composite hold, carried on the ASYNC CONTEXT rather than threaded through
|
|
43
|
+
* every call site. `AsyncLocalStorage` is what makes the reentrancy correctly
|
|
44
|
+
* COMPOSITE-scoped instead of process-scoped: a leg reached from inside a
|
|
45
|
+
* composite inherits the store and recognizes the hold, while a genuinely
|
|
46
|
+
* concurrent composite in the same process (two parallel MCP tool calls) runs in
|
|
47
|
+
* its OWN context, sees no store, and is excluded exactly as a second process
|
|
48
|
+
* would be. A process-wide "we hold it" flag would have let those two interleave
|
|
49
|
+
* silently — the very thing this scoping exists to stop.
|
|
50
|
+
*/
|
|
51
|
+
const compositeHold = new AsyncLocalStorage();
|
|
52
|
+
/** True when an enclosing composite already holds `path` on this async context. */
|
|
53
|
+
export function mutationLockHeld(path) {
|
|
54
|
+
return compositeHold.getStore()?.path === path;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Run `body` holding ONE mutation lock for its whole duration — the COMPOSITE
|
|
58
|
+
* scope. Every {@link acquireMutationLock} reached from inside (each leg, and
|
|
59
|
+
* any nested composite) is a reentrant no-op, so the composite serializes
|
|
60
|
+
* against other writers as a WHOLE rather than leg by leg.
|
|
61
|
+
*
|
|
62
|
+
* Already inside a hold on the same path (a composite invoked as another
|
|
63
|
+
* composite's leg): `body` runs directly on the enclosing hold — never a second
|
|
64
|
+
* acquisition, which would deadlock against its own holder.
|
|
65
|
+
*
|
|
66
|
+
* Throws {@link MutationLockError} if the lock cannot be taken, exactly as the
|
|
67
|
+
* per-leg acquisition does; the caller shapes that into its own refusal.
|
|
68
|
+
*/
|
|
69
|
+
export async function withMutationLock(path, body, options = {}) {
|
|
70
|
+
if (mutationLockHeld(path))
|
|
71
|
+
return body();
|
|
72
|
+
const lock = await acquireMutationLock(path, options);
|
|
73
|
+
try {
|
|
74
|
+
return await compositeHold.run({ path }, body);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
lock.release();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
31
80
|
let stealCounter = 0;
|
|
32
81
|
function realDeps() {
|
|
33
82
|
return {
|
|
@@ -46,6 +95,12 @@ function errCode(err) {
|
|
|
46
95
|
return err.code;
|
|
47
96
|
}
|
|
48
97
|
export async function acquireMutationLock(path, options = {}) {
|
|
98
|
+
// REENTRANT under a composite hold (see withMutationLock): the enclosing
|
|
99
|
+
// composite already owns this lockfile, so a leg neither re-takes it (it would
|
|
100
|
+
// wait out the timeout against its own holder) nor releases it (the remaining
|
|
101
|
+
// legs still need it). The composite's own release is the only one.
|
|
102
|
+
if (mutationLockHeld(path))
|
|
103
|
+
return { release() { } };
|
|
49
104
|
const waitMs = options.waitMs ?? 30_000;
|
|
50
105
|
const sleep = options.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
51
106
|
const deps = options.deps ?? realDeps();
|
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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"}
|
|
@@ -75,19 +75,15 @@ export async function promoteProjectViaGui(deps, params, options = {}) {
|
|
|
75
75
|
if (options.dangerouslyDriveGui !== true && options.dryRun !== true) {
|
|
76
76
|
return blockedUiDrive("project.make-repeating");
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
...(params.reminder !== undefined && { reminder: params.reminder }),
|
|
88
|
-
...(params.deadline !== undefined && { deadline: params.deadline }),
|
|
89
|
-
...(params.startDaysEarlier !== undefined && { startDaysEarlier: params.startDaysEarlier }),
|
|
90
|
-
};
|
|
78
|
+
// Everything but the uuid rides THROUGH: this bag is re-keyed to the resolved
|
|
79
|
+
// project uuid, not filtered. `next` (the dialog's first-occurrence field,
|
|
80
|
+
// ANCH2) was missing from an earlier hand-enumeration, so every project promote
|
|
81
|
+
// silently took the app's today-anchored default — a dated `project
|
|
82
|
+
// make-repeating` / `add-repeating --when` landed on the wrong phase and then
|
|
83
|
+
// failed its own post-drive verify. Spread first, override the uuid, so a new
|
|
84
|
+
// rule field is carried by default instead of dropped by omission (the RRF1
|
|
85
|
+
// hand-enumeration class, decisions.md 2026-08-17).
|
|
86
|
+
const driveParams = { ...params, uuid };
|
|
91
87
|
if (options.dryRun === true) {
|
|
92
88
|
const coercion = tax.kind === "anytime"
|
|
93
89
|
? `coerce to Someday (update-project?id=${uuid}&when=someday) → verified → `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make-repeating-project.js","sourceRoot":"","sources":["../../src/write/make-repeating-project.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"make-repeating-project.js","sourceRoot":"","sources":["../../src/write/make-repeating-project.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* per-vector matrices (data, produced by the lab), not here.
|
|
5
5
|
*/
|
|
6
6
|
import type { IsoDate, ReminderTime } from "../model/dates.ts";
|
|
7
|
-
export declare const OPERATION_KINDS: readonly ["todo.add", "todo.update", "todo.complete", "todo.cancel", "todo.reopen", "todo.move", "todo.set-tags", "todo.replace-checklist", "todo.edit-checklist-item", "todo.delete", "project.add", "project.update", "project.complete", "project.delete", "area.add", "area.delete", "tag.add", "tag.delete", "trash.empty", "reorder", "todo.duplicate", "area.update", "tag.update", "project.move", "todo.restore", "project.duplicate", "project.cancel", "project.reopen", "project.restore", "project.set-tags", "todo.set-dates", "project.set-dates", "project.add-heading", "project.rename-heading", "project.archive-heading", "project.unarchive-heading", "project.promote-heading", "project.move-heading", "project.move-heading-to-project", "project.dissolve-heading", "todo.clear-dated-reminder", "todo.make-repeating", "todo.reschedule-repeat", "todo.pause-repeat", "todo.resume-repeat", "todo.convert-to-project", "project.reschedule-repeat", "project.pause-repeat", "project.resume-repeat", "area.reorder", "project.make-repeating", "project.add-repeating", "todo.add-repeating", "todo.clone", "project.clone", "log-now"];
|
|
7
|
+
export declare const OPERATION_KINDS: readonly ["todo.add", "todo.update", "todo.complete", "todo.cancel", "todo.reopen", "todo.move", "todo.set-tags", "todo.replace-checklist", "todo.edit-checklist-item", "todo.delete", "project.add", "project.update", "project.complete", "project.delete", "area.add", "area.delete", "tag.add", "tag.delete", "trash.empty", "reorder", "todo.duplicate", "area.update", "tag.update", "project.move", "todo.restore", "project.duplicate", "project.cancel", "project.reopen", "project.restore", "project.set-tags", "todo.set-dates", "project.set-dates", "project.add-heading", "project.rename-heading", "project.archive-heading", "project.unarchive-heading", "project.promote-heading", "project.move-heading", "project.move-heading-to-project", "project.dissolve-heading", "todo.clear-dated-reminder", "todo.make-repeating", "todo.reschedule-repeat", "todo.pause-repeat", "todo.resume-repeat", "todo.create-next-copy", "todo.convert-to-project", "project.reschedule-repeat", "project.pause-repeat", "project.resume-repeat", "area.reorder", "project.make-repeating", "project.add-repeating", "todo.add-repeating", "todo.clone", "project.clone", "log-now"];
|
|
8
8
|
export type OperationKind = (typeof OPERATION_KINDS)[number];
|
|
9
9
|
/**
|
|
10
10
|
* Operations delivered EXCLUSIVELY through the Accessibility GUI ("ui")
|
|
@@ -82,8 +82,20 @@ export interface TodoAddParams {
|
|
|
82
82
|
*/
|
|
83
83
|
completedAt?: string;
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
/**
|
|
86
|
+
* The attribute vocabulary of the update verbs — ONE declaration shared by
|
|
87
|
+
* {@link TodoUpdateParams} and {@link ProjectUpdateParams} (the two carry an
|
|
88
|
+
* identical field set; the app's `update` / `update-project` URL commands take
|
|
89
|
+
* the same parameter names).
|
|
90
|
+
*
|
|
91
|
+
* It is a MULTI-CONSUMER vocabulary: the URL compilation, the expected-delta
|
|
92
|
+
* assertions, the undo inverse, and the CLI/MCP patch builders all speak it. Per
|
|
93
|
+
* the exhaustive-map doctrine (decisions.md 2026-08-17, #491) none of them may
|
|
94
|
+
* hand-enumerate it — every consumer derives from the exhaustive `Record<keyof
|
|
95
|
+
* UpdateFields, …>` in [update-fields.ts](./update-fields.ts), so a field added
|
|
96
|
+
* here breaks compilation until it is consciously handled everywhere.
|
|
97
|
+
*/
|
|
98
|
+
export interface UpdateFields {
|
|
87
99
|
title?: string;
|
|
88
100
|
notes?: string;
|
|
89
101
|
/** Append to the existing notes (newline-joined). Exclusive with notes/prependNotes. */
|
|
@@ -92,14 +104,17 @@ export interface TodoUpdateParams {
|
|
|
92
104
|
prependNotes?: string;
|
|
93
105
|
when?: WhenValue;
|
|
94
106
|
/**
|
|
95
|
-
* `HH:mm` sets a reminder (requires when: today|evening in the same
|
|
96
|
-
* null clears it (today/evening only — a dated reminder can only be
|
|
107
|
+
* `HH:mm` sets a reminder (requires when: today|evening|YYYY-MM-DD in the same
|
|
108
|
+
* call); null clears it (today/evening only — a dated reminder can only be
|
|
97
109
|
* changed, not cleared). When re-scheduling with this OMITTED, an existing
|
|
98
|
-
* reminder is auto-preserved.
|
|
110
|
+
* (live) reminder is auto-preserved.
|
|
99
111
|
*/
|
|
100
112
|
reminder?: ReminderTime | null;
|
|
101
113
|
deadline?: IsoDate | null;
|
|
102
114
|
}
|
|
115
|
+
export interface TodoUpdateParams extends UpdateFields {
|
|
116
|
+
uuid: string;
|
|
117
|
+
}
|
|
103
118
|
export interface UuidParams {
|
|
104
119
|
uuid: string;
|
|
105
120
|
}
|
|
@@ -310,22 +325,9 @@ export interface ProjectAddParams {
|
|
|
310
325
|
*/
|
|
311
326
|
completedAt?: string;
|
|
312
327
|
}
|
|
313
|
-
|
|
328
|
+
/** Projects take the same {@link UpdateFields} vocabulary as to-dos (A3). */
|
|
329
|
+
export interface ProjectUpdateParams extends UpdateFields {
|
|
314
330
|
uuid: string;
|
|
315
|
-
title?: string;
|
|
316
|
-
notes?: string;
|
|
317
|
-
/** Append to the existing notes (newline-joined). Exclusive with notes/prependNotes. */
|
|
318
|
-
appendNotes?: string;
|
|
319
|
-
/** Prepend to the existing notes (newline-joined). Exclusive with notes/appendNotes. */
|
|
320
|
-
prependNotes?: string;
|
|
321
|
-
when?: WhenValue;
|
|
322
|
-
/**
|
|
323
|
-
* `HH:mm` sets a reminder (requires when: today|evening|YYYY-MM-DD in the
|
|
324
|
-
* same call); null clears it (today/evening only — a dated reminder can
|
|
325
|
-
* only be changed, not cleared). Same semantics as to-do reminders.
|
|
326
|
-
*/
|
|
327
|
-
reminder?: ReminderTime | null;
|
|
328
|
-
deadline?: IsoDate | null;
|
|
329
331
|
}
|
|
330
332
|
export interface ProjectSetTagsParams {
|
|
331
333
|
uuid: string;
|
|
@@ -565,6 +567,11 @@ export interface AddRepeatingRuleFields {
|
|
|
565
567
|
* seeds a pure-AX taxonomy (an `area` lands a selectable AREA-view row; otherwise
|
|
566
568
|
* Someday) so the promote never needs a coercion. The two legs are NOT atomic:
|
|
567
569
|
* the created project persists even if the promote refuses.
|
|
570
|
+
*
|
|
571
|
+
* `deadline` is the exception, exactly as on {@link TodoAddRepeatingParams}: a
|
|
572
|
+
* concrete deadline DATE maps to the RULE (each occurrence starts
|
|
573
|
+
* `deadline − when` days before its own deadline) rather than landing on the
|
|
574
|
+
* created project, which the promote replaces with the series' own instance.
|
|
568
575
|
*/
|
|
569
576
|
export interface ProjectAddRepeatingParams extends AddRepeatingRuleFields {
|
|
570
577
|
title: string;
|
|
@@ -572,6 +579,13 @@ export interface ProjectAddRepeatingParams extends AddRepeatingRuleFields {
|
|
|
572
579
|
/** Destination area (uuid or unique name); when omitted the project is created in Someday. */
|
|
573
580
|
area?: ContainerRef;
|
|
574
581
|
when?: WhenValue;
|
|
582
|
+
/**
|
|
583
|
+
* The FIRST occurrence's due date — mapped to the RULE (derive
|
|
584
|
+
* start-days-earlier = deadline − when), so every occurrence is deadlined and
|
|
585
|
+
* the created project carries none. Needs a concrete `when` on or before it;
|
|
586
|
+
* refused on an after-completion series, whose instance is created without a
|
|
587
|
+
* deadline (RSIM-P P4).
|
|
588
|
+
*/
|
|
575
589
|
deadline?: IsoDate;
|
|
576
590
|
/** Flat child to-do titles (born open). Exclusive with `items`. */
|
|
577
591
|
todos?: string[];
|
|
@@ -700,6 +714,7 @@ export interface OperationParamsMap {
|
|
|
700
714
|
"todo.reschedule-repeat": RepeatRuleParams;
|
|
701
715
|
"todo.pause-repeat": UuidParams;
|
|
702
716
|
"todo.resume-repeat": UuidParams;
|
|
717
|
+
"todo.create-next-copy": UuidParams;
|
|
703
718
|
"todo.convert-to-project": UuidParams;
|
|
704
719
|
"project.reschedule-repeat": RepeatRuleParams;
|
|
705
720
|
"project.pause-repeat": UuidParams;
|
package/dist/write/operations.js
CHANGED
|
@@ -44,6 +44,7 @@ export const OPERATION_KINDS = [
|
|
|
44
44
|
"todo.reschedule-repeat",
|
|
45
45
|
"todo.pause-repeat",
|
|
46
46
|
"todo.resume-repeat",
|
|
47
|
+
"todo.create-next-copy",
|
|
47
48
|
"todo.convert-to-project",
|
|
48
49
|
"project.reschedule-repeat",
|
|
49
50
|
"project.pause-repeat",
|
|
@@ -68,6 +69,12 @@ export const UI_DRIVE_OPS = [
|
|
|
68
69
|
"todo.reschedule-repeat",
|
|
69
70
|
"todo.pause-repeat",
|
|
70
71
|
"todo.resume-repeat",
|
|
72
|
+
// CNC1: `Items ▸ Repeat ▸ Create Next Copy` — materialize the pending
|
|
73
|
+
// occurrence and advance the series. Not a user-facing verb: it is the first
|
|
74
|
+
// leg of the template-mutation composites (template-mutation.ts), which mutate
|
|
75
|
+
// the row it mints. Its template delta is byte-identical to the app's own
|
|
76
|
+
// `Make Exception` (docs/lab/cnc1-template-mutations.md §1).
|
|
77
|
+
"todo.create-next-copy",
|
|
71
78
|
"todo.convert-to-project",
|
|
72
79
|
"project.promote-heading",
|
|
73
80
|
"project.reschedule-repeat",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/write/operations.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,UAAU;IACV,aAAa;IACb,eAAe;IACf,aAAa;IACb,aAAa;IACb,WAAW;IACX,eAAe;IACf,wBAAwB;IACxB,0BAA0B;IAC1B,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,kBAAkB;IAClB,gBAAgB;IAChB,UAAU;IACV,aAAa;IACb,SAAS;IACT,YAAY;IACZ,aAAa;IACb,SAAS;IACT,gBAAgB;IAChB,aAAa;IACb,YAAY;IACZ,cAAc;IACd,cAAc;IACd,mBAAmB;IACnB,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,gBAAgB;IAChB,mBAAmB;IACnB,qBAAqB;IACrB,wBAAwB;IACxB,yBAAyB;IACzB,2BAA2B;IAC3B,yBAAyB;IACzB,sBAAsB;IACtB,iCAAiC;IACjC,0BAA0B;IAC1B,2BAA2B;IAC3B,qBAAqB;IACrB,wBAAwB;IACxB,mBAAmB;IACnB,oBAAoB;IACpB,yBAAyB;IACzB,2BAA2B;IAC3B,sBAAsB;IACtB,uBAAuB;IACvB,cAAc;IACd,wBAAwB;IACxB,uBAAuB;IACvB,oBAAoB;IACpB,YAAY;IACZ,eAAe;IACf,SAAS;CACD,CAAC;AAIX;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAA6B;IACpD,qBAAqB;IACrB,wBAAwB;IACxB,mBAAmB;IACnB,oBAAoB;IACpB,yBAAyB;IACzB,yBAAyB;IACzB,2BAA2B;IAC3B,sBAAsB;IACtB,uBAAuB;IACvB,cAAc;IACd,uEAAuE;IACvE,4EAA4E;IAC5E,6EAA6E;IAC7E,iEAAiE;IACjE,wBAAwB;IACxB,2EAA2E;IAC3E,4EAA4E;IAC5E,+EAA+E;IAC/E,kEAAkE;IAClE,iCAAiC;IACjC,6EAA6E;IAC7E,yEAAyE;IACzE,2EAA2E;IAC3E,8EAA8E;IAC9E,gBAAgB;IAChB,0BAA0B;CAClB,CAAC;AAEX,MAAM,UAAU,WAAW,CAAC,EAAiB;IAC3C,OAAO,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAA6B;IACnD,qBAAqB;IACrB,wBAAwB;IACxB,yBAAyB;IACzB,2BAA2B;IAC3B,yBAAyB;IACzB,sBAAsB;IACtB,iCAAiC;IACjC,0BAA0B;CAClB,CAAC;AAEX,MAAM,UAAU,WAAW,CAAC,EAAiB;IAC3C,OAAO,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA6B;IAC1D,wBAAwB;IACxB,yBAAyB;IACzB,2BAA2B;IAC3B,yBAAyB;IACzB,0BAA0B;CAClB,CAAC;AAEX,MAAM,UAAU,iBAAiB,CAAC,EAAiB;IACjD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzC,CAAC;
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/write/operations.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,UAAU;IACV,aAAa;IACb,eAAe;IACf,aAAa;IACb,aAAa;IACb,WAAW;IACX,eAAe;IACf,wBAAwB;IACxB,0BAA0B;IAC1B,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,kBAAkB;IAClB,gBAAgB;IAChB,UAAU;IACV,aAAa;IACb,SAAS;IACT,YAAY;IACZ,aAAa;IACb,SAAS;IACT,gBAAgB;IAChB,aAAa;IACb,YAAY;IACZ,cAAc;IACd,cAAc;IACd,mBAAmB;IACnB,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,gBAAgB;IAChB,mBAAmB;IACnB,qBAAqB;IACrB,wBAAwB;IACxB,yBAAyB;IACzB,2BAA2B;IAC3B,yBAAyB;IACzB,sBAAsB;IACtB,iCAAiC;IACjC,0BAA0B;IAC1B,2BAA2B;IAC3B,qBAAqB;IACrB,wBAAwB;IACxB,mBAAmB;IACnB,oBAAoB;IACpB,uBAAuB;IACvB,yBAAyB;IACzB,2BAA2B;IAC3B,sBAAsB;IACtB,uBAAuB;IACvB,cAAc;IACd,wBAAwB;IACxB,uBAAuB;IACvB,oBAAoB;IACpB,YAAY;IACZ,eAAe;IACf,SAAS;CACD,CAAC;AAIX;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAA6B;IACpD,qBAAqB;IACrB,wBAAwB;IACxB,mBAAmB;IACnB,oBAAoB;IACpB,sEAAsE;IACtE,6EAA6E;IAC7E,+EAA+E;IAC/E,0EAA0E;IAC1E,6DAA6D;IAC7D,uBAAuB;IACvB,yBAAyB;IACzB,yBAAyB;IACzB,2BAA2B;IAC3B,sBAAsB;IACtB,uBAAuB;IACvB,cAAc;IACd,uEAAuE;IACvE,4EAA4E;IAC5E,6EAA6E;IAC7E,iEAAiE;IACjE,wBAAwB;IACxB,2EAA2E;IAC3E,4EAA4E;IAC5E,+EAA+E;IAC/E,kEAAkE;IAClE,iCAAiC;IACjC,6EAA6E;IAC7E,yEAAyE;IACzE,2EAA2E;IAC3E,8EAA8E;IAC9E,gBAAgB;IAChB,0BAA0B;CAClB,CAAC;AAEX,MAAM,UAAU,WAAW,CAAC,EAAiB;IAC3C,OAAO,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAA6B;IACnD,qBAAqB;IACrB,wBAAwB;IACxB,yBAAyB;IACzB,2BAA2B;IAC3B,yBAAyB;IACzB,sBAAsB;IACtB,iCAAiC;IACjC,0BAA0B;CAClB,CAAC;AAEX,MAAM,UAAU,WAAW,CAAC,EAAiB;IAC3C,OAAO,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA6B;IAC1D,wBAAwB;IACxB,yBAAyB;IACzB,2BAA2B;IAC3B,yBAAyB;IACzB,0BAA0B;CAClB,CAAC;AAEX,MAAM,UAAU,iBAAiB,CAAC,EAAiB;IACjD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzC,CAAC;AAkhBD,MAAM,CAAC,MAAM,QAAQ,GAAuB;IAC1C,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,WAAW;IACX,UAAU;IACV,QAAQ;IACR,UAAU;CACF,CAAC"}
|
package/dist/write/opid.d.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* (as a batch line OR a single `--op-id` invocation) is safe against a double.
|
|
13
13
|
*/
|
|
14
14
|
import type { AuditRecord } from "../audit/schema.ts";
|
|
15
|
+
import { type MutationResult, type WriteDeps, type WriteOptions } from "./pipeline.ts";
|
|
15
16
|
/** The idempotency-key charset/length, identical for a batch line and a single-op flag. */
|
|
16
17
|
export declare const OP_ID_RE: RegExp;
|
|
17
18
|
/**
|
|
@@ -29,3 +30,16 @@ export declare const OPID_LOOKBACK_MS: number;
|
|
|
29
30
|
* verify-failed:timeout reconciliation variant is a queued phase-2 round).
|
|
30
31
|
*/
|
|
31
32
|
export declare function findAppliedOpId(records: AuditRecord[], opId: string, now: Date): AuditRecord | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* The lookback as a DISPATCH DECISION: the replay result when this write's
|
|
35
|
+
* `opId` was already applied, or null when it must run. The ONE gate every
|
|
36
|
+
* single-invocation entry point calls before doing anything — the client's
|
|
37
|
+
* single-op `run`, and the complete/cancel/exception entries whose composites
|
|
38
|
+
* own their own dispatch (they never reach `run`, so without this the key would
|
|
39
|
+
* be recorded and never honored).
|
|
40
|
+
*
|
|
41
|
+
* Three conditions, all fail-open (run the write) rather than fail-closed:
|
|
42
|
+
* no key, a dry run (it mints and records nothing, so there is nothing to
|
|
43
|
+
* deduplicate against), or no trail to read.
|
|
44
|
+
*/
|
|
45
|
+
export declare function replayIfApplied(deps: WriteDeps, options: WriteOptions): MutationResult | null;
|
package/dist/write/opid.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { replayResultFromRecord, } from "./pipeline.js";
|
|
2
|
+
import { readAuditRecords } from "./undo.js";
|
|
1
3
|
/** The idempotency-key charset/length, identical for a batch line and a single-op flag. */
|
|
2
4
|
export const OP_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
3
5
|
/**
|
|
@@ -27,4 +29,24 @@ export function findAppliedOpId(records, opId, now) {
|
|
|
27
29
|
}
|
|
28
30
|
return match;
|
|
29
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* The lookback as a DISPATCH DECISION: the replay result when this write's
|
|
34
|
+
* `opId` was already applied, or null when it must run. The ONE gate every
|
|
35
|
+
* single-invocation entry point calls before doing anything — the client's
|
|
36
|
+
* single-op `run`, and the complete/cancel/exception entries whose composites
|
|
37
|
+
* own their own dispatch (they never reach `run`, so without this the key would
|
|
38
|
+
* be recorded and never honored).
|
|
39
|
+
*
|
|
40
|
+
* Three conditions, all fail-open (run the write) rather than fail-closed:
|
|
41
|
+
* no key, a dry run (it mints and records nothing, so there is nothing to
|
|
42
|
+
* deduplicate against), or no trail to read.
|
|
43
|
+
*/
|
|
44
|
+
export function replayIfApplied(deps, options) {
|
|
45
|
+
if (options.opId === undefined || options.dryRun === true)
|
|
46
|
+
return null;
|
|
47
|
+
if (deps.auditDirPath === undefined)
|
|
48
|
+
return null;
|
|
49
|
+
const applied = findAppliedOpId(readAuditRecords(deps.auditDirPath), options.opId, deps.now?.() ?? new Date());
|
|
50
|
+
return applied === undefined ? null : replayResultFromRecord(applied);
|
|
51
|
+
}
|
|
30
52
|
//# sourceMappingURL=opid.js.map
|
package/dist/write/opid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opid.js","sourceRoot":"","sources":["../../src/write/opid.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"opid.js","sourceRoot":"","sources":["../../src/write/opid.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,sBAAsB,GAIvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,2FAA2F;AAC3F,MAAM,CAAC,MAAM,QAAQ,GAAG,uBAAuB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAC1C,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAsB,EACtB,IAAY,EACZ,GAAS;IAET,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,gBAAgB,CAAC;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC;IACrD,IAAI,KAA8B,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI;YAAE,SAAS;QACnD,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,MAAM;YAAE,SAAS;QAChD,KAAK,GAAG,CAAC,CAAC,CAAC,4DAA4D;IACzE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,IAAe,EAAE,OAAqB;IACpE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACvE,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,OAAO,GAAG,eAAe,CAC7B,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,EACnC,OAAO,CAAC,IAAI,EACZ,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,IAAI,IAAI,EAAE,CAC3B,CAAC;IACF,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE per-operation PARAMETER schema registry — the structural contract every
|
|
3
|
+
* untyped entry point (batch JSONL, MCP `run_operation`/`batch`, a JavaScript
|
|
4
|
+
* caller handing over parsed JSON) is held to BEFORE anything is dispatched.
|
|
5
|
+
*
|
|
6
|
+
* Why it exists (#580): the engine used to duck-test its own params — `todo.add`
|
|
7
|
+
* asked whether `params.project` LOOKED like a container (`.uuid`/`.title`
|
|
8
|
+
* present) and, when a bare uuid STRING was supplied instead, concluded the field
|
|
9
|
+
* was ABSENT. No `list-id` compiled, no destination assertion was emitted, the
|
|
10
|
+
* to-do landed in the Inbox, verification passed against the (empty) delta, and
|
|
11
|
+
* the batch reported success. Malformed input degraded silently into a different,
|
|
12
|
+
* plausible-looking mutation. The same genus lurks anywhere a shape is inferred
|
|
13
|
+
* rather than asserted, so the fix is structural: ONE registry, checked at the
|
|
14
|
+
* two choke points (the batch's static preflight and the mutation pipeline), and
|
|
15
|
+
* duck tests downgraded to belt-and-braces throws.
|
|
16
|
+
*
|
|
17
|
+
* Doctrine (decisions.md 2026-08-17, #491 RRF1 — the exhaustive-map law): the
|
|
18
|
+
* registry is EXHAUSTIVE on both axes. `PARAM_SCHEMAS` is a
|
|
19
|
+
* `{ [K in OperationKind]: … }`, so a new operation breaks compilation until it
|
|
20
|
+
* declares a schema; each op's schema is a `{ [F in keyof Params]-?: FieldSpec }`,
|
|
21
|
+
* so a new parameter breaks compilation until its shape is consciously named.
|
|
22
|
+
* Neither axis can be satisfied by an out-of-date literal.
|
|
23
|
+
*
|
|
24
|
+
* Hand-written, zero-dependency validation in the style of
|
|
25
|
+
* [repeat-rule.ts](./repeat-rule.ts) — NO zod. zod is a consumer-surface
|
|
26
|
+
* dependency confined to `src/mcp/server.ts` (the CLI guest bundle ships neither
|
|
27
|
+
* it nor the MCP SDK; see the lazy loader in `src/index.ts`).
|
|
28
|
+
*
|
|
29
|
+
* The contract:
|
|
30
|
+
* - a REQUIRED field must be present and the right shape; absent or `null` is a
|
|
31
|
+
* structural error;
|
|
32
|
+
* - an OPTIONAL field may be absent, explicitly `null`, or the right shape —
|
|
33
|
+
* any other type is a structural error (never a silent "treat as absent");
|
|
34
|
+
* - UNKNOWN keys are refused by name (a typo is never silently dropped);
|
|
35
|
+
* - a container reference is an OBJECT (`{"uuid": …}` / `{"title": …}`) — a bare
|
|
36
|
+
* string is refused with steering copy rather than normalized. One canonical
|
|
37
|
+
* shape (ALPHA-CONTRACT: no shorthand alias machinery pre-1.0).
|
|
38
|
+
*
|
|
39
|
+
* The check is purely STRUCTURAL. It says nothing about whether a uuid exists,
|
|
40
|
+
* whether two fields contradict each other (that stays with each command's
|
|
41
|
+
* `preRead`), or whether a `"$name"` batch temp-reference is declared (that stays
|
|
42
|
+
* with the batch's own `staticRefError`) — so `$`-prefixed strings pass every
|
|
43
|
+
* plain-string field and every container `uuid`, as they must.
|
|
44
|
+
*/
|
|
45
|
+
import { type OperationKind, type OperationParamsMap } from "./operations.ts";
|
|
46
|
+
/**
|
|
47
|
+
* The shape vocabulary. `custom` carries a hand-written validator for the shapes
|
|
48
|
+
* the primitives cannot express (a discriminated bag, a structured item list, a
|
|
49
|
+
* calendar anchor — those WRAP the engine's existing validators rather than
|
|
50
|
+
* restating them). `unvalidated` is the escape hatch and requires a WRITTEN
|
|
51
|
+
* reason; there are currently none.
|
|
52
|
+
*/
|
|
53
|
+
export type FieldKind = "string" | "boolean" | "number" | "stringArray" | "enum" | "container" | "custom" | "unvalidated";
|
|
54
|
+
export interface FieldSpec {
|
|
55
|
+
kind: FieldKind;
|
|
56
|
+
/** Absent (or explicitly `null`) is accepted. */
|
|
57
|
+
optional: boolean;
|
|
58
|
+
/** Behavioral description of the accepted shape — the "expected" half of every refusal. */
|
|
59
|
+
describe: string;
|
|
60
|
+
/** enum: the accepted values. */
|
|
61
|
+
values?: readonly string[];
|
|
62
|
+
/** string: reject the empty string. */
|
|
63
|
+
nonEmpty?: boolean;
|
|
64
|
+
/** number: whole numbers only, and the inclusive bounds. */
|
|
65
|
+
integer?: boolean;
|
|
66
|
+
min?: number;
|
|
67
|
+
max?: number;
|
|
68
|
+
/** custom: returns a refusal detail, or null when the value is well-shaped. */
|
|
69
|
+
validate?: (value: unknown, path: string) => string | null;
|
|
70
|
+
/** unvalidated: why this field carries no shape check. */
|
|
71
|
+
reason?: string;
|
|
72
|
+
}
|
|
73
|
+
/** The received-type half of a refusal, in the words a caller reading JSON uses. */
|
|
74
|
+
export declare function describeType(value: unknown): string;
|
|
75
|
+
type OpSchema<K extends OperationKind> = {
|
|
76
|
+
[F in keyof OperationParamsMap[K]]-?: FieldSpec;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* The registry. EXHAUSTIVE on both axes by construction: a new
|
|
80
|
+
* {@link OperationKind} breaks compilation here, and a new parameter on any
|
|
81
|
+
* operation breaks compilation in that operation's entry.
|
|
82
|
+
*/
|
|
83
|
+
export declare const PARAM_SCHEMAS: {
|
|
84
|
+
[K in OperationKind]: OpSchema<K>;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* The STRUCTURAL parameter check for one operation. Returns the FIRST refusal
|
|
88
|
+
* detail (JSON path · expected shape · received type), or null when the bag is
|
|
89
|
+
* well-shaped. Never throws; never mutates or normalizes the params.
|
|
90
|
+
*/
|
|
91
|
+
export declare function validateOperationParams(op: OperationKind, params: unknown): string | null;
|
|
92
|
+
/** A structural parameter refusal — an input-contract error, never an app failure. */
|
|
93
|
+
export declare class ParamSchemaError extends RangeError {
|
|
94
|
+
/** The operation whose parameter bag was refused. */
|
|
95
|
+
readonly op: OperationKind;
|
|
96
|
+
constructor(op: OperationKind, detail: string);
|
|
97
|
+
}
|
|
98
|
+
/** {@link validateOperationParams}, as a throwing assertion for the pipeline. */
|
|
99
|
+
export declare function assertOperationParams(op: OperationKind, params: unknown): void;
|
|
100
|
+
/** One parameter's machine-readable summary (the `capabilities` params column). */
|
|
101
|
+
export interface ParamSummary {
|
|
102
|
+
name: string;
|
|
103
|
+
kind: FieldKind;
|
|
104
|
+
optional: boolean;
|
|
105
|
+
/** Behavioral description of the accepted shape. */
|
|
106
|
+
expects: string;
|
|
107
|
+
/** enum only: the accepted values. */
|
|
108
|
+
values?: readonly string[];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The per-op parameter summary `things capabilities` publishes, so the promise
|
|
112
|
+
* that the catalog carries "operation kinds AND their parameter shapes" is met by
|
|
113
|
+
* data rather than by prose.
|
|
114
|
+
*/
|
|
115
|
+
export declare function paramSummary(op: OperationKind): ParamSummary[];
|
|
116
|
+
/** Runtime completeness law: every cataloged operation declares a schema. */
|
|
117
|
+
export declare function operationsMissingSchema(): OperationKind[];
|
|
118
|
+
/** Every `unvalidated` escape in the registry, with its written reason (currently none). */
|
|
119
|
+
export declare function unvalidatedFields(): {
|
|
120
|
+
op: OperationKind;
|
|
121
|
+
field: string;
|
|
122
|
+
reason: string;
|
|
123
|
+
}[];
|
|
124
|
+
export {};
|