things-api 0.15.0 → 0.17.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 +4 -4
- package/dist/audit/schema.d.ts +8 -0
- package/dist/audit/schema.js.map +1 -1
- package/dist/cli/commands/install-skill.js +9 -2
- package/dist/cli/commands/install-skill.js.map +1 -1
- package/dist/cli/commands/repeat-flags.d.ts +14 -4
- package/dist/cli/commands/repeat-flags.js +113 -33
- package/dist/cli/commands/repeat-flags.js.map +1 -1
- package/dist/cli/commands/todo.js +49 -2
- package/dist/cli/commands/todo.js.map +1 -1
- package/dist/cli/commands/writes.js +241 -66
- package/dist/cli/commands/writes.js.map +1 -1
- package/dist/cli/help.js +23 -13
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/interrupt.d.ts +42 -0
- package/dist/cli/interrupt.js +105 -0
- package/dist/cli/interrupt.js.map +1 -0
- package/dist/cli/main.js +5 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/read-driver.d.ts +2 -2
- package/dist/cli/skill.d.ts +24 -0
- package/dist/cli/skill.js +40 -0
- package/dist/cli/skill.js.map +1 -1
- package/dist/client.d.ts +53 -12
- package/dist/client.js +9 -1
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +39 -0
- package/dist/config.js +16 -1
- package/dist/config.js.map +1 -1
- package/dist/contracts.d.ts +9 -2
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +132 -31
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/entities.d.ts +35 -0
- package/dist/model/entities.js.map +1 -1
- package/dist/model/occurrences.d.ts +14 -1
- package/dist/model/occurrences.js +20 -4
- package/dist/model/occurrences.js.map +1 -1
- package/dist/model/recurrence.d.ts +60 -9
- package/dist/model/recurrence.js +76 -19
- package/dist/model/recurrence.js.map +1 -1
- package/dist/paths.d.ts +8 -0
- package/dist/paths.js +10 -0
- package/dist/paths.js.map +1 -1
- package/dist/read/detail.js +49 -1
- package/dist/read/detail.js.map +1 -1
- package/dist/read/queries.d.ts +12 -0
- package/dist/read/queries.js +14 -0
- package/dist/read/queries.js.map +1 -1
- package/dist/read/shape.d.ts +25 -22
- package/dist/read/shape.js +81 -55
- package/dist/read/shape.js.map +1 -1
- package/dist/read/stage.d.ts +5 -5
- package/dist/read/stage.js +2 -2
- package/dist/read/views.d.ts +1 -1
- package/dist/read/views.js +4 -4
- package/dist/surface-copy.d.ts +2 -2
- package/dist/surface-copy.js +2 -2
- package/dist/sync-health.js +2 -1
- package/dist/sync-health.js.map +1 -1
- package/dist/trace/tracer.d.ts +87 -0
- package/dist/trace/tracer.js +167 -0
- package/dist/trace/tracer.js.map +1 -0
- package/dist/write/batch.d.ts +28 -3
- package/dist/write/batch.js +162 -46
- package/dist/write/batch.js.map +1 -1
- package/dist/write/clear-reminder.js +24 -21
- package/dist/write/clear-reminder.js.map +1 -1
- package/dist/write/clone.d.ts +4 -0
- package/dist/write/clone.js +531 -0
- package/dist/write/clone.js.map +1 -0
- package/dist/write/commands.js +140 -49
- package/dist/write/commands.js.map +1 -1
- package/dist/write/completion-context.d.ts +57 -0
- package/dist/write/completion-context.js +49 -0
- package/dist/write/completion-context.js.map +1 -0
- package/dist/write/failure-hints.d.ts +10 -1
- package/dist/write/failure-hints.js +8 -0
- package/dist/write/failure-hints.js.map +1 -1
- package/dist/write/guards.d.ts +1 -1
- package/dist/write/guards.js +43 -5
- package/dist/write/guards.js.map +1 -1
- package/dist/write/make-repeating-project.d.ts +2 -3
- package/dist/write/make-repeating-project.js +2 -73
- package/dist/write/make-repeating-project.js.map +1 -1
- package/dist/write/move.js +8 -1
- package/dist/write/move.js.map +1 -1
- package/dist/write/operations.d.ts +140 -9
- package/dist/write/operations.js +4 -1
- package/dist/write/operations.js.map +1 -1
- package/dist/write/pipeline.d.ts +77 -0
- package/dist/write/pipeline.js +298 -20
- package/dist/write/pipeline.js.map +1 -1
- package/dist/write/pre-state.d.ts +1 -1
- package/dist/write/pre-state.js +9 -3
- package/dist/write/pre-state.js.map +1 -1
- package/dist/write/preserve-modified.d.ts +55 -0
- package/dist/write/preserve-modified.js +106 -0
- package/dist/write/preserve-modified.js.map +1 -0
- package/dist/write/promote-clone.d.ts +32 -0
- package/dist/write/promote-clone.js +867 -0
- package/dist/write/promote-clone.js.map +1 -0
- package/dist/write/repeat-anchor.d.ts +110 -0
- package/dist/write/repeat-anchor.js +238 -0
- package/dist/write/repeat-anchor.js.map +1 -0
- package/dist/write/repeat-asserts.d.ts +28 -0
- package/dist/write/repeat-asserts.js +169 -0
- package/dist/write/repeat-asserts.js.map +1 -0
- package/dist/write/repeat-rule.js +27 -12
- package/dist/write/repeat-rule.js.map +1 -1
- package/dist/write/resolution-timestamps.js +22 -0
- package/dist/write/resolution-timestamps.js.map +1 -1
- package/dist/write/reversibility.js +27 -14
- package/dist/write/reversibility.js.map +1 -1
- package/dist/write/undo.d.ts +11 -1
- package/dist/write/undo.js +126 -10
- package/dist/write/undo.js.map +1 -1
- package/dist/write/vectors/session-reachability.d.ts +78 -0
- package/dist/write/vectors/session-reachability.js +103 -0
- package/dist/write/vectors/session-reachability.js.map +1 -0
- package/dist/write/vectors/simulator.js +100 -30
- package/dist/write/vectors/simulator.js.map +1 -1
- package/dist/write/vectors/types.d.ts +117 -10
- package/dist/write/vectors/ui-certification.d.ts +1 -1
- package/dist/write/vectors/ui-certification.js +10 -3
- package/dist/write/vectors/ui-certification.js.map +1 -1
- package/dist/write/vectors/ui-recipes.d.ts +8 -0
- package/dist/write/vectors/ui-recipes.js +120 -22
- package/dist/write/vectors/ui-recipes.js.map +1 -1
- package/dist/write/vectors/ui.d.ts +79 -13
- package/dist/write/vectors/ui.js +415 -59
- package/dist/write/vectors/ui.js.map +1 -1
- package/dist/write/verify/delta.d.ts +12 -14
- package/dist/write/verify/delta.js +35 -34
- package/dist/write/verify/delta.js.map +1 -1
- package/package.json +1 -1
- package/schema/envelope.schema.json +22 -0
- package/skills/things-cli/SKILL.md +7 -3
- package/skills/things-cli/references/banner.md +1 -1
- package/skills/things-cli/references/contracts.md +17 -9
- package/skills/things-cli/references/data-model.md +2 -1
package/dist/write/commands.js
CHANGED
|
@@ -7,6 +7,8 @@ import { areaMemberCounts, childTagTitles, classifyHeadingConvert, classifyHeadi
|
|
|
7
7
|
import { resolveTagRefs } from "./tag-refs.js";
|
|
8
8
|
import { PRIVATE_REORDER_COMMAND } from "./experimental.js";
|
|
9
9
|
import { assertRepeatRule } from "./repeat-rule.js";
|
|
10
|
+
import { deadlineDriveNext } from "./repeat-anchor.js";
|
|
11
|
+
import { expectedRuleAssertions } from "./repeat-asserts.js";
|
|
10
12
|
import { escapeAppleScript } from "./vectors/applescript.js";
|
|
11
13
|
import { areaReorderSidebarRecipe, convertToProjectRecipe, dissolveHeadingRecipe, headingConvertToProjectRecipe, moveHeadingToProjectRecipe, makeRepeatingRecipe, pauseRepeatRecipe, projectMakeRepeatingRecipe, projectPauseRepeatRecipe, projectRescheduleRepeatRecipe, projectResumeRepeatRecipe, rescheduleRepeatRecipe, resumeRepeatRecipe, } from "./vectors/ui-recipes.js";
|
|
12
14
|
import { buildRepeatingFingerprint } from "./verify/delta.js";
|
|
@@ -455,9 +457,12 @@ function statusSpec(op, urlParam, asStatus, scriptStatus) {
|
|
|
455
457
|
return {
|
|
456
458
|
op,
|
|
457
459
|
hazards: ["H-UNKNOWN-DESTINATION", "H-REPEAT-SCHEDULE"],
|
|
458
|
-
preRead(db, params) {
|
|
460
|
+
preRead(db, params, now, zone) {
|
|
459
461
|
const pre = emptyPreState();
|
|
460
|
-
|
|
462
|
+
// Load under the response clock so the target's Today marker (read by the
|
|
463
|
+
// HINTS1 completion-context) reflects the same calendar day the pipeline
|
|
464
|
+
// verifies under, not the host wall clock.
|
|
465
|
+
pre.target = loadTarget(db, params.uuid, now, zone);
|
|
461
466
|
return pre;
|
|
462
467
|
},
|
|
463
468
|
expectedDelta(_pre, params) {
|
|
@@ -644,6 +649,33 @@ function checklistItemsJsonAttr(specs) {
|
|
|
644
649
|
attributes: s.completed === undefined ? { title: s.title } : { title: s.title, completed: s.completed },
|
|
645
650
|
}));
|
|
646
651
|
}
|
|
652
|
+
/**
|
|
653
|
+
* Build a project json import's `items` array from a structured
|
|
654
|
+
* {@link ProjectItemSpec} list (the clone / rich-import path). Order IS the
|
|
655
|
+
* layout: a `heading` node produces a `{type:"heading"}` row and every following
|
|
656
|
+
* `to-do` node inherits it positionally (A4); a `to-do` before the first heading
|
|
657
|
+
* is a project-root child. Children are born OPEN — no `completed` attribute.
|
|
658
|
+
*/
|
|
659
|
+
function projectItemsJsonAttr(items) {
|
|
660
|
+
return items.map((it) => {
|
|
661
|
+
if (it.kind === "heading") {
|
|
662
|
+
return { type: "heading", attributes: { title: it.title } };
|
|
663
|
+
}
|
|
664
|
+
const attrs = { title: it.title };
|
|
665
|
+
if (it.notes !== undefined)
|
|
666
|
+
attrs["notes"] = it.notes;
|
|
667
|
+
if (it.when !== undefined)
|
|
668
|
+
attrs["when"] = it.when;
|
|
669
|
+
if (it.deadline !== undefined)
|
|
670
|
+
attrs["deadline"] = it.deadline;
|
|
671
|
+
if (it.tags !== undefined)
|
|
672
|
+
attrs["tags"] = it.tags;
|
|
673
|
+
if (it.checklistItems !== undefined) {
|
|
674
|
+
attrs["checklist-items"] = checklistItemsJsonAttr(it.checklistItems.map((title) => ({ title })));
|
|
675
|
+
}
|
|
676
|
+
return { type: "to-do", attributes: attrs };
|
|
677
|
+
});
|
|
678
|
+
}
|
|
647
679
|
function checklistSpecs(items) {
|
|
648
680
|
const specs = items.map((i) => typeof i === "string"
|
|
649
681
|
? { title: i, completed: false }
|
|
@@ -715,6 +747,28 @@ const todoEditChecklistItem = {
|
|
|
715
747
|
throw new Error(ORCHESTRATED_ONLY);
|
|
716
748
|
},
|
|
717
749
|
};
|
|
750
|
+
const CLONE_ORCHESTRATED_ONLY = "todo.clone / project.clone are delivered by the runCloneTodo / runCloneProject orchestrators (a " +
|
|
751
|
+
"compound over todo.add / project.add plus checklist / terminal-state follow-up legs); they have " +
|
|
752
|
+
"no atomic surface and are never dispatched directly through the pipeline";
|
|
753
|
+
function cloneStub(op) {
|
|
754
|
+
return {
|
|
755
|
+
op,
|
|
756
|
+
hazards: [],
|
|
757
|
+
preRead(db, params) {
|
|
758
|
+
const pre = emptyPreState();
|
|
759
|
+
pre.target = loadTarget(db, params.uuid);
|
|
760
|
+
return pre;
|
|
761
|
+
},
|
|
762
|
+
expectedDelta() {
|
|
763
|
+
throw new Error(CLONE_ORCHESTRATED_ONLY);
|
|
764
|
+
},
|
|
765
|
+
compile() {
|
|
766
|
+
throw new Error(CLONE_ORCHESTRATED_ONLY);
|
|
767
|
+
},
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
const todoClone = cloneStub("todo.clone");
|
|
771
|
+
const projectClone = cloneStub("project.clone");
|
|
718
772
|
const todoDelete = {
|
|
719
773
|
op: "todo.delete",
|
|
720
774
|
hazards: ["H-UNKNOWN-DESTINATION", "H-REPEAT-SCHEDULE"],
|
|
@@ -744,6 +798,13 @@ const projectAdd = {
|
|
|
744
798
|
throw new RangeError("--completed-at cannot seed child to-dos: a completed-project import reverts to open " +
|
|
745
799
|
"unless every child is resolved (§5b) — create the project resolved, then add logged children");
|
|
746
800
|
}
|
|
801
|
+
if (params.todos !== undefined && params.items !== undefined) {
|
|
802
|
+
throw new RangeError("project.add takes either `todos` or structured `items`, not both");
|
|
803
|
+
}
|
|
804
|
+
if (params.completedAt !== undefined && params.items !== undefined && params.items.length > 0) {
|
|
805
|
+
throw new RangeError("--completed-at cannot seed child items: a completed-project import reverts to open " +
|
|
806
|
+
"unless every child is resolved (§5b)");
|
|
807
|
+
}
|
|
747
808
|
const pre = emptyPreState();
|
|
748
809
|
if (containerGiven(params.area))
|
|
749
810
|
pre.destArea = resolveArea(db, params.area);
|
|
@@ -779,7 +840,9 @@ const projectAdd = {
|
|
|
779
840
|
compile(params, vector, pre, ctx) {
|
|
780
841
|
if (vector !== "url-scheme")
|
|
781
842
|
unsupportedVector(this.op, vector);
|
|
782
|
-
|
|
843
|
+
// The json import is required for born-timestamps AND for structured `items`
|
|
844
|
+
// (headings / rich children) — the plain add-project URL carries neither.
|
|
845
|
+
if (addHasTimestamps(params) || params.items !== undefined) {
|
|
783
846
|
const attrs = { title: params.title };
|
|
784
847
|
if (params.notes !== undefined)
|
|
785
848
|
attrs["notes"] = params.notes;
|
|
@@ -789,7 +852,10 @@ const projectAdd = {
|
|
|
789
852
|
attrs["when"] = params.when;
|
|
790
853
|
if (params.deadline !== undefined)
|
|
791
854
|
attrs["deadline"] = params.deadline;
|
|
792
|
-
if (params.
|
|
855
|
+
if (params.items !== undefined) {
|
|
856
|
+
attrs["items"] = projectItemsJsonAttr(params.items);
|
|
857
|
+
}
|
|
858
|
+
else if (params.todos !== undefined) {
|
|
793
859
|
attrs["items"] = params.todos.map((t) => ({ type: "to-do", attributes: { title: t } }));
|
|
794
860
|
}
|
|
795
861
|
}
|
|
@@ -1086,7 +1152,10 @@ const projectReopen = {
|
|
|
1086
1152
|
};
|
|
1087
1153
|
const projectRestore = {
|
|
1088
1154
|
op: "project.restore",
|
|
1089
|
-
|
|
1155
|
+
// H-REPEAT-SCHEDULE: a trashed repeating PROJECT template cannot be restored
|
|
1156
|
+
// headlessly (Put Back only) — refuse categorically instead of the raw AS-301
|
|
1157
|
+
// no-op. (The to-do path already carries it; kind-parity, 2026-08-13.)
|
|
1158
|
+
hazards: ["H-UNKNOWN-DESTINATION", "H-REPEAT-SCHEDULE"],
|
|
1090
1159
|
preRead(db, params) {
|
|
1091
1160
|
const pre = emptyPreState();
|
|
1092
1161
|
pre.target = loadTarget(db, params.uuid);
|
|
@@ -1848,8 +1917,23 @@ function ruleExtras(params) {
|
|
|
1848
1917
|
...(params.reminder !== undefined && { reminder: params.reminder }),
|
|
1849
1918
|
...(params.deadline !== undefined && { deadline: params.deadline }),
|
|
1850
1919
|
...(params.startDaysEarlier !== undefined && { startDaysEarlier: params.startDaysEarlier }),
|
|
1920
|
+
...(params.next !== undefined && { next: params.next }),
|
|
1851
1921
|
};
|
|
1852
1922
|
}
|
|
1923
|
+
/**
|
|
1924
|
+
* Recipe extras for a RESCHEDULE, with the "Next:" drive date deadline-adjusted
|
|
1925
|
+
* (YANCH1 #493): `--when` is the scheduled START, but a deadlined rule anchors on
|
|
1926
|
+
* the DEADLINE, so the dialog's "Next:" field is driven with `when +
|
|
1927
|
+
* startDaysEarlier` and the app back-shifts the instance start to `--when`. The
|
|
1928
|
+
* expectedDelta keeps the RAW `params.next` (the cursor asserts the START).
|
|
1929
|
+
* make/add-repeating apply this shift upstream (promote-clone.ts) and pass an
|
|
1930
|
+
* already-adjusted rule, so only the reschedule compile needs it here.
|
|
1931
|
+
*/
|
|
1932
|
+
function reschedRuleExtras(params) {
|
|
1933
|
+
const base = ruleExtras(params);
|
|
1934
|
+
const drive = deadlineDriveNext(params);
|
|
1935
|
+
return drive !== undefined ? { ...base, next: drive } : base;
|
|
1936
|
+
}
|
|
1853
1937
|
/** ui ops all guard existence/type + the H-UI-DRIVE acknowledgement. */
|
|
1854
1938
|
const UI_HAZARDS = ["H-UNKNOWN-DESTINATION", "H-UI-DRIVE"];
|
|
1855
1939
|
const todoMakeRepeating = {
|
|
@@ -1870,9 +1954,12 @@ const todoMakeRepeating = {
|
|
|
1870
1954
|
// rows), pick it by asserting it IS a template, then the `repeating` context
|
|
1871
1955
|
// hardens discovery (restored time-bound, source-fingerprint tiebreak) and
|
|
1872
1956
|
// derives instance + source fate for the enriched result. `expectedRule`
|
|
1873
|
-
// makes the LANDED rule verifiable: a template minted
|
|
1874
|
-
// frequency/interval (the interval-field race, oddities §8l)
|
|
1875
|
-
// verify-failed:mismatch instead
|
|
1957
|
+
// makes the LANDED rule verifiable at FULL fidelity (#491): a template minted
|
|
1958
|
+
// with the wrong frequency/interval (the interval-field race, oddities §8l) OR
|
|
1959
|
+
// a dropped anchor / ends / deadline becomes a verify-failed:mismatch instead
|
|
1960
|
+
// of a silent ok. includeCursor:false — the fresh template's cursor follows
|
|
1961
|
+
// the app's spawn law (ANCH1), not the raw --when, so make verifies the rule
|
|
1962
|
+
// BLOB + deadline, not the cursor.
|
|
1876
1963
|
return {
|
|
1877
1964
|
mode: "create",
|
|
1878
1965
|
probe: {
|
|
@@ -1884,11 +1971,7 @@ const todoMakeRepeating = {
|
|
|
1884
1971
|
repeating: {
|
|
1885
1972
|
sourceUuid: pre.target.uuid,
|
|
1886
1973
|
fingerprint: buildRepeatingFingerprint(pre.target),
|
|
1887
|
-
expectedRule: {
|
|
1888
|
-
type: params.afterCompletion === true ? "after-completion" : "fixed",
|
|
1889
|
-
unit: params.frequency,
|
|
1890
|
-
interval: params.interval,
|
|
1891
|
-
},
|
|
1974
|
+
expectedRule: expectedRuleAssertions(params, { includeCursor: false }),
|
|
1892
1975
|
},
|
|
1893
1976
|
}),
|
|
1894
1977
|
},
|
|
@@ -1911,33 +1994,26 @@ const todoRescheduleRepeat = {
|
|
|
1911
1994
|
return pre;
|
|
1912
1995
|
},
|
|
1913
1996
|
expectedDelta(_pre, params) {
|
|
1914
|
-
// Identity PRESERVED (UI2-b): the same template uuid, rule mutated in
|
|
1915
|
-
//
|
|
1916
|
-
//
|
|
1917
|
-
//
|
|
1918
|
-
//
|
|
1919
|
-
//
|
|
1920
|
-
//
|
|
1921
|
-
//
|
|
1922
|
-
//
|
|
1997
|
+
// Identity PRESERVED (UI2-b): the same template uuid, rule mutated in place.
|
|
1998
|
+
// Assert the FULL requested rule (#491) — type + unit + interval + calendar
|
|
1999
|
+
// anchor + ends bound + deadline offset + the ANCH2 first-occurrence cursor —
|
|
2000
|
+
// built from the complete vocabulary by expectedRuleAssertions so the pre-drive
|
|
2001
|
+
// idempotency check skips ONLY when EVERY requested field already holds, and
|
|
2002
|
+
// the post-drive verify catches a wrong-anchor landing. A shallow unit+interval
|
|
2003
|
+
// subset false-noop'd a reschedule that changed only the monthly anchor /
|
|
2004
|
+
// deadline / ends (#491). ALSO capture the whole prior rule (+ deadline flag)
|
|
2005
|
+
// so the undo can re-drive it faithfully.
|
|
1923
2006
|
return {
|
|
1924
2007
|
mode: "update",
|
|
1925
2008
|
uuid: params.uuid,
|
|
1926
|
-
assert:
|
|
1927
|
-
{
|
|
1928
|
-
field: "repeating.rule.type",
|
|
1929
|
-
equals: params.afterCompletion === true ? "after-completion" : "fixed",
|
|
1930
|
-
},
|
|
1931
|
-
{ field: "repeating.rule.unit", equals: params.frequency },
|
|
1932
|
-
{ field: "repeating.rule.interval", equals: params.interval },
|
|
1933
|
-
],
|
|
2009
|
+
assert: expectedRuleAssertions(params, { includeCursor: true }),
|
|
1934
2010
|
capture: [{ field: "repeating.rule" }, { field: "repeating.deadlined" }],
|
|
1935
2011
|
};
|
|
1936
2012
|
},
|
|
1937
2013
|
compile(params, vector) {
|
|
1938
2014
|
if (vector !== "ui")
|
|
1939
2015
|
unsupportedVector(this.op, vector);
|
|
1940
|
-
return uiDrive(rescheduleRepeatRecipe(params.uuid, params.frequency, params.interval,
|
|
2016
|
+
return uiDrive(rescheduleRepeatRecipe(params.uuid, params.frequency, params.interval, reschedRuleExtras(params)));
|
|
1941
2017
|
},
|
|
1942
2018
|
};
|
|
1943
2019
|
const todoPauseRepeat = {
|
|
@@ -2002,26 +2078,20 @@ const projectRescheduleRepeat = {
|
|
|
2002
2078
|
expectedDelta(_pre, params) {
|
|
2003
2079
|
// Identity PRESERVED (UIC2-a): same project uuid, rule mutated in place;
|
|
2004
2080
|
// capture the prior rule (+ deadline flag) for the faithful undo. Assert the
|
|
2005
|
-
//
|
|
2006
|
-
// unit+interval
|
|
2081
|
+
// FULL requested rule (#491) via expectedRuleAssertions — same completeness as
|
|
2082
|
+
// todo.reschedule-repeat (a shallow unit+interval subset false-noop'd an
|
|
2083
|
+
// anchor/deadline/ends-only reschedule).
|
|
2007
2084
|
return {
|
|
2008
2085
|
mode: "update",
|
|
2009
2086
|
uuid: params.uuid,
|
|
2010
|
-
assert:
|
|
2011
|
-
{
|
|
2012
|
-
field: "repeating.rule.type",
|
|
2013
|
-
equals: params.afterCompletion === true ? "after-completion" : "fixed",
|
|
2014
|
-
},
|
|
2015
|
-
{ field: "repeating.rule.unit", equals: params.frequency },
|
|
2016
|
-
{ field: "repeating.rule.interval", equals: params.interval },
|
|
2017
|
-
],
|
|
2087
|
+
assert: expectedRuleAssertions(params, { includeCursor: true }),
|
|
2018
2088
|
capture: [{ field: "repeating.rule" }, { field: "repeating.deadlined" }],
|
|
2019
2089
|
};
|
|
2020
2090
|
},
|
|
2021
2091
|
compile(params, vector) {
|
|
2022
2092
|
if (vector !== "ui")
|
|
2023
2093
|
unsupportedVector(this.op, vector);
|
|
2024
|
-
return uiDrive(projectRescheduleRepeatRecipe(params.uuid, params.frequency, params.interval,
|
|
2094
|
+
return uiDrive(projectRescheduleRepeatRecipe(params.uuid, params.frequency, params.interval, reschedRuleExtras(params)));
|
|
2025
2095
|
},
|
|
2026
2096
|
};
|
|
2027
2097
|
const projectPauseRepeat = {
|
|
@@ -2070,7 +2140,7 @@ const projectResumeRepeat = {
|
|
|
2070
2140
|
};
|
|
2071
2141
|
// project.make-repeating: the pure-AX row-selection op (UIC4). The command
|
|
2072
2142
|
// spec drives the area / someday cases; the area-less-anytime coercion is done
|
|
2073
|
-
// by the
|
|
2143
|
+
// by the promoteProjectViaGui internal orchestrator BEFORE this spec sees the target,
|
|
2074
2144
|
// so by drive time the taxonomy is always area or someday. A DIRECT dispatch on
|
|
2075
2145
|
// an anytime project is refused by H-PROJECT-REPEAT (with the orchestrator as
|
|
2076
2146
|
// the remediation).
|
|
@@ -2094,7 +2164,10 @@ const projectMakeRepeating = {
|
|
|
2094
2164
|
// the current-occurrence instance. Pick the TEMPLATE by asserting it IS one,
|
|
2095
2165
|
// excluding pre-existing same-title rows; the `repeating` context hardens
|
|
2096
2166
|
// discovery and derives instance + source fate + childrenReplaced.
|
|
2097
|
-
// `expectedRule` makes the landed rule verifiable
|
|
2167
|
+
// `expectedRule` makes the landed rule verifiable at FULL fidelity (#491):
|
|
2168
|
+
// a wrong frequency/interval (interval-race §8l) OR a dropped anchor/ends/
|
|
2169
|
+
// deadline is a mismatch, not a silent ok. includeCursor:false — the fresh
|
|
2170
|
+
// template's cursor follows the ANCH1 spawn law, not the raw --when.
|
|
2098
2171
|
return {
|
|
2099
2172
|
mode: "create",
|
|
2100
2173
|
probe: {
|
|
@@ -2107,11 +2180,7 @@ const projectMakeRepeating = {
|
|
|
2107
2180
|
sourceUuid: pre.target.uuid,
|
|
2108
2181
|
fingerprint: buildRepeatingFingerprint(pre.target),
|
|
2109
2182
|
subtreeUuids: pre.repeatSubtreeUuids ?? [],
|
|
2110
|
-
expectedRule: {
|
|
2111
|
-
type: params.afterCompletion === true ? "after-completion" : "fixed",
|
|
2112
|
-
unit: params.frequency,
|
|
2113
|
-
interval: params.interval,
|
|
2114
|
-
},
|
|
2183
|
+
expectedRule: expectedRuleAssertions(params, { includeCursor: false }),
|
|
2115
2184
|
},
|
|
2116
2185
|
}),
|
|
2117
2186
|
},
|
|
@@ -2148,6 +2217,25 @@ const projectAddRepeating = {
|
|
|
2148
2217
|
throw new Error(ADD_REPEATING_ORCHESTRATED);
|
|
2149
2218
|
},
|
|
2150
2219
|
};
|
|
2220
|
+
// todo.add-repeating is delivered by the runAddRepeatingTodo orchestrator
|
|
2221
|
+
// (todo.add THEN native promote); it has no atomic surface and is never
|
|
2222
|
+
// dispatched directly through the pipeline (promote-clone.ts).
|
|
2223
|
+
const TODO_ADD_REPEATING_ORCHESTRATED = "todo.add-repeating is delivered by the runAddRepeatingTodo orchestrator (create the to-do, " +
|
|
2224
|
+
"then promote it to a repeating series); it has no atomic surface and is never dispatched " +
|
|
2225
|
+
"directly through the pipeline";
|
|
2226
|
+
const todoAddRepeating = {
|
|
2227
|
+
op: "todo.add-repeating",
|
|
2228
|
+
hazards: [],
|
|
2229
|
+
preRead() {
|
|
2230
|
+
return emptyPreState();
|
|
2231
|
+
},
|
|
2232
|
+
expectedDelta() {
|
|
2233
|
+
throw new Error(TODO_ADD_REPEATING_ORCHESTRATED);
|
|
2234
|
+
},
|
|
2235
|
+
compile() {
|
|
2236
|
+
throw new Error(TODO_ADD_REPEATING_ORCHESTRATED);
|
|
2237
|
+
},
|
|
2238
|
+
};
|
|
2151
2239
|
const todoConvertToProject = {
|
|
2152
2240
|
op: "todo.convert-to-project",
|
|
2153
2241
|
hazards: UI_HAZARDS,
|
|
@@ -2489,6 +2577,9 @@ export const COMMANDS = {
|
|
|
2489
2577
|
"area.reorder": areaReorderSidebar,
|
|
2490
2578
|
"project.make-repeating": projectMakeRepeating,
|
|
2491
2579
|
"project.add-repeating": projectAddRepeating,
|
|
2580
|
+
"todo.add-repeating": todoAddRepeating,
|
|
2581
|
+
"todo.clone": todoClone,
|
|
2582
|
+
"project.clone": projectClone,
|
|
2492
2583
|
"log-now": logNow,
|
|
2493
2584
|
};
|
|
2494
2585
|
//# sourceMappingURL=commands.js.map
|