@north-light/crouter 0.3.300 → 0.3.302

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.
Files changed (51) hide show
  1. package/dist/api/dto/reports.d.ts +8 -8
  2. package/dist/clients/attach/session/profile-files.d.ts +6 -3
  3. package/dist/clients/attach/session/profile-files.js +39 -10
  4. package/dist/clients/attach/viewer.js +663 -663
  5. package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +30 -1
  6. package/dist/commands/memory/read.js +12 -14
  7. package/dist/commands/node/create.js +1 -1
  8. package/dist/commands/node/lifecycle.js +36 -8
  9. package/dist/commands/push.js +4 -4
  10. package/dist/core/__tests__/human-action-delivery.test.js +13 -11
  11. package/dist/core/__tests__/integration/revive.test.js +3 -3
  12. package/dist/core/__tests__/node-outcome.test.js +1 -6
  13. package/dist/core/__tests__/seam/dormancy-release.test.js +42 -0
  14. package/dist/core/__tests__/stop-guard.test.js +64 -0
  15. package/dist/core/bash-jobs.d.ts +22 -0
  16. package/dist/core/bash-jobs.js +38 -1
  17. package/dist/core/canvas/crons.d.ts +20 -4
  18. package/dist/core/canvas/crons.js +54 -7
  19. package/dist/core/canvas/delivery-contract.d.ts +19 -0
  20. package/dist/core/canvas/delivery-contract.js +8 -0
  21. package/dist/core/canvas/human-deliveries.d.ts +3 -17
  22. package/dist/core/canvas/node-outcome-deliveries.d.ts +3 -19
  23. package/dist/core/canvas/node-outcome-deliveries.js +0 -4
  24. package/dist/core/keybindings/catalog.js +1 -1
  25. package/dist/core/memory-resolver.d.ts +3 -1
  26. package/dist/core/memory-resolver.js +3 -3
  27. package/dist/core/nested-stores.d.ts +1 -1
  28. package/dist/core/nested-stores.js +3 -3
  29. package/dist/core/runtime/bearings-render.js +1 -1
  30. package/dist/core/runtime/close.js +8 -6
  31. package/dist/core/runtime/stop-guard.js +6 -6
  32. package/dist/core/worktree.js +3 -6
  33. package/dist/daemon/__tests__/node-outcome-delivery.test.js +3 -2
  34. package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +21 -11
  35. package/dist/daemon/api/handlers/reports.js +1 -1
  36. package/dist/daemon/api/map.d.ts +1 -1
  37. package/dist/daemon/api/map.js +2 -2
  38. package/dist/daemon/cron/sinks.d.ts +1 -1
  39. package/dist/daemon/cron/sinks.js +2 -2
  40. package/dist/daemon/delivery/run-delivery.d.ts +25 -0
  41. package/dist/daemon/delivery/run-delivery.js +164 -0
  42. package/dist/daemon/human/deliver-action.d.ts +1 -14
  43. package/dist/daemon/human/deliver-action.js +5 -165
  44. package/dist/daemon/node-outcome/deliver-outcome.d.ts +1 -12
  45. package/dist/daemon/node-outcome/deliver-outcome.js +6 -152
  46. package/dist/daemon/reconcilers/live-obligation.js +2 -2
  47. package/dist/pi-extensions/canvas-bash-valve.js +7 -10
  48. package/package.json +1 -1
  49. package/runtime.lock.json +5 -5
  50. package/dist/daemon/cron-sink.d.ts +0 -26
  51. package/dist/daemon/cron-sink.js +0 -43
@@ -22,13 +22,13 @@ export interface PushReportResultDTO {
22
22
  from: string;
23
23
  to: string;
24
24
  };
25
- /** Present (and true) only for a `final` push whose reporting node owned a
26
- * managed worktree with zero commits ahead of its base and no uncommitted
27
- * changes: the server auto-dropped it instead of blocking on `node worktree
28
- * close`. A worktree with real unlanded work instead blocks with
29
- * an `open_managed_worktree` error. */
25
+ /** Present (and true) only for a `final` push that closes the reporting
26
+ * node's managed-worktree record without `node worktree close`. An existing
27
+ * checkout must be clean with its tip contained in the local base and stays
28
+ * pending cleanup; a missing checkout must be proven delivered. Work not
29
+ * proven delivered blocks with an `open_managed_worktree` error. */
30
30
  worktree_auto_dropped?: boolean;
31
- /** Present only alongside `worktree_auto_dropped`: the checkout path dropped. */
31
+ /** Present only alongside `worktree_auto_dropped`: the closed managed-worktree path; an existing checkout remains until pending cleanup. */
32
32
  worktree_auto_dropped_path?: string;
33
33
  }
34
34
  /** Why a node declined a structured result. `reason` is one plain sentence
@@ -55,8 +55,8 @@ export type SubmitResultRequest = {
55
55
  retryable: boolean;
56
56
  };
57
57
  /** Result of a structured-result submission (`crtr push result`). Terminal
58
- * mode reuses the final-push machinery, so `transitioned` and the worktree
59
- * auto-drop fields carry the same meaning as on PushReportResultDTO. */
58
+ * mode reuses the final-push machinery, so `transitioned` and the managed-worktree
59
+ * closure fields carry the same meaning as on PushReportResultDTO. */
60
60
  export interface SubmitResultDTO {
61
61
  /** Which request this answered: `terminal` finished the node; `oneoff` left it working. */
62
62
  mode: 'terminal' | 'oneoff';
@@ -2,13 +2,16 @@ import type { NodeRow } from '../../../core/canvas/types.js';
2
2
  interface ProfileFileSearchOptions {
3
3
  cwd: string;
4
4
  nodeDirs: readonly string[];
5
+ nodeIds: readonly string[];
5
6
  profileId: string | null;
6
7
  fdPath: string | null;
7
8
  onNotice: (message: string) => void;
8
9
  }
9
- /** Return the working directories for this node, its complete parent chain,
10
- * and its full descendant subtree. The `parent` hierarchy, rather than the
11
- * subscription graph, is the user-visible child/parent relationship. */
10
+ /** Return the ids of this node, its complete parent chain, and its full
11
+ * descendant subtree. The `parent` hierarchy, rather than the subscription
12
+ * graph, is the user-visible child/parent relationship. */
13
+ export declare function relatedNodeIds(nodes: readonly Pick<NodeRow, 'node_id' | 'parent'>[], nodeId: string): string[];
14
+ /** Return the working directories of the same node family. */
12
15
  export declare function relatedNodeDirs(nodes: readonly Pick<NodeRow, 'node_id' | 'cwd' | 'parent'>[], nodeId: string): string[];
13
16
  export declare function launchProfileFileSearch(opts: ProfileFileSearchOptions): void;
14
17
  export {};
@@ -1,22 +1,24 @@
1
1
  // session/profile-files.ts — fuzzy file search across a node's working family and local profile.
2
2
  //
3
3
  // The popup searches the current workspace, every ancestor and descendant
4
- // node's workspace, every project named by the node's profile manifest, and the
5
- // profile's own memory store. Ancestor `.crouter/memory/` stores are added with
6
- // ignore rules disabled, so project memory remains findable even when a parent
7
- // ignore file hides `.crouter/`. fzf owns matching and selection and nvim owns
8
- // viewing; the attach viewer resolves the related nodes and wires the two popups.
4
+ // node's workspace, the context and reports directories of those same nodes,
5
+ // every project named by the node's profile manifest, and the profile's own
6
+ // memory store. Ancestor `.crouter/memory/` stores are added with ignore rules
7
+ // disabled, so project memory remains findable even when a parent ignore file
8
+ // hides `.crouter/`. fzf owns matching and selection and nvim owns viewing; the
9
+ // attach viewer resolves the related nodes and wires the two popups.
9
10
  import { constants, accessSync, existsSync, mkdtempSync, readFileSync, rmSync, statSync } from 'node:fs';
10
11
  import { tmpdir } from 'node:os';
11
12
  import { delimiter, dirname, join, resolve, sep } from 'node:path';
12
13
  import { execFile, spawnSync } from 'node:child_process';
13
14
  import { loadProfileManifest, profileMemoryDir } from '../../../core/profiles/manifest.js';
15
+ import { contextDir, reportsDir } from '../../../core/canvas/paths.js';
14
16
  import { shellQuote } from '../../../core/runtime/placement-tmux.js';
15
17
  import { surfaceTmuxStyleArgs } from '../../../core/runtime/surface-bg.js';
16
- /** Return the working directories for this node, its complete parent chain,
17
- * and its full descendant subtree. The `parent` hierarchy, rather than the
18
- * subscription graph, is the user-visible child/parent relationship. */
19
- export function relatedNodeDirs(nodes, nodeId) {
18
+ /** Return the ids of this node, its complete parent chain, and its full
19
+ * descendant subtree. The `parent` hierarchy, rather than the subscription
20
+ * graph, is the user-visible child/parent relationship. */
21
+ export function relatedNodeIds(nodes, nodeId) {
20
22
  const byId = new Map(nodes.map((node) => [node.node_id, node]));
21
23
  const included = new Set([nodeId]);
22
24
  for (let current = byId.get(nodeId); current?.parent !== null && current?.parent !== undefined;) {
@@ -36,7 +38,27 @@ export function relatedNodeDirs(nodes, nodeId) {
36
38
  pending.push(child.node_id);
37
39
  }
38
40
  }
39
- return nodes.filter((node) => included.has(node.node_id)).map((node) => node.cwd);
41
+ return nodes.filter((node) => included.has(node.node_id)).map((node) => node.node_id);
42
+ }
43
+ /** Return the working directories of the same node family. */
44
+ export function relatedNodeDirs(nodes, nodeId) {
45
+ const family = new Set(relatedNodeIds(nodes, nodeId));
46
+ return nodes.filter((node) => family.has(node.node_id)).map((node) => node.cwd);
47
+ }
48
+ /** Return the canvas-home directories that hold each family node's shared
49
+ * documents: its context dir and its pushed reports. These live outside every
50
+ * working directory, so they are searched as roots of their own. */
51
+ function familyDocumentDirs(nodeIds) {
52
+ const dirs = [];
53
+ for (const id of nodeIds) {
54
+ try {
55
+ dirs.push(contextDir(id), reportsDir(id));
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ }
61
+ return dedupeExistingDirs(dirs);
40
62
  }
41
63
  function isDirectory(path) {
42
64
  try {
@@ -163,8 +185,15 @@ export function launchProfileFileSearch(opts) {
163
185
  const tempDir = mkdtempSync(join(tmpdir(), 'crtr-profile-files-'));
164
186
  const selected = join(tempDir, 'selection');
165
187
  const candidates = join(tempDir, 'candidates');
188
+ // A context dir can hold a full repo clone a node made for itself, so ignore
189
+ // rules stay on (they are what keeps a clone's dependencies out) and the
190
+ // background-bash log dir directly beneath it is dropped — those are
191
+ // transient command output named by job id, never a document to open.
192
+ const documentDirs = familyDocumentDirs(opts.nodeIds)
193
+ .filter((dir) => !roots.some((root) => dir === root || dir.startsWith(root + sep)));
166
194
  const scans = [
167
195
  ...roots.map((root) => `${shellQuote(fd)} --type f --hidden --exclude .git --exclude ${shellQuote('**/.crouter/memory/**')} . ${shellQuote(root)}`),
196
+ ...documentDirs.map((dir) => `${shellQuote(fd)} --type f --hidden --exclude .git --exclude ${shellQuote('/jobs')} . ${shellQuote(dir)}`),
168
197
  ...memoryDirs.map((memory) => `${shellQuote(fd)} --type f --hidden --exclude .git --no-ignore . ${shellQuote(memory)}`),
169
198
  ];
170
199
  // Every line is the whole path and nothing else, so fzf matches, ranks, and