@codyswann/lisa 4.10.15 → 4.11.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/dist/cli/doctor-worktree-hygiene.d.ts +5 -2
- package/dist/cli/doctor-worktree-hygiene.d.ts.map +1 -1
- package/dist/cli/doctor-worktree-hygiene.js +12 -6
- package/dist/cli/doctor-worktree-hygiene.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/prune-commands.d.ts +52 -0
- package/dist/cli/prune-commands.d.ts.map +1 -0
- package/dist/cli/prune-commands.js +158 -0
- package/dist/cli/prune-commands.js.map +1 -0
- package/dist/cli/prune-report.d.ts +40 -0
- package/dist/cli/prune-report.d.ts.map +1 -0
- package/dist/cli/prune-report.js +81 -0
- package/dist/cli/prune-report.js.map +1 -0
- package/dist/cli/stash-prune-policy.d.ts +72 -0
- package/dist/cli/stash-prune-policy.d.ts.map +1 -0
- package/dist/cli/stash-prune-policy.js +90 -0
- package/dist/cli/stash-prune-policy.js.map +1 -0
- package/dist/cli/stash-prune.d.ts +104 -0
- package/dist/cli/stash-prune.d.ts.map +1 -0
- package/dist/cli/stash-prune.js +206 -0
- package/dist/cli/stash-prune.js.map +1 -0
- package/dist/cli/worktree-inventory.d.ts +82 -0
- package/dist/cli/worktree-inventory.d.ts.map +1 -0
- package/dist/cli/worktree-inventory.js +195 -0
- package/dist/cli/worktree-inventory.js.map +1 -0
- package/dist/cli/worktree-liveness.d.ts +52 -0
- package/dist/cli/worktree-liveness.d.ts.map +1 -0
- package/dist/cli/worktree-liveness.js +124 -0
- package/dist/cli/worktree-liveness.js.map +1 -0
- package/dist/cli/worktree-ownership.d.ts +65 -0
- package/dist/cli/worktree-ownership.d.ts.map +1 -0
- package/dist/cli/worktree-ownership.js +142 -0
- package/dist/cli/worktree-ownership.js.map +1 -0
- package/dist/cli/worktree-prune-policy.d.ts +76 -0
- package/dist/cli/worktree-prune-policy.d.ts.map +1 -0
- package/dist/cli/worktree-prune-policy.js +114 -0
- package/dist/cli/worktree-prune-policy.js.map +1 -0
- package/dist/cli/worktree-prune.d.ts +96 -0
- package/dist/cli/worktree-prune.d.ts.map +1 -0
- package/dist/cli/worktree-prune.js +153 -0
- package/dist/cli/worktree-prune.js.map +1 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +16 -0
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- 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,
|
|
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,CAiqPjE,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,7 @@ 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-verbs-negative-controls.test.ts": true,
|
|
7749
7759
|
"tests/integration/push-collects-integration-tree-once.test.ts": true,
|
|
7750
7760
|
"tests/integration/quality-declaration-required-jobs.test.ts": true,
|
|
7751
7761
|
"tests/integration/quality-dual-adoption-controls.test.ts": true,
|
|
@@ -7882,11 +7892,14 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7882
7892
|
"tests/unit/cli/merge-learnings-cmd.test.ts": true,
|
|
7883
7893
|
"tests/unit/cli/parse-refresh-templates.test.ts": true,
|
|
7884
7894
|
"tests/unit/cli/prompts.test.ts": true,
|
|
7895
|
+
"tests/unit/cli/prune-commands.test.ts": true,
|
|
7896
|
+
"tests/unit/cli/prune-parsing.test.ts": true,
|
|
7885
7897
|
"tests/unit/cli/serialize-legs-callee-grant.test.ts": true,
|
|
7886
7898
|
"tests/unit/cli/setup-project.test.ts": true,
|
|
7887
7899
|
"tests/unit/cli/setup-wiki.test.ts": true,
|
|
7888
7900
|
"tests/unit/cli/shared-options.test.ts": true,
|
|
7889
7901
|
"tests/unit/cli/starters.test.ts": true,
|
|
7902
|
+
"tests/unit/cli/stash-prune-policy.test.ts": true,
|
|
7890
7903
|
"tests/unit/cli/sync-cmd.test.ts": true,
|
|
7891
7904
|
"tests/unit/cli/ui-automations-fixture.test.ts": true,
|
|
7892
7905
|
"tests/unit/cli/ui-automations-map.test.ts": true,
|
|
@@ -7921,6 +7934,9 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7921
7934
|
"tests/unit/cli/update-cmd.test.ts": true,
|
|
7922
7935
|
"tests/unit/cli/version-cmd.test.ts": true,
|
|
7923
7936
|
"tests/unit/cli/workstation-cmd.test.ts": true,
|
|
7937
|
+
"tests/unit/cli/worktree-liveness.test.ts": true,
|
|
7938
|
+
"tests/unit/cli/worktree-ownership.test.ts": true,
|
|
7939
|
+
"tests/unit/cli/worktree-prune-policy.test.ts": true,
|
|
7924
7940
|
"tests/unit/codex/agent-installer.test.ts": true,
|
|
7925
7941
|
"tests/unit/codex/agent-transformer.test.ts": true,
|
|
7926
7942
|
"tests/unit/codex/agents-md-installer.test.ts": true,
|