things-api 0.19.0 → 0.19.2
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 +3 -1
- package/deputy/prebuilt/Things API Helper.app/Contents/CodeResources +0 -0
- 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/MacOS/things-deputy +0 -0
- package/dist/audit/schema.d.ts +19 -2
- package/dist/audit/schema.js.map +1 -1
- package/dist/capability.d.ts +166 -4
- package/dist/capability.js +303 -13
- package/dist/capability.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +13 -1
- package/dist/cli/commands/doctor.js +52 -22
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/helpers.js +14 -3
- package/dist/cli/commands/helpers.js.map +1 -1
- package/dist/cli/commands/mcp.js +8 -0
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/repeat-flags.js +34 -2
- package/dist/cli/commands/repeat-flags.js.map +1 -1
- package/dist/cli/commands/setup.js +16 -3
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/ui-state.d.ts +11 -0
- package/dist/cli/commands/ui-state.js +27 -0
- package/dist/cli/commands/ui-state.js.map +1 -0
- package/dist/cli/commands/writes.js +102 -67
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/help.js +2 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/interrupt.d.ts +54 -6
- package/dist/cli/interrupt.js +78 -12
- package/dist/cli/interrupt.js.map +1 -1
- package/dist/cli/main.js +10 -5
- package/dist/cli/main.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/contracts.d.ts +4 -4
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/deputy/install.d.ts +15 -1
- package/dist/deputy/install.js +46 -6
- package/dist/deputy/install.js.map +1 -1
- package/dist/deputy/osa.d.ts +42 -2
- package/dist/deputy/osa.js +79 -5
- package/dist/deputy/osa.js.map +1 -1
- package/dist/deputy/routing.d.ts +34 -0
- package/dist/deputy/routing.js +95 -0
- package/dist/deputy/routing.js.map +1 -1
- package/dist/deputy/wake.d.ts +61 -0
- package/dist/deputy/wake.js +149 -0
- package/dist/deputy/wake.js.map +1 -0
- package/dist/diagnose.d.ts +6 -4
- package/dist/diagnose.js +20 -4
- package/dist/diagnose.js.map +1 -1
- package/dist/direct-setup.d.ts +31 -5
- package/dist/direct-setup.js +200 -26
- package/dist/direct-setup.js.map +1 -1
- package/dist/host-access.d.ts +12 -0
- package/dist/host-access.js +12 -0
- package/dist/host-access.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +23 -9
- package/dist/mcp/server.js.map +1 -1
- package/dist/op-result.js +8 -1
- package/dist/op-result.js.map +1 -1
- package/dist/session-grant.js +16 -1
- package/dist/session-grant.js.map +1 -1
- package/dist/surface-copy.d.ts +11 -3
- package/dist/surface-copy.js +11 -3
- package/dist/surface-copy.js.map +1 -1
- package/dist/ui-state.d.ts +46 -0
- package/dist/ui-state.js +82 -0
- package/dist/ui-state.js.map +1 -0
- package/dist/wizard.js +8 -1
- package/dist/wizard.js.map +1 -1
- package/dist/write/accessibility-probe.js +4 -1
- package/dist/write/accessibility-probe.js.map +1 -1
- package/dist/write/automation-probe.js +7 -1
- package/dist/write/automation-probe.js.map +1 -1
- package/dist/write/availability.d.ts +0 -15
- package/dist/write/availability.js +7 -62
- package/dist/write/availability.js.map +1 -1
- package/dist/write/batch.js +17 -6
- package/dist/write/batch.js.map +1 -1
- package/dist/write/commands.d.ts +10 -6
- package/dist/write/commands.js +120 -31
- package/dist/write/commands.js.map +1 -1
- package/dist/write/failure-hints.d.ts +36 -7
- package/dist/write/failure-hints.js +33 -14
- package/dist/write/failure-hints.js.map +1 -1
- package/dist/write/field-limits.d.ts +100 -0
- package/dist/write/field-limits.js +144 -0
- package/dist/write/field-limits.js.map +1 -0
- package/dist/write/guards.js +3 -2
- package/dist/write/guards.js.map +1 -1
- package/dist/write/move.js +9 -12
- package/dist/write/move.js.map +1 -1
- package/dist/write/operations.d.ts +15 -8
- package/dist/write/operations.js +9 -0
- package/dist/write/operations.js.map +1 -1
- package/dist/write/opid.d.ts +67 -23
- package/dist/write/opid.js +141 -19
- package/dist/write/opid.js.map +1 -1
- package/dist/write/param-schema.d.ts +17 -44
- package/dist/write/param-schema.js +74 -7
- package/dist/write/param-schema.js.map +1 -1
- package/dist/write/pipeline.d.ts +38 -7
- package/dist/write/pipeline.js +134 -18
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +30 -16
- package/dist/write/pre-state.js +88 -20
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/promote-clone.d.ts +26 -0
- package/dist/write/promote-clone.js +333 -41
- package/dist/write/promote-clone.js.map +1 -1
- package/dist/write/repeat-collateral.d.ts +31 -0
- package/dist/write/repeat-collateral.js +153 -0
- package/dist/write/repeat-collateral.js.map +1 -0
- package/dist/write/resolution-timestamps.js +25 -2
- package/dist/write/resolution-timestamps.js.map +1 -1
- package/dist/write/template-mutation.js +163 -16
- package/dist/write/template-mutation.js.map +1 -1
- package/dist/write/vectors/applescript.js +3 -10
- package/dist/write/vectors/applescript.js.map +1 -1
- package/dist/write/vectors/simulator.js +8 -2
- package/dist/write/vectors/simulator.js.map +1 -1
- package/dist/write/vectors/types.d.ts +236 -4
- package/dist/write/vectors/ui-certification.js +63 -13
- package/dist/write/vectors/ui-certification.js.map +1 -1
- package/dist/write/vectors/ui-chord.d.ts +144 -0
- package/dist/write/vectors/ui-chord.js +428 -0
- package/dist/write/vectors/ui-chord.js.map +1 -0
- package/dist/write/vectors/ui-drag.d.ts +8 -4
- package/dist/write/vectors/ui-drag.js +2 -0
- package/dist/write/vectors/ui-drag.js.map +1 -1
- package/dist/write/vectors/ui-recipes.d.ts +51 -3
- package/dist/write/vectors/ui-recipes.js +452 -44
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui-state.d.ts +157 -0
- package/dist/write/vectors/ui-state.js +237 -0
- package/dist/write/vectors/ui-state.js.map +1 -0
- package/dist/write/vectors/ui.d.ts +386 -13
- package/dist/write/vectors/ui.js +1543 -124
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/vectors/url-scheme.js +3 -0
- package/dist/write/vectors/url-scheme.js.map +1 -1
- package/dist/write/verify/delta.d.ts +41 -0
- package/dist/write/verify/delta.js +36 -2
- package/dist/write/verify/delta.js.map +1 -1
- package/dist/write/verify/poller.d.ts +4 -1
- package/dist/write/verify/poller.js +14 -0
- package/dist/write/verify/poller.js.map +1 -1
- package/package.json +1 -1
- package/schema/envelope.schema.json +2 -1
- package/skills/things-cli/SKILL.md +2 -2
package/dist/write/commands.js
CHANGED
|
@@ -2,6 +2,7 @@ import { localToday, zonedWallInstant } from "../model/dates.js";
|
|
|
2
2
|
import { byUuid } from "../read/detail.js";
|
|
3
3
|
import { manualLogDateEpoch, pendingLogCount } from "../read/log-boundary.js";
|
|
4
4
|
import { isLooseRef } from "../read/pseudo-area.js";
|
|
5
|
+
import { RESOLUTION_TIMESTAMP_EXPECTED } from "../surface-copy.js";
|
|
5
6
|
import { areaMemberCounts, childTagTitles, classifyHeadingConvert, classifyHeadingDissolve, classifyHeadingMoveToProject, classifyProjectRepeat, computeHeadingMovePre, computeReorderPre, emptyPreState, loadTarget, projectChildren, projectStatus, projectSubtreeUuids, resolveArea, resolveHeading, resolveProject, resolveTag, sameTitleTaskUuids, seriesRowUuids, trashedCount, } from "./pre-state.js";
|
|
6
7
|
import { assertNotesModesExclusive, normalizeReminder, updateAssertions, updateWireParams, whenAssertions, whenWithReminder, } from "./update-fields.js";
|
|
7
8
|
import { resolveTagRefs } from "./tag-refs.js";
|
|
@@ -10,7 +11,7 @@ import { assertRepeatRule } from "./repeat-rule.js";
|
|
|
10
11
|
import { assessOffRuleFirst, deadlineDriveNext, deriveFixedAnchor } from "./repeat-anchor.js";
|
|
11
12
|
import { expectedRuleAssertions } from "./repeat-asserts.js";
|
|
12
13
|
import { escapeAppleScript } from "./vectors/applescript.js";
|
|
13
|
-
import { areaReorderSidebarRecipe, convertToProjectRecipe, dissolveHeadingRecipe, headingConvertToProjectRecipe, moveHeadingToProjectRecipe, makeRepeatingRecipe, createNextCopyRecipe, pauseRepeatRecipe, projectMakeRepeatingRecipe, projectPauseRepeatRecipe, projectRescheduleRepeatRecipe, projectResumeRepeatRecipe, rescheduleRepeatRecipe, resumeRepeatRecipe, } from "./vectors/ui-recipes.js";
|
|
14
|
+
import { areaReorderSidebarRecipe, convertToProjectRecipe, dissolveHeadingRecipe, headingConvertToProjectRecipe, moveHeadingChordRecipe, moveHeadingToProjectRecipe, makeRepeatingRecipe, createNextCopyRecipe, pauseRepeatRecipe, projectMakeRepeatingRecipe, projectPauseRepeatRecipe, projectRescheduleRepeatRecipe, projectResumeRepeatRecipe, rescheduleRepeatRecipe, resumeRepeatRecipe, } from "./vectors/ui-recipes.js";
|
|
14
15
|
import { buildRepeatingFingerprint } from "./verify/delta.js";
|
|
15
16
|
// ------------------------------------------------------------------ helpers
|
|
16
17
|
function thingsUrl(command, params, token) {
|
|
@@ -1416,22 +1417,26 @@ const reorder = {
|
|
|
1416
1417
|
};
|
|
1417
1418
|
// ---- resolution-timestamp normalization (§5 of the plan) ------------------
|
|
1418
1419
|
/**
|
|
1419
|
-
* Parse
|
|
1420
|
-
*
|
|
1421
|
-
*
|
|
1422
|
-
*
|
|
1423
|
-
*
|
|
1424
|
-
*
|
|
1420
|
+
* Parse a date (`2025-01-15`) OR datetime (`2025-01-15T09:30[:ss]`, or the same
|
|
1421
|
+
* value spelled with a space — `2025-01-15 09:30`) and resolve it to a single
|
|
1422
|
+
* UTC instant in the effective `zone`. Both separators are first-class
|
|
1423
|
+
* spellings of the SAME instant: the space form is what a human (or a shell
|
|
1424
|
+
* heredoc) types, the `T` form is what a serializer emits, and neither is
|
|
1425
|
+
* rewritten into the other. A date-only value lands at NOON in that zone
|
|
1426
|
+
* (B-DATEONLY: noon decodes to the intended calendar date in every zone;
|
|
1427
|
+
* midnight can slip a day). A datetime is read as wall-clock time in the
|
|
1428
|
+
* effective zone. `zone` undefined = the process-local (app host) zone, which
|
|
1429
|
+
* for a local CLI run IS the app's own zone.
|
|
1425
1430
|
*/
|
|
1426
1431
|
export function resolveResolutionInstant(input, zone) {
|
|
1427
1432
|
const dateOnly = /^(\d{4}-\d{2}-\d{2})$/.exec(input);
|
|
1428
1433
|
if (dateOnly !== null)
|
|
1429
1434
|
return zonedWallInstant(dateOnly[1], 12, 0, 0, zone);
|
|
1430
|
-
const dt = /^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(input);
|
|
1435
|
+
const dt = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?$/.exec(input);
|
|
1431
1436
|
if (dt !== null) {
|
|
1432
1437
|
return zonedWallInstant(dt[1], Number(dt[2]), Number(dt[3]), dt[4] === undefined ? 0 : Number(dt[4]), zone);
|
|
1433
1438
|
}
|
|
1434
|
-
throw new RangeError(`invalid timestamp "${input}" — expected
|
|
1439
|
+
throw new RangeError(`invalid timestamp "${input}" — expected ${RESOLUTION_TIMESTAMP_EXPECTED}`);
|
|
1435
1440
|
}
|
|
1436
1441
|
const pad2 = (n) => String(n).padStart(2, "0");
|
|
1437
1442
|
/** The host-local calendar date (`YYYY-MM-DD`) an instant renders as — what the verify layer observes for stopped/created. */
|
|
@@ -1662,9 +1667,18 @@ const headingAdd = {
|
|
|
1662
1667
|
});
|
|
1663
1668
|
},
|
|
1664
1669
|
};
|
|
1670
|
+
/**
|
|
1671
|
+
* project.move-heading — within-project heading order, on the ARROW-CHORD ui
|
|
1672
|
+
* vector (CHORDMH1, on the HEADORD1 law). Things 3.23 left the private reorder
|
|
1673
|
+
* command declared and inert, which took heading order offline entirely; the
|
|
1674
|
+
* replacement is the app's own keyboard affordance (⌘↑/⌘↓/⌘⌥↑/⌘⌥↓ on a selected
|
|
1675
|
+
* heading row), driven as a verified closed loop by src/write/vectors/ui-chord.ts.
|
|
1676
|
+
* This is the ONE reorder that leaves the `privateReorderIsNoOp` range — every
|
|
1677
|
+
* other scope still routes through its own gate.
|
|
1678
|
+
*/
|
|
1665
1679
|
const projectMoveHeading = {
|
|
1666
1680
|
op: "project.move-heading",
|
|
1667
|
-
hazards: ["H-UNKNOWN-DESTINATION", "H-HEADING-ORDER"],
|
|
1681
|
+
hazards: ["H-UNKNOWN-DESTINATION", "H-HEADING-ORDER", "H-UI-DRIVE"],
|
|
1668
1682
|
preRead(db, params) {
|
|
1669
1683
|
const pre = emptyPreState();
|
|
1670
1684
|
pre.destProject = resolveProject(db, params.project);
|
|
@@ -1672,24 +1686,41 @@ const projectMoveHeading = {
|
|
|
1672
1686
|
return pre;
|
|
1673
1687
|
},
|
|
1674
1688
|
expectedDelta(pre) {
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1689
|
+
const move = pre.headingMove;
|
|
1690
|
+
return {
|
|
1691
|
+
mode: "ordering",
|
|
1692
|
+
key: "index",
|
|
1693
|
+
// The full end state: every heading of the project, strictly ascending.
|
|
1694
|
+
sequence: move?.targetOrder ?? [],
|
|
1695
|
+
// RRF1: the headings the caller did NOT name must hold their EXACT prior
|
|
1696
|
+
// rank — a chord is a single-row write, and this is what proves the one
|
|
1697
|
+
// that landed was the row the plan addressed (a heading row exposes no
|
|
1698
|
+
// title to read the selection back through).
|
|
1699
|
+
unchanged: move?.untouched ?? [],
|
|
1700
|
+
// Children follow their heading through an intact FK, un-renumbered and
|
|
1701
|
+
// un-touched (no userModificationDate bump — that is what `frozen` adds).
|
|
1702
|
+
frozen: (move?.children ?? []).map((c) => ({
|
|
1703
|
+
uuid: c.uuid,
|
|
1704
|
+
assert: [{ field: "heading.uuid", equals: c.heading }],
|
|
1705
|
+
})),
|
|
1706
|
+
...(move?.targetOrder[0] !== undefined && { subject: move.targetOrder[0] }),
|
|
1707
|
+
};
|
|
1679
1708
|
},
|
|
1680
|
-
compile(
|
|
1681
|
-
|
|
1682
|
-
// used (experimental — gated by allow-experimental + the sdef canary),
|
|
1683
|
-
// fed the computed full order.
|
|
1684
|
-
if (vector !== "applescript")
|
|
1709
|
+
compile(params, vector, pre) {
|
|
1710
|
+
if (vector !== "ui")
|
|
1685
1711
|
unsupportedVector(this.op, vector);
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1712
|
+
const move = pre.headingMove;
|
|
1713
|
+
if (move === null || move.problems.length > 0) {
|
|
1714
|
+
// The membership/anchor refusals are surfaced by H-HEADING-ORDER
|
|
1715
|
+
// before compile; reaching here with one means the guard was bypassed.
|
|
1716
|
+
throw new Error(`project.move-heading: ${move === null ? "no heading move computed (guard bypassed?)" : move.problems.join("; ")}`);
|
|
1717
|
+
}
|
|
1718
|
+
// The movee set is EXACTLY what the caller named — never derived from the
|
|
1719
|
+
// untouched set, which fences a different (smaller) thing: a bystander whose
|
|
1720
|
+
// POSITION shifts is still a bystander no chord may move.
|
|
1721
|
+
return uiDrive(moveHeadingChordRecipe(pre.destProject?.resolved?.uuid ?? "", move.targetOrder, [
|
|
1722
|
+
...params.headings,
|
|
1723
|
+
]));
|
|
1693
1724
|
},
|
|
1694
1725
|
};
|
|
1695
1726
|
const todoClearDatedReminder = {
|
|
@@ -1738,11 +1769,41 @@ function uiDrive(recipe) {
|
|
|
1738
1769
|
// the validator from commands.ts; the implementation + the full combination
|
|
1739
1770
|
// matrix live in repeat-rule.ts.
|
|
1740
1771
|
export { assertRepeatRule };
|
|
1772
|
+
/**
|
|
1773
|
+
* The recipe extras for a MAKE-REPEATING drive: {@link ruleExtras} with the
|
|
1774
|
+
* "Next:" drive date deadline-adjusted, exactly as {@link reschedRuleExtras}
|
|
1775
|
+
* does for a reschedule.
|
|
1776
|
+
*
|
|
1777
|
+
* ONE MEANING FOR `next`, ONE PLACE THAT SHIFTS IT (NEXTPOP1). `next` is the
|
|
1778
|
+
* requested first-occurrence START — what `--when` means to a caller — in every
|
|
1779
|
+
* params bag, at every layer. A DEADLINED rule anchors the dialog on the
|
|
1780
|
+
* DEADLINE (YANCH1 #493), so the date the "Next:" control must carry is
|
|
1781
|
+
* `next + startDaysEarlier`; that conversion belongs to the compile, where the
|
|
1782
|
+
* dialog is, and nowhere else.
|
|
1783
|
+
*
|
|
1784
|
+
* It used to happen upstream too: the promote orchestrators shifted `next`
|
|
1785
|
+
* before handing the bag to this op, so the SAME field meant a START coming from
|
|
1786
|
+
* a caller and a DUE date coming from a composite. Everything downstream that
|
|
1787
|
+
* shifts — `assessOffRuleFirst`, via `assertRepeatRule` in preRead — then shifted
|
|
1788
|
+
* a second time, and a deadlined MONTHLY promote was refused before it ran with
|
|
1789
|
+
* a message about a date the caller never asked for (`--deadline 2026-08-20`
|
|
1790
|
+
* + `--when 2026-08-06` → "a first occurrence on 2026-08-20 would not hold",
|
|
1791
|
+
* measured in-lab). The orchestrators now pass `--when` through unshifted.
|
|
1792
|
+
*/
|
|
1793
|
+
function makeRuleExtras(params) {
|
|
1794
|
+
const base = ruleExtras(params);
|
|
1795
|
+
const drive = deadlineDriveNext(params);
|
|
1796
|
+
return drive !== undefined ? { ...base, next: drive } : base;
|
|
1797
|
+
}
|
|
1741
1798
|
/**
|
|
1742
1799
|
* The extended-vocabulary fields of a rule as a recipe `extras` bag, including
|
|
1743
1800
|
* ONLY the keys that are present (exactOptionalPropertyTypes: never set an
|
|
1744
1801
|
* optional field to undefined). A bare `{ uuid, frequency, interval }` yields
|
|
1745
1802
|
* `{}`, so the recipe drives exactly the certified two-control path.
|
|
1803
|
+
*
|
|
1804
|
+
* `next` is copied through VERBATIM — a START. Every compile that drives the
|
|
1805
|
+
* dialog wraps this with its own deadline shift ({@link makeRuleExtras},
|
|
1806
|
+
* {@link reschedRuleExtras}); this function never shifts (NEXTPOP1).
|
|
1746
1807
|
*/
|
|
1747
1808
|
function ruleExtras(params) {
|
|
1748
1809
|
return {
|
|
@@ -1785,15 +1846,31 @@ function reschedEffParams(params) {
|
|
|
1785
1846
|
* `--when` is the scheduled START, but a deadlined rule anchors on the DEADLINE,
|
|
1786
1847
|
* so the dialog's "Next:" field is driven with `when + startDaysEarlier` and the
|
|
1787
1848
|
* app back-shifts the instance start to `--when`. The expectedDelta keeps the RAW
|
|
1788
|
-
* `params.next` (the cursor asserts the START).
|
|
1789
|
-
*
|
|
1790
|
-
*
|
|
1849
|
+
* `params.next` (the cursor asserts the START). {@link makeRuleExtras} is the
|
|
1850
|
+
* make/add-repeating twin of this — the shift lands in the compile on every verb
|
|
1851
|
+
* that drives the dialog, and nowhere upstream of it (NEXTPOP1).
|
|
1791
1852
|
*/
|
|
1792
1853
|
function reschedRuleExtras(params) {
|
|
1793
1854
|
const base = ruleExtras(reschedEffParams(params));
|
|
1794
1855
|
const drive = deadlineDriveNext(params);
|
|
1795
1856
|
return drive !== undefined ? { ...base, next: drive } : base;
|
|
1796
1857
|
}
|
|
1858
|
+
/**
|
|
1859
|
+
* The rule-vocabulary keys this reschedule REQUESTED — the input to the
|
|
1860
|
+
* unexplained-delta check (CGRD1 guard 3): every decoded-rule field that moves
|
|
1861
|
+
* must be attributable to one of these, or to a mapped co-mover of one.
|
|
1862
|
+
*
|
|
1863
|
+
* Built from the EFFECTIVE params, the same bag the recipe drives, so a
|
|
1864
|
+
* `--when`-only reschedule that DERIVES a calendar anchor counts that anchor as
|
|
1865
|
+
* requested rather than as an unexplained move (RSPA1 / YANCH1 #493) — the drive
|
|
1866
|
+
* really does address those pop-ups. `uuid` is the target, not a rule field.
|
|
1867
|
+
*/
|
|
1868
|
+
function requestedRuleKeys(params) {
|
|
1869
|
+
const eff = reschedEffParams(params);
|
|
1870
|
+
return Object.entries(eff)
|
|
1871
|
+
.filter(([key, value]) => key !== "uuid" && value !== undefined)
|
|
1872
|
+
.map(([key]) => key);
|
|
1873
|
+
}
|
|
1797
1874
|
/** ui ops all guard existence/type + the H-UI-DRIVE acknowledgement. */
|
|
1798
1875
|
const UI_HAZARDS = ["H-UNKNOWN-DESTINATION", "H-UI-DRIVE"];
|
|
1799
1876
|
const todoMakeRepeating = {
|
|
@@ -1841,7 +1918,7 @@ const todoMakeRepeating = {
|
|
|
1841
1918
|
compile(params, vector) {
|
|
1842
1919
|
if (vector !== "ui")
|
|
1843
1920
|
unsupportedVector(this.op, vector);
|
|
1844
|
-
return uiDrive(makeRepeatingRecipe(params.uuid, params.frequency, params.interval,
|
|
1921
|
+
return uiDrive(makeRepeatingRecipe(params.uuid, params.frequency, params.interval, makeRuleExtras(params)));
|
|
1845
1922
|
},
|
|
1846
1923
|
};
|
|
1847
1924
|
const todoRescheduleRepeat = {
|
|
@@ -1879,6 +1956,12 @@ const todoRescheduleRepeat = {
|
|
|
1879
1956
|
includeCursor: assessOffRuleFirst(eff)?.kind !== "honored",
|
|
1880
1957
|
}),
|
|
1881
1958
|
capture: [{ field: "repeating.rule" }, { field: "repeating.deadlined" }],
|
|
1959
|
+
// UNEXPLAINED-DELTA DETECTION (CGRD1 guard 3). The assertions above prove
|
|
1960
|
+
// the requested rule landed; this proves nothing ELSE did. A reschedule
|
|
1961
|
+
// rewrites an EXISTING rule, so there is a full pre-state to diff against —
|
|
1962
|
+
// which is why make-repeating / add-repeating do not carry it: they mint the
|
|
1963
|
+
// rule, so every field is new by construction and there is nothing to compare.
|
|
1964
|
+
collateral: { requested: requestedRuleKeys(params) },
|
|
1882
1965
|
};
|
|
1883
1966
|
},
|
|
1884
1967
|
compile(params, vector) {
|
|
@@ -2018,6 +2101,12 @@ const projectRescheduleRepeat = {
|
|
|
2018
2101
|
includeCursor: assessOffRuleFirst(eff)?.kind !== "honored",
|
|
2019
2102
|
}),
|
|
2020
2103
|
capture: [{ field: "repeating.rule" }, { field: "repeating.deadlined" }],
|
|
2104
|
+
// UNEXPLAINED-DELTA DETECTION (CGRD1 guard 3). The assertions above prove
|
|
2105
|
+
// the requested rule landed; this proves nothing ELSE did. A reschedule
|
|
2106
|
+
// rewrites an EXISTING rule, so there is a full pre-state to diff against —
|
|
2107
|
+
// which is why make-repeating / add-repeating do not carry it: they mint the
|
|
2108
|
+
// rule, so every field is new by construction and there is nothing to compare.
|
|
2109
|
+
collateral: { requested: requestedRuleKeys(params) },
|
|
2021
2110
|
};
|
|
2022
2111
|
},
|
|
2023
2112
|
compile(params, vector) {
|
|
@@ -2127,7 +2216,7 @@ const projectMakeRepeating = {
|
|
|
2127
2216
|
// Unreachable in practice: the guards block refuse/anytime before compile.
|
|
2128
2217
|
throw new Error("project.make-repeating: no selectable-row taxonomy resolved (guard bypassed?)");
|
|
2129
2218
|
}
|
|
2130
|
-
return uiDrive(projectMakeRepeatingRecipe(tax.containerReveal, params.uuid, tax.title, params.frequency, params.interval,
|
|
2219
|
+
return uiDrive(projectMakeRepeatingRecipe(tax.containerReveal, params.uuid, tax.title, params.frequency, params.interval, makeRuleExtras(params)));
|
|
2131
2220
|
},
|
|
2132
2221
|
};
|
|
2133
2222
|
// project.add-repeating is delivered by the runAddRepeatingProject
|