@hasna/todos 0.13.12 → 0.14.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.
@@ -1,3 +1,42 @@
1
1
  import type { Command } from "commander";
2
+ /**
3
+ * Rows that are the SAME identity as `requested` under the canonical
4
+ * case-insensitive rule, but are spelled differently — i.e. the rows that
5
+ * registering `requested` would turn into a case-variant clash.
6
+ *
7
+ * WHY THIS GUARD IS ON THE CLOUD BRANCH AND NOT SHARED (todos task 1170f87b).
8
+ * `init` has two branches. The LOCAL one goes through `db/agents.ts`, whose
9
+ * `validateAgentName` RETURNS the lower-cased name, so a case variant cannot
10
+ * be created there. The CLOUD one posts the raw argument straight to
11
+ * `/v1/agents`. Every station on this fleet is cloud-routed, so 100% of
12
+ * registrations took the unnormalised branch and the shared normaliser —
13
+ * documented in `lib/agent-name-normalize.ts` as "the single source of truth"
14
+ * for `fabricius`, `Fabricius` and `FABRICIUS` being ONE agent — was never
15
+ * consulted. Measured on the live roster 2026-08-02: 1291 rows, 75 names held
16
+ * in two or more capitalisations, 7 of those clashes minted since 07-29.
17
+ *
18
+ * WHY IT REFUSES RATHER THAN SILENTLY LOWER-CASING. Normalising here would
19
+ * redirect a session that registers as `Silvanus` onto the existing
20
+ * `silvanus` row — merging two mailboxes with nothing on screen to say so.
21
+ * The live consequence of these split identities is that
22
+ * `todos list --assigned Silvanus` and `--assigned silvanus` return disjoint
23
+ * sets (28 and 29 rows, intersection 0), so silently moving an agent between
24
+ * them would change which queue a running watcher reads. A refusal is
25
+ * visible; a silent redirect is another instance of the defect being fixed.
26
+ *
27
+ * WHY IT DOES NOT CALL `validateAgentName` FOR SYMMETRY WITH THE LOCAL PATH.
28
+ * That validator enforces `/^[a-z]+$/` — letters only. 283 of the 1291 live
29
+ * names (21.9%) fail it, including every seat (`agent-ceo`,
30
+ * `agent-chief-staff`, ...). Applying it here would make registration fail for
31
+ * a fifth of the fleet. Only the trim-and-lower-case normaliser is safe.
32
+ *
33
+ * An EXACT-spelling row is deliberately NOT a conflict: re-registering an
34
+ * identity that already exists is the ordinary restart path, and refusing it
35
+ * would break every agent on the fleet rather than only the typos.
36
+ */
37
+ export declare function findCaseVariantRows<T extends {
38
+ id: string;
39
+ name: string;
40
+ }>(agents: readonly T[], requested: string): T[];
2
41
  export declare function registerAgentCommands(program: Command): void;
3
42
  //# sourceMappingURL=agent-commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/agent-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8DzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAsgBrD"}
1
+ {"version":3,"file":"agent-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/agent-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoDzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACxE,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,SAAS,EAAE,MAAM,GAChB,CAAC,EAAE,CAML;AAYD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QAuiBrD"}
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dispatch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWzC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuL/D"}
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/dispatch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8L/D"}
@@ -1 +1 @@
1
- {"version":3,"file":"project-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/project-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6OzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QAwkCvD"}
1
+ {"version":3,"file":"project-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/project-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2QzC,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,QA+kCvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"task-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/task-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0DzC,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ5D;AAkPD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAqiDpD"}
1
+ {"version":3,"file":"task-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/task-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4DzC,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ5D;AAqPD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QA2iDpD"}
@@ -1,6 +1,7 @@
1
1
  import type { HasnaStorageClient } from "@hasna/contracts/client/storage";
2
+ import { type EnumVocabularySpec } from "../lib/enum-vocabulary.js";
2
3
  import { getPackageVersion } from "../lib/package-version.js";
3
- import type { Project, Task } from "../types/index.js";
4
+ import type { Project, Task, TaskPriority, TaskStatus } from "../types/index.js";
4
5
  export { getPackageVersion };
5
6
  /**
6
7
  * Detect whether the invocation requested JSON output, from raw argv.
@@ -24,6 +25,11 @@ export declare function jsonModeRequested(argv?: readonly string[]): boolean;
24
25
  * Keeping stderr populated in JSON mode preserves the CLI's long-standing
25
26
  * human-facing diagnostics (and every test that asserts them) while adding the
26
27
  * stdout envelope machine callers rely on.
28
+ *
29
+ * When the error is a remote HTTP failure whose body carries the authority's
30
+ * own `{"error": "<reason>"}`, that reason is appended to the message (both on
31
+ * stderr and in the --json envelope) rather than silently dropped — see
32
+ * `remoteErrorDetail` above.
27
33
  */
28
34
  export declare function handleError(e: unknown): never;
29
35
  /**
@@ -75,11 +81,67 @@ export declare function autoDetectProject(opts: {
75
81
  export declare function autoProject(opts: {
76
82
  project?: string;
77
83
  }): string | undefined;
78
- /** Normalize user-friendly status aliases to canonical TaskStatus values */
84
+ /**
85
+ * Normalize user-friendly status aliases to canonical TaskStatus values.
86
+ *
87
+ * Case and surrounding whitespace are folded away for EVERY input, not just the
88
+ * aliases below. Previously the alias switch lower-cased its subject but the
89
+ * default branch returned the caller's string verbatim, so `--status Pending`
90
+ * survived as `Pending`, missed the vocabulary, matched no rows, and printed
91
+ * "No tasks found." with exit 0. Every canonical status in `TASK_STATUSES` is
92
+ * lower-case, so folding is lossless: it cannot collide two distinct members.
93
+ */
79
94
  export declare function normalizeStatus(s: string): string;
95
+ /**
96
+ * Fold case/whitespace on a priority value. `TASK_PRIORITIES` is all lower-case
97
+ * and carries no aliases, so folding is the whole canonicalization.
98
+ */
99
+ export declare function normalizePriority(p: string): string;
80
100
  export declare function normalizeStatusList(statuses: string | string[]): string | string[];
101
+ /**
102
+ * Remediation hints for status inputs operators plausibly type that are NOT
103
+ * statuses. These are never accepted as values — `resolveEnumVocabulary` still
104
+ * rejects them non-zero — they only make the rejection actionable.
105
+ *
106
+ * `all` earns a hint because it is the most dangerous near-miss in the set: it
107
+ * reads as "everything" and used to return the empty set with exit 0. The flag
108
+ * that actually widens the status filter is `-a`/`--all`.
109
+ */
110
+ export declare const TASK_STATUS_FLAG_HINTS: Readonly<Record<string, string>>;
111
+ /**
112
+ * Validate a closed-vocabulary flag value and exit non-zero when it is not in the
113
+ * vocabulary, instead of letting it reach storage and return an empty result set.
114
+ *
115
+ * Uses `handleError`, so the failure shape matches what `todos list` already does
116
+ * for `--sort`, `--format` and `--project-name`: red message on stderr, exit 1,
117
+ * plus the `{"error":...}` stdout envelope under `--json`.
118
+ *
119
+ * Returns a bare string for a single value and an array for a comma-separated
120
+ * list, matching the `TaskFilter` field types and keeping the generated query
121
+ * identical to the pre-validation behaviour for single-value callers.
122
+ */
123
+ export declare function parseEnumFlag<T extends string>(raw: string | undefined, spec: EnumVocabularySpec<T>): T | T[] | undefined;
124
+ /** Same as `parseEnumFlag` but always an array, for callers whose filter field is a list. */
125
+ export declare function parseEnumFlagList<T extends string>(raw: string | undefined, spec: EnumVocabularySpec<T>): T[] | undefined;
126
+ /** Vocabulary spec for any `--status` flag over the canonical task statuses. */
127
+ export declare const TASK_STATUS_FLAG: EnumVocabularySpec<TaskStatus>;
128
+ /** Vocabulary spec for any `--priority` flag over the canonical task priorities. */
129
+ export declare const TASK_PRIORITY_FLAG: EnumVocabularySpec<TaskPriority>;
81
130
  export declare function printJson(data: unknown): void;
82
131
  export declare function output(data: unknown, jsonMode: boolean): void;
132
+ /**
133
+ * Emit one entity on stdout in BOTH modes.
134
+ *
135
+ * `output()` prints only under `--json`, so call sites that used it as their only
136
+ * emitter exited 0 with completely empty stdout in human mode — including two
137
+ * mutations (`projects --update`, `lists --update`) that gave no sign the write
138
+ * had landed. Those call sites use this instead. JSON mode is unchanged: it goes
139
+ * through the same `printJson`, byte for byte.
140
+ *
141
+ * Call sites that already print their own human rendering after `output()` must
142
+ * keep using `output()`, otherwise they would print twice.
143
+ */
144
+ export declare function outputRecord(data: unknown, jsonMode: boolean, heading?: string): void;
83
145
  export declare const statusColors: Record<string, (s: string) => string>;
84
146
  export declare const priorityColors: Record<string, (s: string) => string>;
85
147
  export declare function formatTaskLine(t: Task): string;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAI1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAK7B;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,SAAS,MAAM,EAAiB,GAAG,OAAO,CAMjF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAO7C;AAKD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAmDvD;AAED,mFAAmF;AACnF,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,kBAAkB,GAAG,IAA4B,GACvD,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED,KAAK,6BAA6B,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAgEtE;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,6BAA6B,GAAG,OAAO,CAU1F;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAM7C;AAQD,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAMxE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAgC7D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,GAAG,SAAS,CAWjF;AAMD,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAUjD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,CAGlF;AA0BD,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE7C;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAI7D;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAM9D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAKhE,CAAC;AAEF,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAS9C"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/cli/helpers.ts"],"names":[],"mappings":"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"}