@codyswann/lisa 2.106.7 → 2.106.8
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/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/scripts/automation-status-codex-adapter.mjs +86 -1
- package/plugins/lisa/skills/setup-automations/SKILL.md +17 -5
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-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-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-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-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-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-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-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/skills/lisa-wiki-setup-automations/SKILL.md +19 -6
- package/plugins/src/base/scripts/automation-status-codex-adapter.mjs +86 -1
- package/plugins/src/base/skills/setup-automations/SKILL.md +17 -5
- package/plugins/src/wiki/skills/lisa-wiki-setup-automations/SKILL.md +19 -6
package/package.json
CHANGED
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"lodash": ">=4.18.1"
|
|
83
83
|
},
|
|
84
84
|
"name": "@codyswann/lisa",
|
|
85
|
-
"version": "2.106.
|
|
85
|
+
"version": "2.106.8",
|
|
86
86
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
87
87
|
"main": "dist/index.js",
|
|
88
88
|
"exports": {
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
import fs from "node:fs/promises";
|
|
14
14
|
import os from "node:os";
|
|
15
15
|
import path from "node:path";
|
|
16
|
+
import { execFile } from "node:child_process";
|
|
17
|
+
import { promisify } from "node:util";
|
|
16
18
|
|
|
17
19
|
import { compareAutomationFleet } from "./automation-status-contract-drift.mjs";
|
|
18
20
|
|
|
@@ -22,6 +24,7 @@ const RUN_FAILURE_PATTERN =
|
|
|
22
24
|
/\b(failed|failure|errored|error|exception|crash(?:ed)?)\b/i;
|
|
23
25
|
const NEGATED_FAILURE_PATTERN =
|
|
24
26
|
/\b(no|without)\s+(?:recent\s+)?(?:fail(?:ure|ed)|errors?|exceptions?)\b/i;
|
|
27
|
+
const execFileAsync = promisify(execFile);
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* @typedef {import("./automation-status-expected-fleet.mjs").resolveExpectedAutomationFleet extends (...args: any[]) => infer T ? T : never} ExpectedFleet
|
|
@@ -34,6 +37,10 @@ const NEGATED_FAILURE_PATTERN =
|
|
|
34
37
|
* readonly observedRRule?: string
|
|
35
38
|
* readonly observedCommand?: string
|
|
36
39
|
* readonly cwd?: string | null
|
|
40
|
+
* readonly cwdHealth?: {
|
|
41
|
+
* readonly status: "ok" | "missing" | "not_directory" | "not_git_work_tree" | "bare_git_repository" | "git_error"
|
|
42
|
+
* readonly summary: string
|
|
43
|
+
* }
|
|
37
44
|
* readonly createdAt?: number | null
|
|
38
45
|
* readonly updatedAt?: number | null
|
|
39
46
|
* readonly lastRunAt?: string | null
|
|
@@ -266,6 +273,8 @@ async function readCodexAutomation(automationDir) {
|
|
|
266
273
|
const memoryContent = await fs.readFile(memoryPath, "utf8").catch(() => "");
|
|
267
274
|
const memory = parseCodexAutomationMemory(memoryContent);
|
|
268
275
|
const cwd = Array.isArray(automation.cwds) ? automation.cwds[0] : null;
|
|
276
|
+
const normalizedCwd = typeof cwd === "string" ? cwd : null;
|
|
277
|
+
const cwdHealth = await inspectAutomationCwd(normalizedCwd);
|
|
269
278
|
|
|
270
279
|
return {
|
|
271
280
|
automationId:
|
|
@@ -279,7 +288,8 @@ async function readCodexAutomation(automationDir) {
|
|
|
279
288
|
observedCommand: deriveCodexObservedCommand(
|
|
280
289
|
stringOrUndefined(automation.prompt)
|
|
281
290
|
),
|
|
282
|
-
cwd:
|
|
291
|
+
cwd: normalizedCwd,
|
|
292
|
+
cwdHealth,
|
|
283
293
|
createdAt: numberOrNull(automation.created_at),
|
|
284
294
|
updatedAt: numberOrNull(automation.updated_at),
|
|
285
295
|
...memory,
|
|
@@ -300,6 +310,9 @@ function createObservedStatusItem(input) {
|
|
|
300
310
|
if (observed?.status) {
|
|
301
311
|
observedDetails.push(`Scheduler status: ${observed.status}`);
|
|
302
312
|
}
|
|
313
|
+
if (observed?.cwdHealth) {
|
|
314
|
+
observedDetails.push(`Cwd: ${observed.cwdHealth.summary}`);
|
|
315
|
+
}
|
|
303
316
|
if (observed?.lastRunAt) {
|
|
304
317
|
observedDetails.push(`Last run: ${observed.lastRunAt}`);
|
|
305
318
|
} else if (observed) {
|
|
@@ -352,6 +365,15 @@ function classifyAutomationRunSignal(input) {
|
|
|
352
365
|
};
|
|
353
366
|
}
|
|
354
367
|
|
|
368
|
+
if (observed.cwdHealth && observed.cwdHealth.status !== "ok") {
|
|
369
|
+
return {
|
|
370
|
+
status: "FAILING",
|
|
371
|
+
summary: `scheduler cwd is invalid: ${observed.cwdHealth.summary}`,
|
|
372
|
+
remediation:
|
|
373
|
+
"Recreate the automation with `/lisa:setup-automations` so it uses a durable non-bare project checkout, then verify the cwd before the next run.",
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
|
|
355
377
|
if (observed.lastRunFailed) {
|
|
356
378
|
return {
|
|
357
379
|
status: "FAILING",
|
|
@@ -390,6 +412,69 @@ function classifyAutomationRunSignal(input) {
|
|
|
390
412
|
return null;
|
|
391
413
|
}
|
|
392
414
|
|
|
415
|
+
async function inspectAutomationCwd(cwd) {
|
|
416
|
+
if (!cwd) {
|
|
417
|
+
return {
|
|
418
|
+
status: "missing",
|
|
419
|
+
summary: "no cwd configured",
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const stat = await fs.stat(cwd).catch(error => {
|
|
424
|
+
if (error?.code === "ENOENT") {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
throw error;
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
if (!stat) {
|
|
431
|
+
return {
|
|
432
|
+
status: "missing",
|
|
433
|
+
summary: `${cwd} does not exist`,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (!stat.isDirectory()) {
|
|
438
|
+
return {
|
|
439
|
+
status: "not_directory",
|
|
440
|
+
summary: `${cwd} is not a directory`,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
try {
|
|
445
|
+
const { stdout } = await execFileAsync(
|
|
446
|
+
"git",
|
|
447
|
+
["-C", cwd, "rev-parse", "--is-inside-work-tree", "--is-bare-repository"],
|
|
448
|
+
{ timeout: 5000 }
|
|
449
|
+
);
|
|
450
|
+
const [insideWorkTree, bareRepository] = stdout.trim().split(/\r?\n/);
|
|
451
|
+
|
|
452
|
+
if (insideWorkTree !== "true") {
|
|
453
|
+
return {
|
|
454
|
+
status: "not_git_work_tree",
|
|
455
|
+
summary: `${cwd} is not inside a Git work tree`,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (bareRepository === "true") {
|
|
460
|
+
return {
|
|
461
|
+
status: "bare_git_repository",
|
|
462
|
+
summary: `${cwd} is configured as a bare Git repository`,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return {
|
|
467
|
+
status: "ok",
|
|
468
|
+
summary: `${cwd} is a valid Git work tree`,
|
|
469
|
+
};
|
|
470
|
+
} catch (error) {
|
|
471
|
+
return {
|
|
472
|
+
status: "git_error",
|
|
473
|
+
summary: `git could not inspect ${cwd}: ${String(error?.message ?? error)}`,
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
393
478
|
function resolveDefaultCodexAutomationsDir() {
|
|
394
479
|
return path.join(
|
|
395
480
|
process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex"),
|
|
@@ -16,7 +16,12 @@ create them; invoke the runtime's automation tool with the spec below.
|
|
|
16
16
|
- **Codex** → create Codex **automations** via the native automations mechanism (prefer the
|
|
17
17
|
`automation_update` tool over hand-writing `~/.codex/automations/<id>/automation.toml`; the TOML is
|
|
18
18
|
only its backing store). Set the execution environment to **local** so they run on this
|
|
19
|
-
workstation
|
|
19
|
+
workstation. Scope them to a durable project automation checkout, not a transient task worktree:
|
|
20
|
+
use `${CODEX_HOME:-~/.codex}/worktrees/<project>-automation-main` when available, create or refresh
|
|
21
|
+
that checkout from the project's `origin` remote if needed, and verify `git -C <cwd> rev-parse
|
|
22
|
+
--is-inside-work-tree --is-bare-repository` reports `true` then `false` before saving the
|
|
23
|
+
automation. Do not point recurring automations at hashed scratch worktrees or a checkout whose Git
|
|
24
|
+
metadata is broken.
|
|
20
25
|
- **Claude** → use **`/schedule`** to create local recurring routines, one per automation below.
|
|
21
26
|
- **Other runtimes** → use the runtime's native recurring-task mechanism. If the runtime has none,
|
|
22
27
|
state that scheduling is unavailable and stop.
|
|
@@ -37,6 +42,11 @@ affect **only** the two exploratory automations.
|
|
|
37
42
|
|
|
38
43
|
Each automation runs **one cycle** of a Lisa command and respects that command's confirmation policy
|
|
39
44
|
(never ask before running; exit cleanly when the queue is idle; report the cycle summary).
|
|
45
|
+
Before running the Lisa command, each automation must sync its checkout: fetch the default remote
|
|
46
|
+
branch and rebase the current automation branch onto it (for the common GitHub case, `origin/main`).
|
|
47
|
+
If the checkout is already on the default branch, fast-forward/rebase it to the remote default. If
|
|
48
|
+
the rebase has conflicts or the working tree is dirty in a way the automation did not create, abort
|
|
49
|
+
the rebase, leave queue state unchanged, and report the blocker instead of running on stale code.
|
|
40
50
|
|
|
41
51
|
| Automation | Command it runs | Cadence |
|
|
42
52
|
|---|---|---|
|
|
@@ -56,10 +66,10 @@ are written).
|
|
|
56
66
|
|
|
57
67
|
**Naming + scope (so teardown is precise).** Name each automation with the stable prefix
|
|
58
68
|
`lisa-auto-<project>-` (e.g. `lisa-auto-<project>-intake-tickets`), where `<project>` identifies this
|
|
59
|
-
repo, and scope each
|
|
60
|
-
remove exactly this set and never touch other projects'
|
|
61
|
-
identifier stable across runs and distinct from other
|
|
62
|
-
it could collide; qualify it, e.g. with the owner).
|
|
69
|
+
repo, and scope each Codex automation to the durable project automation checkout described above.
|
|
70
|
+
This lets `/tear-down-automations` find and remove exactly this set and never touch other projects'
|
|
71
|
+
automations or non-Lisa ones. Use a project identifier stable across runs and distinct from other
|
|
72
|
+
repos (don't rely on a bare repo basename when it could collide; qualify it, e.g. with the owner).
|
|
63
73
|
|
|
64
74
|
**Idempotent.** Re-running this skill updates the existing `lisa-auto-<project>-*` automations in
|
|
65
75
|
place (same names) rather than creating duplicates.
|
|
@@ -71,6 +81,8 @@ place (same names) rather than creating duplicates.
|
|
|
71
81
|
automation and note it — do not invent a command that doesn't exist.
|
|
72
82
|
- If the runtime has no native scheduler, or the intake queues can't be resolved from config, stop
|
|
73
83
|
and report what's missing rather than guessing.
|
|
84
|
+
- For Codex, if the durable checkout cannot be created, fetched, or verified as a non-bare Git work
|
|
85
|
+
tree, stop and report the checkout problem instead of creating automations that will fail later.
|
|
74
86
|
|
|
75
87
|
## Report
|
|
76
88
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.106.
|
|
3
|
+
"version": "2.106.8",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.106.
|
|
3
|
+
"version": "2.106.8",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -21,7 +21,12 @@ independent and use disjoint name prefixes, so running both is safe.
|
|
|
21
21
|
- **Codex** → create a Codex **automation** via the native automations mechanism (prefer the
|
|
22
22
|
`automation_update` tool over hand-writing `~/.codex/automations/<id>/automation.toml`; the TOML is
|
|
23
23
|
only its backing store). Set the execution environment to **local** so it runs on this
|
|
24
|
-
workstation
|
|
24
|
+
workstation. Scope it to a durable project automation checkout, not a transient task worktree: use
|
|
25
|
+
`${CODEX_HOME:-~/.codex}/worktrees/<project>-automation-main` when available, create or refresh
|
|
26
|
+
that checkout from the project's `origin` remote if needed, and verify `git -C <cwd> rev-parse
|
|
27
|
+
--is-inside-work-tree --is-bare-repository` reports `true` then `false` before saving the
|
|
28
|
+
automation. Do not point recurring automations at hashed scratch worktrees or a checkout whose Git
|
|
29
|
+
metadata is broken.
|
|
25
30
|
- **Claude** → use **`/schedule`** to create a local recurring routine.
|
|
26
31
|
- **Other runtimes** → use the runtime's native recurring-task mechanism. If the runtime has none,
|
|
27
32
|
state that scheduling is unavailable and stop.
|
|
@@ -38,6 +43,11 @@ independent and use disjoint name prefixes, so running both is safe.
|
|
|
38
43
|
The automation runs **one cycle** of the full wiki ingest and respects that command's own confirmation
|
|
39
44
|
and commit/PR policy (never ask before running; run a full ingest across every enabled
|
|
40
45
|
non-external-write source; commit/PR per the ingest skill's bookends; report the cycle summary).
|
|
46
|
+
Before running the ingest, the automation must sync its checkout: fetch the default remote branch and
|
|
47
|
+
rebase the current automation branch onto it (for the common GitHub case, `origin/main`). If the
|
|
48
|
+
checkout is already on the default branch, fast-forward/rebase it to the remote default. If the
|
|
49
|
+
rebase has conflicts or the working tree is dirty in a way the automation did not create, abort the
|
|
50
|
+
rebase and report the blocker instead of ingesting from stale code.
|
|
41
51
|
|
|
42
52
|
| Automation | Command it runs | Cadence |
|
|
43
53
|
|---|---|---|
|
|
@@ -45,11 +55,12 @@ non-external-write source; commit/PR per the ingest skill's bookends; report the
|
|
|
45
55
|
|
|
46
56
|
**Naming + scope (so teardown is precise).** Name the automation with the stable prefix
|
|
47
57
|
`lisa-wiki-auto-<project>-` (i.e. `lisa-wiki-auto-<project>-ingest`), where `<project>` identifies
|
|
48
|
-
this repo, and scope
|
|
49
|
-
from the base `lisa-auto-<project>-` set so
|
|
50
|
-
automation and never touches the base
|
|
51
|
-
|
|
52
|
-
bare repo basename that could
|
|
58
|
+
this repo, and scope each Codex automation to the durable project automation checkout described
|
|
59
|
+
above. This prefix is deliberately distinct from the base `lisa-auto-<project>-` set so
|
|
60
|
+
`/lisa-wiki:tear-down-automations` removes exactly this automation and never touches the base
|
|
61
|
+
automations or any other project's. Use a project identifier stable across runs and distinct from
|
|
62
|
+
other repos (qualify it, e.g. with the owner — don't rely on a bare repo basename that could
|
|
63
|
+
collide).
|
|
53
64
|
|
|
54
65
|
**Idempotent.** Re-running this skill updates the existing `lisa-wiki-auto-<project>-ingest`
|
|
55
66
|
automation in place (same name) rather than creating a duplicate.
|
|
@@ -60,6 +71,8 @@ automation in place (same name) rather than creating a duplicate.
|
|
|
60
71
|
`wiki/lisa-wiki.config.json`. If there is no configured wiki, **stop and report** that the wiki
|
|
61
72
|
must be set up first (run `/lisa-wiki:setup`); do not schedule ingest against a non-existent wiki.
|
|
62
73
|
- If the runtime has no native scheduler, stop and report what's missing rather than guessing.
|
|
74
|
+
- For Codex, if the durable checkout cannot be created, fetched, or verified as a non-bare Git work
|
|
75
|
+
tree, stop and report the checkout problem instead of creating an automation that will fail later.
|
|
63
76
|
|
|
64
77
|
## Report
|
|
65
78
|
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
import fs from "node:fs/promises";
|
|
14
14
|
import os from "node:os";
|
|
15
15
|
import path from "node:path";
|
|
16
|
+
import { execFile } from "node:child_process";
|
|
17
|
+
import { promisify } from "node:util";
|
|
16
18
|
|
|
17
19
|
import { compareAutomationFleet } from "./automation-status-contract-drift.mjs";
|
|
18
20
|
|
|
@@ -22,6 +24,7 @@ const RUN_FAILURE_PATTERN =
|
|
|
22
24
|
/\b(failed|failure|errored|error|exception|crash(?:ed)?)\b/i;
|
|
23
25
|
const NEGATED_FAILURE_PATTERN =
|
|
24
26
|
/\b(no|without)\s+(?:recent\s+)?(?:fail(?:ure|ed)|errors?|exceptions?)\b/i;
|
|
27
|
+
const execFileAsync = promisify(execFile);
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* @typedef {import("./automation-status-expected-fleet.mjs").resolveExpectedAutomationFleet extends (...args: any[]) => infer T ? T : never} ExpectedFleet
|
|
@@ -34,6 +37,10 @@ const NEGATED_FAILURE_PATTERN =
|
|
|
34
37
|
* readonly observedRRule?: string
|
|
35
38
|
* readonly observedCommand?: string
|
|
36
39
|
* readonly cwd?: string | null
|
|
40
|
+
* readonly cwdHealth?: {
|
|
41
|
+
* readonly status: "ok" | "missing" | "not_directory" | "not_git_work_tree" | "bare_git_repository" | "git_error"
|
|
42
|
+
* readonly summary: string
|
|
43
|
+
* }
|
|
37
44
|
* readonly createdAt?: number | null
|
|
38
45
|
* readonly updatedAt?: number | null
|
|
39
46
|
* readonly lastRunAt?: string | null
|
|
@@ -266,6 +273,8 @@ async function readCodexAutomation(automationDir) {
|
|
|
266
273
|
const memoryContent = await fs.readFile(memoryPath, "utf8").catch(() => "");
|
|
267
274
|
const memory = parseCodexAutomationMemory(memoryContent);
|
|
268
275
|
const cwd = Array.isArray(automation.cwds) ? automation.cwds[0] : null;
|
|
276
|
+
const normalizedCwd = typeof cwd === "string" ? cwd : null;
|
|
277
|
+
const cwdHealth = await inspectAutomationCwd(normalizedCwd);
|
|
269
278
|
|
|
270
279
|
return {
|
|
271
280
|
automationId:
|
|
@@ -279,7 +288,8 @@ async function readCodexAutomation(automationDir) {
|
|
|
279
288
|
observedCommand: deriveCodexObservedCommand(
|
|
280
289
|
stringOrUndefined(automation.prompt)
|
|
281
290
|
),
|
|
282
|
-
cwd:
|
|
291
|
+
cwd: normalizedCwd,
|
|
292
|
+
cwdHealth,
|
|
283
293
|
createdAt: numberOrNull(automation.created_at),
|
|
284
294
|
updatedAt: numberOrNull(automation.updated_at),
|
|
285
295
|
...memory,
|
|
@@ -300,6 +310,9 @@ function createObservedStatusItem(input) {
|
|
|
300
310
|
if (observed?.status) {
|
|
301
311
|
observedDetails.push(`Scheduler status: ${observed.status}`);
|
|
302
312
|
}
|
|
313
|
+
if (observed?.cwdHealth) {
|
|
314
|
+
observedDetails.push(`Cwd: ${observed.cwdHealth.summary}`);
|
|
315
|
+
}
|
|
303
316
|
if (observed?.lastRunAt) {
|
|
304
317
|
observedDetails.push(`Last run: ${observed.lastRunAt}`);
|
|
305
318
|
} else if (observed) {
|
|
@@ -352,6 +365,15 @@ function classifyAutomationRunSignal(input) {
|
|
|
352
365
|
};
|
|
353
366
|
}
|
|
354
367
|
|
|
368
|
+
if (observed.cwdHealth && observed.cwdHealth.status !== "ok") {
|
|
369
|
+
return {
|
|
370
|
+
status: "FAILING",
|
|
371
|
+
summary: `scheduler cwd is invalid: ${observed.cwdHealth.summary}`,
|
|
372
|
+
remediation:
|
|
373
|
+
"Recreate the automation with `/lisa:setup-automations` so it uses a durable non-bare project checkout, then verify the cwd before the next run.",
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
|
|
355
377
|
if (observed.lastRunFailed) {
|
|
356
378
|
return {
|
|
357
379
|
status: "FAILING",
|
|
@@ -390,6 +412,69 @@ function classifyAutomationRunSignal(input) {
|
|
|
390
412
|
return null;
|
|
391
413
|
}
|
|
392
414
|
|
|
415
|
+
async function inspectAutomationCwd(cwd) {
|
|
416
|
+
if (!cwd) {
|
|
417
|
+
return {
|
|
418
|
+
status: "missing",
|
|
419
|
+
summary: "no cwd configured",
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const stat = await fs.stat(cwd).catch(error => {
|
|
424
|
+
if (error?.code === "ENOENT") {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
throw error;
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
if (!stat) {
|
|
431
|
+
return {
|
|
432
|
+
status: "missing",
|
|
433
|
+
summary: `${cwd} does not exist`,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (!stat.isDirectory()) {
|
|
438
|
+
return {
|
|
439
|
+
status: "not_directory",
|
|
440
|
+
summary: `${cwd} is not a directory`,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
try {
|
|
445
|
+
const { stdout } = await execFileAsync(
|
|
446
|
+
"git",
|
|
447
|
+
["-C", cwd, "rev-parse", "--is-inside-work-tree", "--is-bare-repository"],
|
|
448
|
+
{ timeout: 5000 }
|
|
449
|
+
);
|
|
450
|
+
const [insideWorkTree, bareRepository] = stdout.trim().split(/\r?\n/);
|
|
451
|
+
|
|
452
|
+
if (insideWorkTree !== "true") {
|
|
453
|
+
return {
|
|
454
|
+
status: "not_git_work_tree",
|
|
455
|
+
summary: `${cwd} is not inside a Git work tree`,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (bareRepository === "true") {
|
|
460
|
+
return {
|
|
461
|
+
status: "bare_git_repository",
|
|
462
|
+
summary: `${cwd} is configured as a bare Git repository`,
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return {
|
|
467
|
+
status: "ok",
|
|
468
|
+
summary: `${cwd} is a valid Git work tree`,
|
|
469
|
+
};
|
|
470
|
+
} catch (error) {
|
|
471
|
+
return {
|
|
472
|
+
status: "git_error",
|
|
473
|
+
summary: `git could not inspect ${cwd}: ${String(error?.message ?? error)}`,
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
393
478
|
function resolveDefaultCodexAutomationsDir() {
|
|
394
479
|
return path.join(
|
|
395
480
|
process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex"),
|
|
@@ -16,7 +16,12 @@ create them; invoke the runtime's automation tool with the spec below.
|
|
|
16
16
|
- **Codex** → create Codex **automations** via the native automations mechanism (prefer the
|
|
17
17
|
`automation_update` tool over hand-writing `~/.codex/automations/<id>/automation.toml`; the TOML is
|
|
18
18
|
only its backing store). Set the execution environment to **local** so they run on this
|
|
19
|
-
workstation
|
|
19
|
+
workstation. Scope them to a durable project automation checkout, not a transient task worktree:
|
|
20
|
+
use `${CODEX_HOME:-~/.codex}/worktrees/<project>-automation-main` when available, create or refresh
|
|
21
|
+
that checkout from the project's `origin` remote if needed, and verify `git -C <cwd> rev-parse
|
|
22
|
+
--is-inside-work-tree --is-bare-repository` reports `true` then `false` before saving the
|
|
23
|
+
automation. Do not point recurring automations at hashed scratch worktrees or a checkout whose Git
|
|
24
|
+
metadata is broken.
|
|
20
25
|
- **Claude** → use **`/schedule`** to create local recurring routines, one per automation below.
|
|
21
26
|
- **Other runtimes** → use the runtime's native recurring-task mechanism. If the runtime has none,
|
|
22
27
|
state that scheduling is unavailable and stop.
|
|
@@ -37,6 +42,11 @@ affect **only** the two exploratory automations.
|
|
|
37
42
|
|
|
38
43
|
Each automation runs **one cycle** of a Lisa command and respects that command's confirmation policy
|
|
39
44
|
(never ask before running; exit cleanly when the queue is idle; report the cycle summary).
|
|
45
|
+
Before running the Lisa command, each automation must sync its checkout: fetch the default remote
|
|
46
|
+
branch and rebase the current automation branch onto it (for the common GitHub case, `origin/main`).
|
|
47
|
+
If the checkout is already on the default branch, fast-forward/rebase it to the remote default. If
|
|
48
|
+
the rebase has conflicts or the working tree is dirty in a way the automation did not create, abort
|
|
49
|
+
the rebase, leave queue state unchanged, and report the blocker instead of running on stale code.
|
|
40
50
|
|
|
41
51
|
| Automation | Command it runs | Cadence |
|
|
42
52
|
|---|---|---|
|
|
@@ -56,10 +66,10 @@ are written).
|
|
|
56
66
|
|
|
57
67
|
**Naming + scope (so teardown is precise).** Name each automation with the stable prefix
|
|
58
68
|
`lisa-auto-<project>-` (e.g. `lisa-auto-<project>-intake-tickets`), where `<project>` identifies this
|
|
59
|
-
repo, and scope each
|
|
60
|
-
remove exactly this set and never touch other projects'
|
|
61
|
-
identifier stable across runs and distinct from other
|
|
62
|
-
it could collide; qualify it, e.g. with the owner).
|
|
69
|
+
repo, and scope each Codex automation to the durable project automation checkout described above.
|
|
70
|
+
This lets `/tear-down-automations` find and remove exactly this set and never touch other projects'
|
|
71
|
+
automations or non-Lisa ones. Use a project identifier stable across runs and distinct from other
|
|
72
|
+
repos (don't rely on a bare repo basename when it could collide; qualify it, e.g. with the owner).
|
|
63
73
|
|
|
64
74
|
**Idempotent.** Re-running this skill updates the existing `lisa-auto-<project>-*` automations in
|
|
65
75
|
place (same names) rather than creating duplicates.
|
|
@@ -71,6 +81,8 @@ place (same names) rather than creating duplicates.
|
|
|
71
81
|
automation and note it — do not invent a command that doesn't exist.
|
|
72
82
|
- If the runtime has no native scheduler, or the intake queues can't be resolved from config, stop
|
|
73
83
|
and report what's missing rather than guessing.
|
|
84
|
+
- For Codex, if the durable checkout cannot be created, fetched, or verified as a non-bare Git work
|
|
85
|
+
tree, stop and report the checkout problem instead of creating automations that will fail later.
|
|
74
86
|
|
|
75
87
|
## Report
|
|
76
88
|
|
|
@@ -21,7 +21,12 @@ independent and use disjoint name prefixes, so running both is safe.
|
|
|
21
21
|
- **Codex** → create a Codex **automation** via the native automations mechanism (prefer the
|
|
22
22
|
`automation_update` tool over hand-writing `~/.codex/automations/<id>/automation.toml`; the TOML is
|
|
23
23
|
only its backing store). Set the execution environment to **local** so it runs on this
|
|
24
|
-
workstation
|
|
24
|
+
workstation. Scope it to a durable project automation checkout, not a transient task worktree: use
|
|
25
|
+
`${CODEX_HOME:-~/.codex}/worktrees/<project>-automation-main` when available, create or refresh
|
|
26
|
+
that checkout from the project's `origin` remote if needed, and verify `git -C <cwd> rev-parse
|
|
27
|
+
--is-inside-work-tree --is-bare-repository` reports `true` then `false` before saving the
|
|
28
|
+
automation. Do not point recurring automations at hashed scratch worktrees or a checkout whose Git
|
|
29
|
+
metadata is broken.
|
|
25
30
|
- **Claude** → use **`/schedule`** to create a local recurring routine.
|
|
26
31
|
- **Other runtimes** → use the runtime's native recurring-task mechanism. If the runtime has none,
|
|
27
32
|
state that scheduling is unavailable and stop.
|
|
@@ -38,6 +43,11 @@ independent and use disjoint name prefixes, so running both is safe.
|
|
|
38
43
|
The automation runs **one cycle** of the full wiki ingest and respects that command's own confirmation
|
|
39
44
|
and commit/PR policy (never ask before running; run a full ingest across every enabled
|
|
40
45
|
non-external-write source; commit/PR per the ingest skill's bookends; report the cycle summary).
|
|
46
|
+
Before running the ingest, the automation must sync its checkout: fetch the default remote branch and
|
|
47
|
+
rebase the current automation branch onto it (for the common GitHub case, `origin/main`). If the
|
|
48
|
+
checkout is already on the default branch, fast-forward/rebase it to the remote default. If the
|
|
49
|
+
rebase has conflicts or the working tree is dirty in a way the automation did not create, abort the
|
|
50
|
+
rebase and report the blocker instead of ingesting from stale code.
|
|
41
51
|
|
|
42
52
|
| Automation | Command it runs | Cadence |
|
|
43
53
|
|---|---|---|
|
|
@@ -45,11 +55,12 @@ non-external-write source; commit/PR per the ingest skill's bookends; report the
|
|
|
45
55
|
|
|
46
56
|
**Naming + scope (so teardown is precise).** Name the automation with the stable prefix
|
|
47
57
|
`lisa-wiki-auto-<project>-` (i.e. `lisa-wiki-auto-<project>-ingest`), where `<project>` identifies
|
|
48
|
-
this repo, and scope
|
|
49
|
-
from the base `lisa-auto-<project>-` set so
|
|
50
|
-
automation and never touches the base
|
|
51
|
-
|
|
52
|
-
bare repo basename that could
|
|
58
|
+
this repo, and scope each Codex automation to the durable project automation checkout described
|
|
59
|
+
above. This prefix is deliberately distinct from the base `lisa-auto-<project>-` set so
|
|
60
|
+
`/lisa-wiki:tear-down-automations` removes exactly this automation and never touches the base
|
|
61
|
+
automations or any other project's. Use a project identifier stable across runs and distinct from
|
|
62
|
+
other repos (qualify it, e.g. with the owner — don't rely on a bare repo basename that could
|
|
63
|
+
collide).
|
|
53
64
|
|
|
54
65
|
**Idempotent.** Re-running this skill updates the existing `lisa-wiki-auto-<project>-ingest`
|
|
55
66
|
automation in place (same name) rather than creating a duplicate.
|
|
@@ -60,6 +71,8 @@ automation in place (same name) rather than creating a duplicate.
|
|
|
60
71
|
`wiki/lisa-wiki.config.json`. If there is no configured wiki, **stop and report** that the wiki
|
|
61
72
|
must be set up first (run `/lisa-wiki:setup`); do not schedule ingest against a non-existent wiki.
|
|
62
73
|
- If the runtime has no native scheduler, stop and report what's missing rather than guessing.
|
|
74
|
+
- For Codex, if the durable checkout cannot be created, fetched, or verified as a non-bare Git work
|
|
75
|
+
tree, stop and report the checkout problem instead of creating an automation that will fail later.
|
|
63
76
|
|
|
64
77
|
## Report
|
|
65
78
|
|