@ctrl-spc/cs 0.7.5 → 0.7.6
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/panel3/run.js +26 -2
- package/package.json +1 -1
package/dist/panel3/run.js
CHANGED
|
@@ -148,6 +148,7 @@ import { listCodebases } from '../codebases.js';
|
|
|
148
148
|
import { killTree, processIsAlive } from '../win-shell.js';
|
|
149
149
|
import { hostname, uptime } from 'node:os';
|
|
150
150
|
import { execFileSync } from 'node:child_process';
|
|
151
|
+
import { existsSync } from 'node:fs';
|
|
151
152
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
152
153
|
import { join } from 'node:path';
|
|
153
154
|
const USAGE = 'usage: run [--once]';
|
|
@@ -1030,6 +1031,14 @@ export async function picturesOnDisk(client, cardId, where, level) {
|
|
|
1030
1031
|
.eq('card_id', cardId).order('created_at'), 'read', `the pictures on card ${cardId}`);
|
|
1031
1032
|
if (images.length === 0)
|
|
1032
1033
|
return [];
|
|
1034
|
+
/* ═══ A CWD THAT IS GONE IS A FAILURE, NOT A FOLDER TO MAKE. ═══ `recursive`
|
|
1035
|
+
below would rebuild a removed worktree as a plain directory holding one
|
|
1036
|
+
`ctrl-spc-images/`, which is exactly the folder `worktreeForCard` then
|
|
1037
|
+
refuses on every start (.bugs/.resolved/20260905-card-stuck-not-a-working-copy). */
|
|
1038
|
+
if (!existsSync(where.cwd)) {
|
|
1039
|
+
throw new Error('This card\'s working copy went away while its agent was starting. Send your message '
|
|
1040
|
+
+ 'again and it is made afresh.');
|
|
1041
|
+
}
|
|
1033
1042
|
const folder = join(gitDirOf(where.cwd) ?? where.cwd, 'ctrl-spc-images');
|
|
1034
1043
|
await mkdir(folder, { recursive: true });
|
|
1035
1044
|
const lines = [];
|
|
@@ -2847,6 +2856,8 @@ export async function takeHandedBack(client, tools, machineId, mine, hold) {
|
|
|
2847
2856
|
* normalised into a constant getter below, so there is one shape inside `run`
|
|
2848
2857
|
* and no branch anywhere near the poll.
|
|
2849
2858
|
*/
|
|
2859
|
+
/** The card states in which nobody will start again on the card's copy. */
|
|
2860
|
+
const CARD_IS_OVER = ['done', 'failed', 'stopped'];
|
|
2850
2861
|
/**
|
|
2851
2862
|
* ═══ THE CARD IS OVER, SO ITS COPY GOES — AND THE BRANCH STAYS. ═══
|
|
2852
2863
|
*
|
|
@@ -2865,7 +2876,7 @@ export async function takeHandedBack(client, tools, machineId, mine, hold) {
|
|
|
2865
2876
|
* A folder no row explains is LEFT ALONE. Nothing here deletes something it
|
|
2866
2877
|
* cannot account for.
|
|
2867
2878
|
*/
|
|
2868
|
-
async function sweepFinishedWorktrees(client) {
|
|
2879
|
+
export async function sweepFinishedWorktrees(client) {
|
|
2869
2880
|
const held = worktreesOnThisMachine();
|
|
2870
2881
|
if (held.length === 0)
|
|
2871
2882
|
return;
|
|
@@ -2889,6 +2900,17 @@ async function sweepFinishedWorktrees(client) {
|
|
|
2889
2900
|
const cards = [...new Set([...cardOfFolder.values()].flat())];
|
|
2890
2901
|
if (cards.length === 0)
|
|
2891
2902
|
return;
|
|
2903
|
+
/* ═══ THE CARD IS ASKED, NOT ONLY ITS RUNS. ═══ A conversational owner is
|
|
2904
|
+
parked between wakes with `ended_at` set, so the second its last worker
|
|
2905
|
+
finishes, no run on the card is open, while the card itself still reads
|
|
2906
|
+
`working`. Reading the runs alone called that card finished and took the
|
|
2907
|
+
copy out from under the owner as it was starting
|
|
2908
|
+
(.bugs/.resolved/20260905-card-stuck-not-a-working-copy). The card's own
|
|
2909
|
+
state is the record's word for whether it is over; the runs still guard a
|
|
2910
|
+
card that is over on paper while a process of it is going. */
|
|
2911
|
+
const over = new Set((await returned(client.from('panel3_cards')
|
|
2912
|
+
.select('id, state')
|
|
2913
|
+
.in('id', cards), 'read', 'which of those cards are over')).filter((row) => CARD_IS_OVER.includes(row.state)).map((row) => row.id));
|
|
2892
2914
|
const live = new Set((await returned(client.from('panel3_runs')
|
|
2893
2915
|
.select('card_id')
|
|
2894
2916
|
.in('card_id', cards)
|
|
@@ -2896,7 +2918,9 @@ async function sweepFinishedWorktrees(client) {
|
|
|
2896
2918
|
const touched = new Set();
|
|
2897
2919
|
for (const one of held) {
|
|
2898
2920
|
const cardIds = cardOfFolder.get(one.folder) ?? [];
|
|
2899
|
-
if (cardIds.length === 0
|
|
2921
|
+
if (cardIds.length === 0)
|
|
2922
|
+
continue;
|
|
2923
|
+
if (!cardIds.every((cardId) => over.has(cardId) && !live.has(cardId)))
|
|
2900
2924
|
continue;
|
|
2901
2925
|
try {
|
|
2902
2926
|
settleCardWorktree(one.folder);
|
package/package.json
CHANGED