@codyswann/lisa 4.10.15 → 4.11.1

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 (97) hide show
  1. package/dist/cli/doctor-worktree-hygiene.d.ts +5 -2
  2. package/dist/cli/doctor-worktree-hygiene.d.ts.map +1 -1
  3. package/dist/cli/doctor-worktree-hygiene.js +12 -6
  4. package/dist/cli/doctor-worktree-hygiene.js.map +1 -1
  5. package/dist/cli/index.d.ts.map +1 -1
  6. package/dist/cli/index.js +2 -0
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/prune-commands.d.ts +52 -0
  9. package/dist/cli/prune-commands.d.ts.map +1 -0
  10. package/dist/cli/prune-commands.js +158 -0
  11. package/dist/cli/prune-commands.js.map +1 -0
  12. package/dist/cli/prune-report.d.ts +52 -0
  13. package/dist/cli/prune-report.d.ts.map +1 -0
  14. package/dist/cli/prune-report.js +143 -0
  15. package/dist/cli/prune-report.js.map +1 -0
  16. package/dist/cli/stash-prune-policy.d.ts +72 -0
  17. package/dist/cli/stash-prune-policy.d.ts.map +1 -0
  18. package/dist/cli/stash-prune-policy.js +90 -0
  19. package/dist/cli/stash-prune-policy.js.map +1 -0
  20. package/dist/cli/stash-prune.d.ts +104 -0
  21. package/dist/cli/stash-prune.d.ts.map +1 -0
  22. package/dist/cli/stash-prune.js +206 -0
  23. package/dist/cli/stash-prune.js.map +1 -0
  24. package/dist/cli/worktree-inventory.d.ts +82 -0
  25. package/dist/cli/worktree-inventory.d.ts.map +1 -0
  26. package/dist/cli/worktree-inventory.js +195 -0
  27. package/dist/cli/worktree-inventory.js.map +1 -0
  28. package/dist/cli/worktree-liveness.d.ts +52 -0
  29. package/dist/cli/worktree-liveness.d.ts.map +1 -0
  30. package/dist/cli/worktree-liveness.js +124 -0
  31. package/dist/cli/worktree-liveness.js.map +1 -0
  32. package/dist/cli/worktree-ownership.d.ts +65 -0
  33. package/dist/cli/worktree-ownership.d.ts.map +1 -0
  34. package/dist/cli/worktree-ownership.js +142 -0
  35. package/dist/cli/worktree-ownership.js.map +1 -0
  36. package/dist/cli/worktree-prune-policy.d.ts +76 -0
  37. package/dist/cli/worktree-prune-policy.d.ts.map +1 -0
  38. package/dist/cli/worktree-prune-policy.js +114 -0
  39. package/dist/cli/worktree-prune-policy.js.map +1 -0
  40. package/dist/cli/worktree-prune.d.ts +96 -0
  41. package/dist/cli/worktree-prune.d.ts.map +1 -0
  42. package/dist/cli/worktree-prune.js +153 -0
  43. package/dist/cli/worktree-prune.js.map +1 -0
  44. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  45. package/dist/core/upstream-evidence-manifest.js +18 -0
  46. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  47. package/package.json +1 -1
  48. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  50. package/plugins/lisa-agy/plugin.json +1 -1
  51. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  53. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  54. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  60. package/plugins/lisa-expo-agy/plugin.json +1 -1
  61. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  65. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  66. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  70. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  71. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  75. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  76. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  80. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  81. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-rails-agy/plugin.json +1 -1
  86. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  90. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  91. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  95. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  96. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The entitlement rule for removing an agent worktree.
3
+ *
4
+ * Deliberately pure: every fact is gathered elsewhere and handed in, so the
5
+ * decision that authorizes a deletion is a function that can be exhaustively
6
+ * tested and mutation-tested rather than a side effect of a shell pipeline.
7
+ *
8
+ * The rule is **entitlement by proof, never by location.** Nothing here looks
9
+ * at where a worktree lives. `$TMPDIR` and the worktree roots are shared by
10
+ * every agent on the machine, so a path prefix identifies a neighbourhood, not
11
+ * an owner; reaping on one deletes siblings' live work. A worktree is the
12
+ * caller's to remove only when it is claimed by the caller, or when no other
13
+ * party can possibly have a claim on it — no live process inside it, no recent
14
+ * activity, and nothing in it that exists nowhere else.
15
+ * @module cli/worktree-prune-policy
16
+ */
17
+ /** Why one worktree was refused. Every value names a specific unmet proof. */
18
+ export type WorktreeBlocker = "primary-checkout" | "current-worktree" | "git-locked" | "claimed-by-another-owner" | "liveness-unknown" | "in-use" | "recently-active" | "unpushed-commits" | "uncommitted-changes" | "unreadable";
19
+ /** Everything the rule is allowed to consider about one worktree. */
20
+ export interface WorktreeFacts {
21
+ /** Absolute worktree path. */
22
+ readonly path: string;
23
+ /** Checked-out branch, or undefined when detached. */
24
+ readonly branch?: string;
25
+ /** Whether this is the repository's primary checkout. */
26
+ readonly isPrimary: boolean;
27
+ /** Whether the cleaner itself is running inside this worktree. */
28
+ readonly isCurrent: boolean;
29
+ /** Whether git reports the worktree as locked. */
30
+ readonly locked: boolean;
31
+ /** Whether git could report on the worktree at all. */
32
+ readonly readable: boolean;
33
+ /** Ownership verdict from the receipt check. */
34
+ readonly ownership: "mine" | "theirs" | "unclaimed";
35
+ /** Live processes whose working directory is inside, or undefined if unknown. */
36
+ readonly liveHolders: number | undefined;
37
+ /** Seconds since the worktree last showed activity. */
38
+ readonly idleSeconds: number;
39
+ /** Modified, staged, added, deleted, or renamed TRACKED files. */
40
+ readonly trackedChanges: number;
41
+ /** Untracked, non-ignored files. */
42
+ readonly untrackedFiles: number;
43
+ /** Commits present locally and on no remote. */
44
+ readonly unpushedCommits: number;
45
+ }
46
+ /** Tunable part of the rule. */
47
+ export interface WorktreePrunePolicy {
48
+ /** Quiescence a worktree must show before an unclaimed one is eligible. */
49
+ readonly minIdleSeconds: number;
50
+ }
51
+ /** Result of applying the rule to one worktree. */
52
+ export interface WorktreeVerdict {
53
+ /** Absolute worktree path. */
54
+ readonly path: string;
55
+ /** Whether the worktree may be removed. */
56
+ readonly eligible: boolean;
57
+ /** Every unmet proof, most severe first. */
58
+ readonly blockers: readonly WorktreeBlocker[];
59
+ }
60
+ /** Default quiescence window: one day of no activity. */
61
+ export declare const DEFAULT_MIN_IDLE_SECONDS: number;
62
+ /** Operator-readable explanation for each blocker. */
63
+ export declare const BLOCKER_EXPLANATIONS: Readonly<Record<WorktreeBlocker, string>>;
64
+ /**
65
+ * Decide whether one worktree may be removed, and say why not when it may not.
66
+ *
67
+ * Blockers are returned in full rather than short-circuiting at the first
68
+ * failure. A worktree refused for three reasons and a worktree refused for one
69
+ * need different remedies, and reporting only the first trains a reader to fix
70
+ * one thing and re-run into the next refusal.
71
+ * @param facts - Gathered facts about the worktree
72
+ * @param policy - Tunable thresholds
73
+ * @returns Verdict with every unmet proof
74
+ */
75
+ export declare function classifyWorktree(facts: WorktreeFacts, policy: WorktreePrunePolicy): WorktreeVerdict;
76
+ //# sourceMappingURL=worktree-prune-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree-prune-policy.d.ts","sourceRoot":"","sources":["../../src/cli/worktree-prune-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GACvB,kBAAkB,GAClB,kBAAkB,GAClB,YAAY,GACZ,0BAA0B,GAC1B,kBAAkB,GAClB,QAAQ,GACR,iBAAiB,GACjB,kBAAkB,GAClB,qBAAqB,GACrB,YAAY,CAAC;AAEjB,qEAAqE;AACrE,MAAM,WAAW,aAAa;IAC5B,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC;IACpD,iFAAiF;IACjF,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,oCAAoC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,gDAAgD;IAChD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,gCAAgC;AAChC,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CAC/C;AAED,yDAAyD;AACzD,eAAO,MAAM,wBAAwB,QAAe,CAAC;AAErD,sDAAsD;AACtD,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAgBvE,CAAC;AAEL;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,mBAAmB,GAC1B,eAAe,CAOjB"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The entitlement rule for removing an agent worktree.
3
+ *
4
+ * Deliberately pure: every fact is gathered elsewhere and handed in, so the
5
+ * decision that authorizes a deletion is a function that can be exhaustively
6
+ * tested and mutation-tested rather than a side effect of a shell pipeline.
7
+ *
8
+ * The rule is **entitlement by proof, never by location.** Nothing here looks
9
+ * at where a worktree lives. `$TMPDIR` and the worktree roots are shared by
10
+ * every agent on the machine, so a path prefix identifies a neighbourhood, not
11
+ * an owner; reaping on one deletes siblings' live work. A worktree is the
12
+ * caller's to remove only when it is claimed by the caller, or when no other
13
+ * party can possibly have a claim on it — no live process inside it, no recent
14
+ * activity, and nothing in it that exists nowhere else.
15
+ * @module cli/worktree-prune-policy
16
+ */
17
+ /** Default quiescence window: one day of no activity. */
18
+ export const DEFAULT_MIN_IDLE_SECONDS = 24 * 60 * 60;
19
+ /** Operator-readable explanation for each blocker. */
20
+ export const BLOCKER_EXPLANATIONS = Object.freeze({
21
+ "primary-checkout": "this is the repository's primary checkout",
22
+ "current-worktree": "the cleaner is running inside it",
23
+ "git-locked": "git reports it locked, which means somebody claimed it",
24
+ "claimed-by-another-owner": "its ownership receipt names a different agent, so it is not yours to remove",
25
+ "liveness-unknown": "the live-process probe could not run, so nothing could be proven idle",
26
+ "in-use": "a live process is working inside it right now",
27
+ "recently-active": "it showed activity too recently to be called abandoned",
28
+ "unpushed-commits": "it holds commits that exist on no remote — push them first",
29
+ "uncommitted-changes": "it holds uncommitted work — commit and push, or stash it, first",
30
+ unreadable: "git could not report on it, so nothing about it was proven",
31
+ });
32
+ /**
33
+ * Decide whether one worktree may be removed, and say why not when it may not.
34
+ *
35
+ * Blockers are returned in full rather than short-circuiting at the first
36
+ * failure. A worktree refused for three reasons and a worktree refused for one
37
+ * need different remedies, and reporting only the first trains a reader to fix
38
+ * one thing and re-run into the next refusal.
39
+ * @param facts - Gathered facts about the worktree
40
+ * @param policy - Tunable thresholds
41
+ * @returns Verdict with every unmet proof
42
+ */
43
+ export function classifyWorktree(facts, policy) {
44
+ const blockers = [
45
+ ...structuralBlockers(facts),
46
+ ...idlenessBlockers(facts, policy),
47
+ ...workAtRiskBlockers(facts),
48
+ ];
49
+ return { path: facts.path, eligible: blockers.length === 0, blockers };
50
+ }
51
+ /**
52
+ * Blockers that make a worktree ineligible regardless of its contents.
53
+ * @param facts - Gathered facts about the worktree
54
+ * @returns Structural blockers
55
+ */
56
+ function structuralBlockers(facts) {
57
+ const candidates = [
58
+ facts.readable ? undefined : "unreadable",
59
+ facts.isPrimary ? "primary-checkout" : undefined,
60
+ facts.isCurrent ? "current-worktree" : undefined,
61
+ facts.locked ? "git-locked" : undefined,
62
+ facts.ownership === "theirs"
63
+ ? "claimed-by-another-owner"
64
+ : undefined,
65
+ ];
66
+ return candidates.filter((blocker) => blocker !== undefined);
67
+ }
68
+ /**
69
+ * Blockers derived from whether anybody could still be using the worktree.
70
+ *
71
+ * A matching ownership receipt waives the quiescence window and NOTHING else.
72
+ * An owner asking to clean its own worktree has said what the window is there
73
+ * to infer. It never waives `in-use`: a claim says the work is finished, not
74
+ * that no process is still standing in the directory.
75
+ * @param facts - Gathered facts about the worktree
76
+ * @param policy - Tunable thresholds
77
+ * @returns Non-use blockers
78
+ */
79
+ function idlenessBlockers(facts, policy) {
80
+ const liveness = facts.liveHolders === undefined
81
+ ? "liveness-unknown"
82
+ : facts.liveHolders > 0
83
+ ? "in-use"
84
+ : undefined;
85
+ const stale = facts.ownership === "mine" || facts.idleSeconds >= policy.minIdleSeconds
86
+ ? undefined
87
+ : "recently-active";
88
+ const candidates = [
89
+ liveness,
90
+ stale,
91
+ ];
92
+ return candidates.filter((blocker) => blocker !== undefined);
93
+ }
94
+ /**
95
+ * Blockers derived from work that would not survive the removal.
96
+ *
97
+ * Untracked files count. The existing doctor check deliberately excludes them
98
+ * from its "work at risk" signal because untracked droppings make every
99
+ * worktree look catastrophic in a REPORT. A report is not a deletion: here the
100
+ * files are about to stop existing, and an untracked file is in no object
101
+ * database at all, so it is the least recoverable thing in the tree.
102
+ * @param facts - Gathered facts about the worktree
103
+ * @returns Work-at-risk blockers
104
+ */
105
+ function workAtRiskBlockers(facts) {
106
+ const candidates = [
107
+ facts.unpushedCommits > 0 ? "unpushed-commits" : undefined,
108
+ facts.trackedChanges > 0 || facts.untrackedFiles > 0
109
+ ? "uncommitted-changes"
110
+ : undefined,
111
+ ];
112
+ return candidates.filter((blocker) => blocker !== undefined);
113
+ }
114
+ //# sourceMappingURL=worktree-prune-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree-prune-policy.js","sourceRoot":"","sources":["../../src/cli/worktree-prune-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { type LivenessProbe } from "./worktree-liveness.js";
2
+ import { type WorktreeFacts, type WorktreeVerdict } from "./worktree-prune-policy.js";
3
+ /** Command-line options for the prune verb. */
4
+ export interface WorktreePruneOptions {
5
+ /** Perform the removals instead of reporting them. */
6
+ readonly apply?: boolean;
7
+ /** Quiescence window in hours before an unclaimed worktree is eligible. */
8
+ readonly idleHours?: string;
9
+ /** Emit machine-readable output. */
10
+ readonly json?: boolean;
11
+ }
12
+ /** What one run decided, before anything is removed. */
13
+ export interface WorktreePrunePlan {
14
+ /** Repository the plan was computed for. */
15
+ readonly repoPath: string;
16
+ /** Verdict for every registered worktree. */
17
+ readonly verdicts: readonly WorktreeVerdict[];
18
+ /** Facts behind each verdict, in the same order. */
19
+ readonly facts: readonly WorktreeFacts[];
20
+ /** Whether the live-process probe produced an answer. */
21
+ readonly livenessAvailable: boolean;
22
+ /** Registrations whose directory is already gone. */
23
+ readonly prunableRegistrations: readonly string[];
24
+ }
25
+ /** Injectable collaborators, overridden by tests. */
26
+ export interface WorktreePruneDependencies {
27
+ /** Machine-wide live working directory probe. */
28
+ readonly probeLive: LivenessProbe;
29
+ /** Owner id of the running process. */
30
+ readonly callerOwnerId: string | undefined;
31
+ /** Clock in epoch milliseconds. */
32
+ readonly now: () => number;
33
+ /** Path the cleaner is running from. */
34
+ readonly currentPath: string;
35
+ }
36
+ /**
37
+ * Arguments used to remove one worktree.
38
+ *
39
+ * Exported so a test can pin the absence of `--force` by value rather than by
40
+ * reading the source. The plain form is not a stylistic preference: it is the
41
+ * backstop that makes a bug in the entitlement rule non-destructive, because
42
+ * git still refuses a dirty tree on its own.
43
+ * @param worktreePath - Absolute worktree path
44
+ * @returns Git arguments
45
+ */
46
+ export declare function buildWorktreeRemoveArgs(worktreePath: string): readonly string[];
47
+ /**
48
+ * Resolve the quiescence window from the command line.
49
+ * @param idleHours - Raw `--idle-hours` value
50
+ * @returns Window in seconds
51
+ */
52
+ export declare function resolveMinIdleSeconds(idleHours: string | undefined): number;
53
+ /**
54
+ * Compute what a run would do, without doing any of it.
55
+ * @param repoPath - Any path inside the repository
56
+ * @param options - Command-line options
57
+ * @param dependencies - Injectable collaborators
58
+ * @returns The plan
59
+ */
60
+ export declare function planWorktreePrune(repoPath: string, options: WorktreePruneOptions, dependencies: WorktreePruneDependencies): Promise<WorktreePrunePlan>;
61
+ /** Outcome of removing one worktree. */
62
+ export interface RemovalOutcome {
63
+ /** Absolute worktree path. */
64
+ readonly path: string;
65
+ /** Whether git removed it. */
66
+ readonly removed: boolean;
67
+ /** Git's message when it refused. */
68
+ readonly error?: string;
69
+ }
70
+ /**
71
+ * Remove every eligible worktree in a plan.
72
+ *
73
+ * Removals run one at a time rather than concurrently. `git worktree remove`
74
+ * takes the repository's worktree lock, and a batch of parallel removals on a
75
+ * machine where other agents are also running git turns a contended lock into
76
+ * a spurious failure that reads like a refusal.
77
+ * @param plan - Plan produced by {@link planWorktreePrune}
78
+ * @param index - Index of the eligible worktree to remove next
79
+ * @returns One outcome per eligible worktree
80
+ */
81
+ export declare function applyWorktreePrune(plan: WorktreePrunePlan, index?: number): Promise<readonly RemovalOutcome[]>;
82
+ /**
83
+ * Drop registrations whose directory has already disappeared.
84
+ *
85
+ * Separate from removal because it destroys nothing: git is only forgetting a
86
+ * pointer to a directory that no longer exists.
87
+ * @param plan - Plan produced by {@link planWorktreePrune}
88
+ * @returns Number of registrations git was asked to forget
89
+ */
90
+ export declare function pruneMissingRegistrations(plan: WorktreePrunePlan): Promise<number>;
91
+ /**
92
+ * Default collaborators for a real run.
93
+ * @returns Dependencies wired to the real probe, environment, and clock
94
+ */
95
+ export declare function defaultWorktreePruneDependencies(): WorktreePruneDependencies;
96
+ //# sourceMappingURL=worktree-prune.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree-prune.d.ts","sourceRoot":"","sources":["../../src/cli/worktree-prune.ts"],"names":[],"mappings":"AAyBA,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AAEpC,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,sDAAsD;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,yDAAyD;IACzD,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,qDAAqD;IACrD,QAAQ,CAAC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;CACnD;AAED,qDAAqD;AACrD,MAAM,WAAW,yBAAyB;IACxC,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,uCAAuC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,mCAAmC;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,GACnB,SAAS,MAAM,EAAE,CAEnB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAO3E;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,oBAAoB,EAC7B,YAAY,EAAE,yBAAyB,GACtC,OAAO,CAAC,iBAAiB,CAAC,CAoB5B;AAED,wCAAwC;AACxC,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,qCAAqC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,iBAAiB,EACvB,KAAK,SAAI,GACR,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAgBpC;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,IAAI,yBAAyB,CAO5E"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * `lisa worktree prune` — the vetted verb for retiring agent worktrees.
3
+ *
4
+ * The guard in `parity-safety-net.sh` blocks `git worktree remove --force`
5
+ * because it discards a dirty tree, and that block is correct and stays. This
6
+ * command does not relax it, is not an override for it, and never passes
7
+ * `--force` to git: it performs the safety checks itself and then uses the
8
+ * plain `git worktree remove`, whose own refusal of a dirty tree remains in
9
+ * place underneath as a last line of defence.
10
+ *
11
+ * Dry-run is the default. The command is meant to be called by unattended
12
+ * loops on a machine shared with other agents' live work, so the first contact
13
+ * a mis-scoped invocation makes must be a report and not a deletion. `--apply`
14
+ * is the whole opt-in; there is no flag anywhere that widens the entitlement
15
+ * rule itself.
16
+ * @module cli/worktree-prune
17
+ */
18
+ import { realpathSync } from "node:fs";
19
+ import * as path from "node:path";
20
+ import { gatherAllWorktreeFacts, git, listWorktrees, } from "./worktree-inventory.js";
21
+ import { probeLiveWorkingDirectories, } from "./worktree-liveness.js";
22
+ import { resolveCallerOwnerId } from "./worktree-ownership.js";
23
+ import { classifyWorktree, DEFAULT_MIN_IDLE_SECONDS, } from "./worktree-prune-policy.js";
24
+ /**
25
+ * Arguments used to remove one worktree.
26
+ *
27
+ * Exported so a test can pin the absence of `--force` by value rather than by
28
+ * reading the source. The plain form is not a stylistic preference: it is the
29
+ * backstop that makes a bug in the entitlement rule non-destructive, because
30
+ * git still refuses a dirty tree on its own.
31
+ * @param worktreePath - Absolute worktree path
32
+ * @returns Git arguments
33
+ */
34
+ export function buildWorktreeRemoveArgs(worktreePath) {
35
+ return ["worktree", "remove", worktreePath];
36
+ }
37
+ /**
38
+ * Resolve the quiescence window from the command line.
39
+ * @param idleHours - Raw `--idle-hours` value
40
+ * @returns Window in seconds
41
+ */
42
+ export function resolveMinIdleSeconds(idleHours) {
43
+ if (idleHours === undefined)
44
+ return DEFAULT_MIN_IDLE_SECONDS;
45
+ const parsed = Number.parseFloat(idleHours);
46
+ if (!Number.isFinite(parsed) || parsed < 0) {
47
+ throw new Error("--idle-hours must be a non-negative number");
48
+ }
49
+ return Math.floor(parsed * 3600);
50
+ }
51
+ /**
52
+ * Compute what a run would do, without doing any of it.
53
+ * @param repoPath - Any path inside the repository
54
+ * @param options - Command-line options
55
+ * @param dependencies - Injectable collaborators
56
+ * @returns The plan
57
+ */
58
+ export async function planWorktreePrune(repoPath, options, dependencies) {
59
+ const minIdleSeconds = resolveMinIdleSeconds(options.idleHours);
60
+ const entries = await listWorktrees(repoPath);
61
+ const live = await dependencies.probeLive();
62
+ const present = entries.filter(entry => !entry.prunable);
63
+ const facts = await gatherAllWorktreeFacts(present, {
64
+ liveWorkingDirectories: live,
65
+ callerOwnerId: dependencies.callerOwnerId,
66
+ currentPath: dependencies.currentPath,
67
+ nowMs: dependencies.now(),
68
+ });
69
+ return {
70
+ repoPath,
71
+ verdicts: facts.map(fact => classifyWorktree(fact, { minIdleSeconds })),
72
+ facts,
73
+ livenessAvailable: live !== undefined,
74
+ prunableRegistrations: entries
75
+ .filter((entry) => entry.prunable)
76
+ .map(entry => entry.path),
77
+ };
78
+ }
79
+ /**
80
+ * Remove every eligible worktree in a plan.
81
+ *
82
+ * Removals run one at a time rather than concurrently. `git worktree remove`
83
+ * takes the repository's worktree lock, and a batch of parallel removals on a
84
+ * machine where other agents are also running git turns a contended lock into
85
+ * a spurious failure that reads like a refusal.
86
+ * @param plan - Plan produced by {@link planWorktreePrune}
87
+ * @param index - Index of the eligible worktree to remove next
88
+ * @returns One outcome per eligible worktree
89
+ */
90
+ export async function applyWorktreePrune(plan, index = 0) {
91
+ const eligible = plan.verdicts.filter(verdict => verdict.eligible);
92
+ if (index >= eligible.length)
93
+ return [];
94
+ const target = eligible[index];
95
+ const outcome = await git(buildWorktreeRemoveArgs(target.path), plan.repoPath).then(() => ({ path: target.path, removed: true }), (error) => ({
96
+ path: target.path,
97
+ removed: false,
98
+ error: describeError(error),
99
+ }));
100
+ return [outcome, ...(await applyWorktreePrune(plan, index + 1))];
101
+ }
102
+ /**
103
+ * Drop registrations whose directory has already disappeared.
104
+ *
105
+ * Separate from removal because it destroys nothing: git is only forgetting a
106
+ * pointer to a directory that no longer exists.
107
+ * @param plan - Plan produced by {@link planWorktreePrune}
108
+ * @returns Number of registrations git was asked to forget
109
+ */
110
+ export async function pruneMissingRegistrations(plan) {
111
+ if (plan.prunableRegistrations.length === 0)
112
+ return 0;
113
+ await git(["worktree", "prune"], plan.repoPath).catch(() => "");
114
+ return plan.prunableRegistrations.length;
115
+ }
116
+ /**
117
+ * Default collaborators for a real run.
118
+ * @returns Dependencies wired to the real probe, environment, and clock
119
+ */
120
+ export function defaultWorktreePruneDependencies() {
121
+ return {
122
+ probeLive: probeLiveWorkingDirectories,
123
+ callerOwnerId: resolveCallerOwnerId(),
124
+ now: () => Date.now(),
125
+ currentPath: resolvePhysicalCwd(),
126
+ };
127
+ }
128
+ /**
129
+ * Resolve the directory the cleaner runs from, following symlinks.
130
+ *
131
+ * The physical form is what the liveness probe reports, so the two have to be
132
+ * in the same spelling or the cleaner cannot recognise its own worktree.
133
+ * @returns Absolute physical path of the current working directory
134
+ */
135
+ function resolvePhysicalCwd() {
136
+ const resolved = path.resolve(process.cwd());
137
+ try {
138
+ return realpathSync.native(resolved);
139
+ }
140
+ catch {
141
+ return resolved;
142
+ }
143
+ }
144
+ /**
145
+ * Render an error for the report.
146
+ * @param error - Rejection from git
147
+ * @returns Single-line message
148
+ */
149
+ function describeError(error) {
150
+ const message = error instanceof Error ? error.message : String(error);
151
+ return message.split("\n").filter(line => line.trim() !== "")[0] ?? "unknown";
152
+ }
153
+ //# sourceMappingURL=worktree-prune.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree-prune.js","sourceRoot":"","sources":["../../src/cli/worktree-prune.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAw5EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAipPjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
1
+ {"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAw5EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAmqPjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
@@ -7255,6 +7255,8 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7255
7255
  "src/cli/merge-learnings-cmd.ts": true,
7256
7256
  "src/cli/print-update-warning.ts": true,
7257
7257
  "src/cli/prompts.ts": true,
7258
+ "src/cli/prune-commands.ts": true,
7259
+ "src/cli/prune-report.ts": true,
7258
7260
  "src/cli/remote-env-cmd.ts": true,
7259
7261
  "src/cli/remote-environment-catalog.ts": true,
7260
7262
  "src/cli/remote-environment-contract.ts": true,
@@ -7265,6 +7267,8 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7265
7267
  "src/cli/shared-options.ts": true,
7266
7268
  "src/cli/standards-proof-cmd.ts": true,
7267
7269
  "src/cli/starters.ts": true,
7270
+ "src/cli/stash-prune-policy.ts": true,
7271
+ "src/cli/stash-prune.ts": true,
7268
7272
  "src/cli/sync-cmd.ts": true,
7269
7273
  "src/cli/ui-automations-adapters.ts": true,
7270
7274
  "src/cli/ui-automations.ts": true,
@@ -7302,6 +7306,11 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7302
7306
  "src/cli/version.ts": true,
7303
7307
  "src/cli/workflow-moments.ts": true,
7304
7308
  "src/cli/workstation-cmd.ts": true,
7309
+ "src/cli/worktree-inventory.ts": true,
7310
+ "src/cli/worktree-liveness.ts": true,
7311
+ "src/cli/worktree-ownership.ts": true,
7312
+ "src/cli/worktree-prune-policy.ts": true,
7313
+ "src/cli/worktree-prune.ts": true,
7305
7314
  "src/codex/agent-installer.ts": true,
7306
7315
  "src/codex/agent-transformer.ts": true,
7307
7316
  "src/codex/agents-md-installer.ts": true,
@@ -7746,6 +7755,8 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7746
7755
  "tests/integration/pre-tool-refusal-scripts-resolve-gates.test.ts": true,
7747
7756
  "tests/integration/prepare-setup-command.test.ts": true,
7748
7757
  "tests/integration/presence-gated-absence-fail-closed.test.ts": true,
7758
+ "tests/integration/prune-report-reachability.test.ts": true,
7759
+ "tests/integration/prune-verbs-negative-controls.test.ts": true,
7749
7760
  "tests/integration/push-collects-integration-tree-once.test.ts": true,
7750
7761
  "tests/integration/quality-declaration-required-jobs.test.ts": true,
7751
7762
  "tests/integration/quality-dual-adoption-controls.test.ts": true,
@@ -7791,6 +7802,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7791
7802
  "tests/integration/threshold-ratchet-gate-fail-closed.test.ts": true,
7792
7803
  "tests/integration/tracked-source-nul-bytes.test.ts": true,
7793
7804
  "tests/support/git-executable.ts": true,
7805
+ "tests/support/prune-fixtures.ts": true,
7794
7806
  "tests/support/work-item-cli.ts": true,
7795
7807
  "tests/unit/agy/block-no-verify-agy.test.ts": true,
7796
7808
  "tests/unit/agy/mcp-collect.test.ts": true,
@@ -7882,11 +7894,14 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7882
7894
  "tests/unit/cli/merge-learnings-cmd.test.ts": true,
7883
7895
  "tests/unit/cli/parse-refresh-templates.test.ts": true,
7884
7896
  "tests/unit/cli/prompts.test.ts": true,
7897
+ "tests/unit/cli/prune-commands.test.ts": true,
7898
+ "tests/unit/cli/prune-parsing.test.ts": true,
7885
7899
  "tests/unit/cli/serialize-legs-callee-grant.test.ts": true,
7886
7900
  "tests/unit/cli/setup-project.test.ts": true,
7887
7901
  "tests/unit/cli/setup-wiki.test.ts": true,
7888
7902
  "tests/unit/cli/shared-options.test.ts": true,
7889
7903
  "tests/unit/cli/starters.test.ts": true,
7904
+ "tests/unit/cli/stash-prune-policy.test.ts": true,
7890
7905
  "tests/unit/cli/sync-cmd.test.ts": true,
7891
7906
  "tests/unit/cli/ui-automations-fixture.test.ts": true,
7892
7907
  "tests/unit/cli/ui-automations-map.test.ts": true,
@@ -7921,6 +7936,9 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7921
7936
  "tests/unit/cli/update-cmd.test.ts": true,
7922
7937
  "tests/unit/cli/version-cmd.test.ts": true,
7923
7938
  "tests/unit/cli/workstation-cmd.test.ts": true,
7939
+ "tests/unit/cli/worktree-liveness.test.ts": true,
7940
+ "tests/unit/cli/worktree-ownership.test.ts": true,
7941
+ "tests/unit/cli/worktree-prune-policy.test.ts": true,
7924
7942
  "tests/unit/codex/agent-installer.test.ts": true,
7925
7943
  "tests/unit/codex/agent-transformer.test.ts": true,
7926
7944
  "tests/unit/codex/agents-md-installer.test.ts": true,