lazycodex-ai 4.16.0 → 4.16.2
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/codex-ulw-loop.d.ts +8 -0
- package/dist/cli/get-local-version/types.d.ts +1 -1
- package/dist/cli/index.js +260 -207
- package/dist/cli-node/index.js +260 -207
- package/docs/reference/web-terminal-visual-qa.md +39 -45
- package/package.json +3 -2
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +3 -3
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +1 -1
- package/packages/omo-codex/plugin/components/teammode/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +3 -3
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +19 -10
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +19 -10
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +13 -0
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +2 -0
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +22 -1
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +4 -0
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +19 -10
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +15 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +89 -27
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +55 -9
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-snapshot.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-snapshot.js +33 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.d.ts +10 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +15 -11
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +7 -7
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +17 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +59 -11
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-snapshot.ts +38 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering-types.ts +11 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +15 -7
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +16 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +260 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering-snapshot.test.ts +124 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +101 -2
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +13 -13
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +64 -17
- package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +10 -6
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +186 -20
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +51 -3
- package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +33 -5
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +9 -9
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +7 -3
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +24 -2
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +1 -1
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +3 -3
- package/packages/omo-codex/plugin/skills/teammode/SKILL.md +3 -3
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +19 -10
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -1
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +7 -7
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +13 -0
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +2 -0
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +14 -18
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +4 -4
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +1 -1
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +35 -1
- package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +22 -9
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +275 -19
- package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +33 -0
- package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +6 -6
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +4 -2
- package/packages/omo-codex/plugin/test/ulw-plan-skill-contract.test.mjs +52 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +65 -39
- package/packages/shared-skills/skills/frontend/SKILL.md +9 -9
- package/packages/shared-skills/skills/frontend/references/design/README.md +7 -3
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +24 -2
- package/packages/shared-skills/skills/frontend/references/designpowers/README.md +2 -2
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +1 -1
- package/packages/shared-skills/skills/review-work/SKILL.md +3 -1
- package/packages/shared-skills/skills/start-work/SKILL.md +4 -2
- package/packages/shared-skills/skills/ulw-research/SKILL.md +3 -1
- package/packages/shared-skills/skills/visual-qa/SKILL.md +13 -17
- package/script/qa/strip-ansi.mjs +10 -0
- package/script/qa/web-terminal-visual-qa.mjs +112 -195
- package/script/qa/xterm-live-terminal.mjs +180 -0
- package/script/qa/web-terminal-renderer.mjs +0 -218
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import { copyFile, mkdir, mkdtemp, readdir, readFile, writeFile } from "node:fs/promises";
|
|
1
|
+
import { appendFile, copyFile, mkdir, mkdtemp, readdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { setImmediate as tick } from "node:timers/promises";
|
|
4
5
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
5
6
|
import { ulwLoopDir, ulwLoopGoalsPath, ulwLoopLedgerPath } from "../src/paths.js";
|
|
6
7
|
import {
|
|
7
8
|
appendLedger,
|
|
9
|
+
findAcceptedSteeringLedgerEntry,
|
|
8
10
|
readSteeringLedgerEntries,
|
|
9
11
|
readUlwLoopPlan,
|
|
10
12
|
withUlwLoopMutationLock,
|
|
11
13
|
writePlan,
|
|
12
14
|
} from "../src/plan-io.js";
|
|
13
|
-
import type { UlwLoopItem, UlwLoopLedgerEntry, UlwLoopPlan } from "../src/types.js";
|
|
15
|
+
import type { UlwLoopItem, UlwLoopLedgerEntry, UlwLoopPlan, UlwLoopSteeringAudit } from "../src/types.js";
|
|
14
16
|
import { UlwLoopError } from "../src/types.js";
|
|
15
17
|
|
|
16
18
|
const NOW = "2026-05-23T00:00:00.000Z";
|
|
@@ -51,6 +53,45 @@ function entry(kind: UlwLoopLedgerEntry["kind"], goalId = "G001"): UlwLoopLedger
|
|
|
51
53
|
return { at: NOW, kind, goalId };
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
function steeringAudit(overrides: Partial<UlwLoopSteeringAudit> = {}): UlwLoopSteeringAudit {
|
|
57
|
+
return {
|
|
58
|
+
kind: "revise_pending_wording",
|
|
59
|
+
source: "cli",
|
|
60
|
+
targetGoalIds: ["G001"],
|
|
61
|
+
evidence: "observed evidence",
|
|
62
|
+
rationale: "needed change",
|
|
63
|
+
invariant: {
|
|
64
|
+
accepted: true,
|
|
65
|
+
structuralInvariantAccepted: true,
|
|
66
|
+
evidenceBackedNecessity: true,
|
|
67
|
+
noEasierCompletion: true,
|
|
68
|
+
rejectedReasons: [],
|
|
69
|
+
},
|
|
70
|
+
...overrides,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function rejectedSteeringAudit(overrides: Partial<UlwLoopSteeringAudit> = {}): UlwLoopSteeringAudit {
|
|
75
|
+
return steeringAudit({
|
|
76
|
+
invariant: {
|
|
77
|
+
accepted: false,
|
|
78
|
+
structuralInvariantAccepted: false,
|
|
79
|
+
evidenceBackedNecessity: false,
|
|
80
|
+
noEasierCompletion: true,
|
|
81
|
+
rejectedReasons: ["missing evidence"],
|
|
82
|
+
},
|
|
83
|
+
...overrides,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function steeringEntry(
|
|
88
|
+
kind: UlwLoopLedgerEntry["kind"],
|
|
89
|
+
audit: UlwLoopSteeringAudit,
|
|
90
|
+
overrides: Partial<UlwLoopLedgerEntry> = {},
|
|
91
|
+
): UlwLoopLedgerEntry {
|
|
92
|
+
return { at: NOW, kind, goalId: "G001", steering: audit, ...overrides };
|
|
93
|
+
}
|
|
94
|
+
|
|
54
95
|
async function makeRepo(): Promise<string> {
|
|
55
96
|
return mkdtemp(join(tmpdir(), "ug-io-"));
|
|
56
97
|
}
|
|
@@ -209,6 +250,112 @@ describe("readSteeringLedgerEntries", () => {
|
|
|
209
250
|
});
|
|
210
251
|
});
|
|
211
252
|
|
|
253
|
+
describe("findAcceptedSteeringLedgerEntry", () => {
|
|
254
|
+
it.each([
|
|
255
|
+
[
|
|
256
|
+
"top-level idempotencyKey",
|
|
257
|
+
steeringEntry("steering_accepted", steeringAudit(), { idempotencyKey: "needle-key" }),
|
|
258
|
+
],
|
|
259
|
+
["steering.idempotencyKey", steeringEntry("steering_accepted", steeringAudit({ idempotencyKey: "needle-key" }))],
|
|
260
|
+
[
|
|
261
|
+
"steering.promptSignature",
|
|
262
|
+
steeringEntry("steering_accepted", steeringAudit({ promptSignature: "needle-key" })),
|
|
263
|
+
],
|
|
264
|
+
] as const)("finds an accepted entry by %s", async (_name, target) => {
|
|
265
|
+
// given
|
|
266
|
+
const repoRoot = await makeRepo();
|
|
267
|
+
await appendLedger(repoRoot, steeringEntry("steering_accepted", steeringAudit({ idempotencyKey: "other-key" })));
|
|
268
|
+
await appendLedger(repoRoot, target);
|
|
269
|
+
|
|
270
|
+
// when
|
|
271
|
+
const found = await findAcceptedSteeringLedgerEntry(repoRoot, "needle-key");
|
|
272
|
+
|
|
273
|
+
// then
|
|
274
|
+
expect(found).toEqual(target);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("skips a rejected entry carrying the same key", async () => {
|
|
278
|
+
// given
|
|
279
|
+
const repoRoot = await makeRepo();
|
|
280
|
+
await appendLedger(
|
|
281
|
+
repoRoot,
|
|
282
|
+
steeringEntry("steering_rejected", rejectedSteeringAudit({ idempotencyKey: "needle-key" })),
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
// when/then
|
|
286
|
+
await expect(findAcceptedSteeringLedgerEntry(repoRoot, "needle-key")).resolves.toBeUndefined();
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("returns the accepted entry even when a rejected one with the same key precedes it", async () => {
|
|
290
|
+
// given
|
|
291
|
+
const repoRoot = await makeRepo();
|
|
292
|
+
const accepted = steeringEntry("steering_accepted", steeringAudit({ idempotencyKey: "needle-key" }));
|
|
293
|
+
await appendLedger(
|
|
294
|
+
repoRoot,
|
|
295
|
+
steeringEntry("steering_rejected", rejectedSteeringAudit({ idempotencyKey: "needle-key" })),
|
|
296
|
+
);
|
|
297
|
+
await appendLedger(repoRoot, accepted);
|
|
298
|
+
|
|
299
|
+
// when/then
|
|
300
|
+
await expect(findAcceptedSteeringLedgerEntry(repoRoot, "needle-key")).resolves.toEqual(accepted);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it("returns undefined when the ledger file is missing", async () => {
|
|
304
|
+
// given
|
|
305
|
+
const repoRoot = await makeRepo();
|
|
306
|
+
|
|
307
|
+
// when/then
|
|
308
|
+
await expect(findAcceptedSteeringLedgerEntry(repoRoot, "needle-key")).resolves.toBeUndefined();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it("ignores the key when it only appears in non-steering entries", async () => {
|
|
312
|
+
// given
|
|
313
|
+
const repoRoot = await makeRepo();
|
|
314
|
+
await appendLedger(repoRoot, { at: NOW, kind: "goal_completed", goalId: "G001", idempotencyKey: "needle-key" });
|
|
315
|
+
await appendLedger(repoRoot, { at: NOW, kind: "evidence_captured", goalId: "G001", evidence: "needle-key" });
|
|
316
|
+
|
|
317
|
+
// when/then
|
|
318
|
+
await expect(findAcceptedSteeringLedgerEntry(repoRoot, "needle-key")).resolves.toBeUndefined();
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("ignores an accepted entry whose key only appears in evidence text", async () => {
|
|
322
|
+
// given
|
|
323
|
+
const repoRoot = await makeRepo();
|
|
324
|
+
await appendLedger(repoRoot, steeringEntry("steering_accepted", steeringAudit({ evidence: "needle-key" })));
|
|
325
|
+
|
|
326
|
+
// when/then
|
|
327
|
+
await expect(findAcceptedSteeringLedgerEntry(repoRoot, "needle-key")).resolves.toBeUndefined();
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it("finds the key inside a legacy entry embedding full before/after plans", async () => {
|
|
331
|
+
// given
|
|
332
|
+
const repoRoot = await makeRepo();
|
|
333
|
+
const bulkyGoals = Array.from({ length: 20 }, (_, index) =>
|
|
334
|
+
makeGoal({ id: `G${String(index + 1).padStart(3, "0")}`, objective: `evidence detail ${index} `.repeat(200) }),
|
|
335
|
+
);
|
|
336
|
+
const bulkyPlan = makePlan({ goals: bulkyGoals });
|
|
337
|
+
const legacyLine = JSON.stringify({
|
|
338
|
+
at: NOW,
|
|
339
|
+
kind: "steering_accepted",
|
|
340
|
+
goalId: "G001",
|
|
341
|
+
idempotencyKey: "needle-key",
|
|
342
|
+
before: bulkyPlan,
|
|
343
|
+
after: bulkyPlan,
|
|
344
|
+
steering: { ...steeringAudit({ idempotencyKey: "needle-key" }), before: bulkyPlan, after: bulkyPlan },
|
|
345
|
+
});
|
|
346
|
+
await mkdir(ulwLoopDir(repoRoot), { recursive: true });
|
|
347
|
+
await appendFile(ulwLoopLedgerPath(repoRoot), `${legacyLine}\n`, "utf8");
|
|
348
|
+
|
|
349
|
+
// when
|
|
350
|
+
const found = await findAcceptedSteeringLedgerEntry(repoRoot, "needle-key");
|
|
351
|
+
|
|
352
|
+
// then
|
|
353
|
+
expect(legacyLine.length).toBeGreaterThan(100_000);
|
|
354
|
+
expect(found?.kind).toBe("steering_accepted");
|
|
355
|
+
expect(found?.idempotencyKey).toBe("needle-key");
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
212
359
|
describe("withUlwLoopMutationLock", () => {
|
|
213
360
|
it("serializes concurrent invocations", async () => {
|
|
214
361
|
// given
|
|
@@ -236,4 +383,115 @@ describe("withUlwLoopMutationLock", () => {
|
|
|
236
383
|
expect(maxActive).toBe(1);
|
|
237
384
|
expect(await readFile(counterPath, "utf8")).toBe("3");
|
|
238
385
|
});
|
|
386
|
+
|
|
387
|
+
it("propagates the body rejection and keeps later calls working", async () => {
|
|
388
|
+
// given
|
|
389
|
+
const repoRoot = await makeRepo();
|
|
390
|
+
|
|
391
|
+
// when
|
|
392
|
+
const failure = withUlwLoopMutationLock(repoRoot, async () => {
|
|
393
|
+
throw new Error("body exploded");
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// then
|
|
397
|
+
await expect(failure).rejects.toThrow("body exploded");
|
|
398
|
+
await expect(withUlwLoopMutationLock(repoRoot, async () => "recovered")).resolves.toBe("recovered");
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it("still serializes a second batch after the first batch's gate settles", async () => {
|
|
402
|
+
// given
|
|
403
|
+
const repoRoot = await makeRepo();
|
|
404
|
+
let active = 0;
|
|
405
|
+
let maxActive = 0;
|
|
406
|
+
const body = async (): Promise<void> => {
|
|
407
|
+
active += 1;
|
|
408
|
+
maxActive = Math.max(maxActive, active);
|
|
409
|
+
await tick();
|
|
410
|
+
active -= 1;
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
// when
|
|
414
|
+
await Promise.all([1, 2, 3].map(() => withUlwLoopMutationLock(repoRoot, body)));
|
|
415
|
+
await tick();
|
|
416
|
+
await Promise.all([1, 2].map(() => withUlwLoopMutationLock(repoRoot, body)));
|
|
417
|
+
|
|
418
|
+
// then
|
|
419
|
+
expect(maxActive).toBe(1);
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
it("keeps an in-flight successor locked when an earlier gate settles", async () => {
|
|
423
|
+
// given
|
|
424
|
+
const repoRoot = await makeRepo();
|
|
425
|
+
const events: string[] = [];
|
|
426
|
+
let releaseSecond = false;
|
|
427
|
+
|
|
428
|
+
// when
|
|
429
|
+
const first = withUlwLoopMutationLock(repoRoot, async () => {
|
|
430
|
+
events.push("first");
|
|
431
|
+
});
|
|
432
|
+
const second = withUlwLoopMutationLock(repoRoot, async () => {
|
|
433
|
+
events.push("second:start");
|
|
434
|
+
while (!releaseSecond) await tick();
|
|
435
|
+
events.push("second:end");
|
|
436
|
+
});
|
|
437
|
+
await first;
|
|
438
|
+
await tick();
|
|
439
|
+
const third = withUlwLoopMutationLock(repoRoot, async () => {
|
|
440
|
+
events.push("third");
|
|
441
|
+
});
|
|
442
|
+
releaseSecond = true;
|
|
443
|
+
await Promise.all([second, third]);
|
|
444
|
+
|
|
445
|
+
// then
|
|
446
|
+
expect(events).toEqual(["first", "second:start", "second:end", "third"]);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it("does not serialize distinct repo roots against each other", async () => {
|
|
450
|
+
// given
|
|
451
|
+
const rootA = await makeRepo();
|
|
452
|
+
const rootB = await makeRepo();
|
|
453
|
+
const events: string[] = [];
|
|
454
|
+
let releaseA = false;
|
|
455
|
+
|
|
456
|
+
// when
|
|
457
|
+
const held = withUlwLoopMutationLock(rootA, async () => {
|
|
458
|
+
events.push("a:start");
|
|
459
|
+
while (!releaseA) await tick();
|
|
460
|
+
events.push("a:end");
|
|
461
|
+
});
|
|
462
|
+
await withUlwLoopMutationLock(rootB, async () => {
|
|
463
|
+
events.push("b");
|
|
464
|
+
});
|
|
465
|
+
releaseA = true;
|
|
466
|
+
await held;
|
|
467
|
+
|
|
468
|
+
// then
|
|
469
|
+
expect(events).toEqual(["a:start", "b", "a:end"]);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it("serializes per scope while distinct scopes stay independent", async () => {
|
|
473
|
+
// given
|
|
474
|
+
const repoRoot = await makeRepo();
|
|
475
|
+
const scoped = { sessionId: "session-a" };
|
|
476
|
+
const events: string[] = [];
|
|
477
|
+
let releaseScoped = false;
|
|
478
|
+
|
|
479
|
+
// when
|
|
480
|
+
const heldScoped = withUlwLoopMutationLock(repoRoot, scoped, async () => {
|
|
481
|
+
events.push("scoped-1:start");
|
|
482
|
+
while (!releaseScoped) await tick();
|
|
483
|
+
events.push("scoped-1:end");
|
|
484
|
+
});
|
|
485
|
+
const queuedScoped = withUlwLoopMutationLock(repoRoot, scoped, async () => {
|
|
486
|
+
events.push("scoped-2");
|
|
487
|
+
});
|
|
488
|
+
await withUlwLoopMutationLock(repoRoot, async () => {
|
|
489
|
+
events.push("root-scope");
|
|
490
|
+
});
|
|
491
|
+
releaseScoped = true;
|
|
492
|
+
await Promise.all([heldScoped, queuedScoped]);
|
|
493
|
+
|
|
494
|
+
// then
|
|
495
|
+
expect(events).toEqual(["scoped-1:start", "root-scope", "scoped-1:end", "scoped-2"]);
|
|
496
|
+
});
|
|
239
497
|
});
|
|
@@ -65,6 +65,6 @@ describe("ulw-loop skill contract", () => {
|
|
|
65
65
|
// then
|
|
66
66
|
expect(workflow.match(/malformed input, prompt injection/g)?.length ?? 0).toBe(1);
|
|
67
67
|
expect(wordCount(workflow)).toBeLessThanOrEqual(3697);
|
|
68
|
-
expect(wordCount(skill)).toBeLessThanOrEqual(
|
|
68
|
+
expect(wordCount(skill)).toBeLessThanOrEqual(625);
|
|
69
69
|
});
|
|
70
70
|
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { buildSteeringPlanSnapshot, changedGoalIdsBetween } from "../src/steering-snapshot.js";
|
|
3
|
+
import type { UlwLoopItem, UlwLoopPlan } from "../src/types.js";
|
|
4
|
+
|
|
5
|
+
const NOW = "2026-05-23T00:00:00.000Z";
|
|
6
|
+
|
|
7
|
+
function goal(id: string, overrides: Partial<UlwLoopItem> = {}): UlwLoopItem {
|
|
8
|
+
return {
|
|
9
|
+
id,
|
|
10
|
+
title: `Goal ${id}`,
|
|
11
|
+
objective: `Objective for ${id}`,
|
|
12
|
+
status: "pending",
|
|
13
|
+
successCriteria: [],
|
|
14
|
+
attempt: 0,
|
|
15
|
+
createdAt: NOW,
|
|
16
|
+
updatedAt: NOW,
|
|
17
|
+
...overrides,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function plan(goals: UlwLoopItem[], overrides: Partial<UlwLoopPlan> = {}): UlwLoopPlan {
|
|
22
|
+
return {
|
|
23
|
+
version: 1,
|
|
24
|
+
createdAt: NOW,
|
|
25
|
+
updatedAt: NOW,
|
|
26
|
+
briefPath: ".omo/ulw-loop/brief.md",
|
|
27
|
+
goalsPath: ".omo/ulw-loop/goals.json",
|
|
28
|
+
ledgerPath: ".omo/ulw-loop/ledger.jsonl",
|
|
29
|
+
goals,
|
|
30
|
+
...overrides,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("changedGoalIdsBetween", () => {
|
|
35
|
+
it.each([
|
|
36
|
+
{
|
|
37
|
+
name: "added goal",
|
|
38
|
+
before: [goal("G001"), goal("G002")],
|
|
39
|
+
after: [goal("G001"), goal("G002"), goal("G003")],
|
|
40
|
+
expected: ["G003"],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "removed goal",
|
|
44
|
+
before: [goal("G001"), goal("G002")],
|
|
45
|
+
after: [goal("G001")],
|
|
46
|
+
expected: ["G002"],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "mutated goal",
|
|
50
|
+
before: [goal("G001"), goal("G002")],
|
|
51
|
+
after: [goal("G001"), goal("G002", { title: "Rewritten" })],
|
|
52
|
+
expected: ["G002"],
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "reordered-only goals",
|
|
56
|
+
before: [goal("G001"), goal("G002"), goal("G003")],
|
|
57
|
+
after: [goal("G003"), goal("G001"), goal("G002")],
|
|
58
|
+
expected: [],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "identical plans",
|
|
62
|
+
before: [goal("G001"), goal("G002")],
|
|
63
|
+
after: [goal("G001"), goal("G002")],
|
|
64
|
+
expected: [],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "add + remove + mutate at once",
|
|
68
|
+
before: [goal("G001"), goal("G002"), goal("G003")],
|
|
69
|
+
after: [goal("G001", { status: "blocked" }), goal("G003"), goal("G004")],
|
|
70
|
+
expected: ["G001", "G002", "G004"],
|
|
71
|
+
},
|
|
72
|
+
])("detects $name", ({ before, after, expected }) => {
|
|
73
|
+
// when
|
|
74
|
+
const changed = changedGoalIdsBetween(plan(before), plan(after));
|
|
75
|
+
|
|
76
|
+
// then
|
|
77
|
+
expect([...changed].sort()).toEqual(expected);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("buildSteeringPlanSnapshot", () => {
|
|
82
|
+
it("includes only changed goals while keeping full goalIds order and goalCount", () => {
|
|
83
|
+
// given
|
|
84
|
+
const goals = [goal("G001"), goal("G002"), goal("G003"), goal("G004")];
|
|
85
|
+
const source = plan(goals);
|
|
86
|
+
|
|
87
|
+
// when
|
|
88
|
+
const snapshot = buildSteeringPlanSnapshot(source, new Set(["G003"]));
|
|
89
|
+
|
|
90
|
+
// then
|
|
91
|
+
expect(snapshot.goals.map((item) => item.id)).toEqual(["G003"]);
|
|
92
|
+
expect(snapshot.goals[0]).toEqual(goals[2]);
|
|
93
|
+
expect(snapshot.goalIds).toEqual(["G001", "G002", "G003", "G004"]);
|
|
94
|
+
expect(snapshot.goalCount).toBe(4);
|
|
95
|
+
expect(snapshot.updatedAt).toBe(NOW);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("omits the activeGoalId key entirely when the plan has none", () => {
|
|
99
|
+
// when
|
|
100
|
+
const snapshot = buildSteeringPlanSnapshot(plan([goal("G001")]), new Set(["G001"]));
|
|
101
|
+
|
|
102
|
+
// then
|
|
103
|
+
expect("activeGoalId" in snapshot).toBe(false);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("carries activeGoalId when the plan has one", () => {
|
|
107
|
+
// when
|
|
108
|
+
const snapshot = buildSteeringPlanSnapshot(plan([goal("G001")], { activeGoalId: "G001" }), new Set());
|
|
109
|
+
|
|
110
|
+
// then
|
|
111
|
+
expect(snapshot.activeGoalId).toBe("G001");
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("keeps plan order for changed goals regardless of set insertion order", () => {
|
|
115
|
+
// given
|
|
116
|
+
const source = plan([goal("G001"), goal("G002"), goal("G003")]);
|
|
117
|
+
|
|
118
|
+
// when
|
|
119
|
+
const snapshot = buildSteeringPlanSnapshot(source, new Set(["G003", "G001"]));
|
|
120
|
+
|
|
121
|
+
// then
|
|
122
|
+
expect(snapshot.goals.map((item) => item.id)).toEqual(["G001", "G003"]);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { mkdtemp, readFile } from "node:fs/promises";
|
|
1
|
+
import { appendFile, mkdtemp, readFile } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { describe, expect, it } from "vitest";
|
|
5
|
-
import { ulwLoopGoalsPath } from "../src/paths.js";
|
|
5
|
+
import { ulwLoopGoalsPath, ulwLoopLedgerPath } from "../src/paths.js";
|
|
6
6
|
import { readSteeringLedgerEntries, readUlwLoopPlan, writePlan } from "../src/plan-io.js";
|
|
7
7
|
import {
|
|
8
8
|
applySteeringMutation,
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "../src/steering.js";
|
|
13
13
|
import type {
|
|
14
14
|
UlwLoopItem,
|
|
15
|
+
UlwLoopLedgerEntry,
|
|
15
16
|
UlwLoopPlan,
|
|
16
17
|
UlwLoopSteeringProposal,
|
|
17
18
|
UlwLoopSuccessCriterion,
|
|
@@ -320,6 +321,104 @@ describe("steerUlwLoop", () => {
|
|
|
320
321
|
expect(second.deduped).toBe(true);
|
|
321
322
|
expect((await readUlwLoopPlan(repoRoot)).goals).toHaveLength(4);
|
|
322
323
|
});
|
|
324
|
+
|
|
325
|
+
describe("compact steering ledger entries", () => {
|
|
326
|
+
const DETAIL = "evidence detail ".repeat(200);
|
|
327
|
+
|
|
328
|
+
function fatGoal(id: string): UlwLoopItem {
|
|
329
|
+
return goal({
|
|
330
|
+
id,
|
|
331
|
+
title: `Fat goal ${id}`,
|
|
332
|
+
objective: `Objective ${id}: ${DETAIL}`,
|
|
333
|
+
evidence: DETAIL,
|
|
334
|
+
successCriteria: [
|
|
335
|
+
criterion({ id: "C001", scenario: DETAIL, expectedEvidence: DETAIL }),
|
|
336
|
+
criterion({ id: "C002", scenario: DETAIL, expectedEvidence: DETAIL }),
|
|
337
|
+
],
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function fatPlan(): UlwLoopPlan {
|
|
342
|
+
return plan({
|
|
343
|
+
goals: Array.from({ length: 20 }, (_, index) => fatGoal(`G${String(index + 1).padStart(3, "0")}`)),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
it("writes an O(changed goals) ledger entry instead of embedding the full plan", async () => {
|
|
348
|
+
// given
|
|
349
|
+
const seed = fatPlan();
|
|
350
|
+
const planBytes = JSON.stringify(seed).length;
|
|
351
|
+
const repoRoot = await repoWithPlan(seed);
|
|
352
|
+
|
|
353
|
+
// when
|
|
354
|
+
await steerUlwLoop(
|
|
355
|
+
repoRoot,
|
|
356
|
+
steering({ kind: "revise_pending_wording", targetGoalId: "G010", revisedTitle: "Sharper goal ten" }),
|
|
357
|
+
);
|
|
358
|
+
|
|
359
|
+
// then
|
|
360
|
+
const lines = (await readFile(ulwLoopLedgerPath(repoRoot), "utf8")).split("\n").filter(Boolean);
|
|
361
|
+
expect(lines).toHaveLength(1);
|
|
362
|
+
const line = lines[0] ?? "";
|
|
363
|
+
expect(line.length).toBeLessThan(planBytes / 4);
|
|
364
|
+
const entry: UlwLoopLedgerEntry = JSON.parse(line);
|
|
365
|
+
expect("before" in entry).toBe(false);
|
|
366
|
+
expect("after" in entry).toBe(false);
|
|
367
|
+
expect(entry.steering?.before?.goals.map((item) => item.id)).toEqual(["G010"]);
|
|
368
|
+
expect(entry.steering?.after?.goals.map((item) => item.id)).toEqual(["G010"]);
|
|
369
|
+
expect(entry.steering?.after?.goals[0]?.title).toBe("Sharper goal ten");
|
|
370
|
+
expect(entry.steering?.before?.goalCount).toBe(20);
|
|
371
|
+
expect(entry.steering?.before?.goalIds).toEqual(seed.goals.map((item) => item.id));
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it("dedup against a legacy full-plan entry strips before/after from the returned audit", async () => {
|
|
376
|
+
// given
|
|
377
|
+
const seed = plan();
|
|
378
|
+
const repoRoot = await repoWithPlan(seed);
|
|
379
|
+
const legacyLine = JSON.stringify({
|
|
380
|
+
at: NOW,
|
|
381
|
+
kind: "steering_accepted",
|
|
382
|
+
goalId: "G001",
|
|
383
|
+
idempotencyKey: "legacy-key",
|
|
384
|
+
evidence: "observable blocker evidence",
|
|
385
|
+
message: "the plan must change to stay safe",
|
|
386
|
+
mutationKind: "revise_pending_wording",
|
|
387
|
+
steering: {
|
|
388
|
+
kind: "revise_pending_wording",
|
|
389
|
+
source: "cli",
|
|
390
|
+
targetGoalIds: ["G001"],
|
|
391
|
+
evidence: "observable blocker evidence",
|
|
392
|
+
rationale: "the plan must change to stay safe",
|
|
393
|
+
idempotencyKey: "legacy-key",
|
|
394
|
+
invariant: {
|
|
395
|
+
accepted: true,
|
|
396
|
+
structuralInvariantAccepted: true,
|
|
397
|
+
evidenceBackedNecessity: true,
|
|
398
|
+
noEasierCompletion: true,
|
|
399
|
+
rejectedReasons: [],
|
|
400
|
+
},
|
|
401
|
+
before: seed,
|
|
402
|
+
after: seed,
|
|
403
|
+
},
|
|
404
|
+
});
|
|
405
|
+
await appendFile(ulwLoopLedgerPath(repoRoot), `${legacyLine}\n`, "utf8");
|
|
406
|
+
|
|
407
|
+
// when
|
|
408
|
+
const result = await steerUlwLoop(repoRoot, steering({ idempotencyKey: "legacy-key" }));
|
|
409
|
+
|
|
410
|
+
// then
|
|
411
|
+
expect(result.deduped).toBe(true);
|
|
412
|
+
expect(result.accepted).toBe(true);
|
|
413
|
+
expect("before" in result.audit).toBe(false);
|
|
414
|
+
expect("after" in result.audit).toBe(false);
|
|
415
|
+
expect(result.audit).toMatchObject({
|
|
416
|
+
kind: "revise_pending_wording",
|
|
417
|
+
idempotencyKey: "legacy-key",
|
|
418
|
+
deduped: true,
|
|
419
|
+
});
|
|
420
|
+
expect((await readUlwLoopPlan(repoRoot)).goals).toEqual(seed.goals);
|
|
421
|
+
});
|
|
323
422
|
});
|
|
324
423
|
|
|
325
424
|
describe("parseUlwLoopSteeringDirective", () => {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/git-bash/dist/cli.js\" hook post-compact",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO) Resetting Git Bash MCP Reminder",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Resetting Git Bash MCP Reminder",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\git-bash\\dist\\cli.js\" hook post-compact"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/lsp/dist/cli.js\" hook post-compact",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO) Resetting LSP Diagnostics Cache",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Resetting LSP Diagnostics Cache",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\lsp\\dist\\cli.js\" hook post-compact"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/rules/dist/cli.js\" hook post-compact",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO) Resetting Project Rule Cache",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Resetting Project Rule Cache",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\rules\\dist\\cli.js\" hook post-compact"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/codegraph/dist/cli.js\" hook post-tool-use",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO) Checking CodeGraph Init Guidance",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Checking CodeGraph Init Guidance",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\codegraph\\dist\\cli.js\" hook post-tool-use"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/comment-checker/dist/cli.js\" hook post-tool-use",
|
|
9
9
|
"timeout": 30,
|
|
10
|
-
"statusMessage": "(OmO) Checking Comments",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Checking Comments",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\comment-checker\\dist\\cli.js\" hook post-tool-use"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/lsp/dist/cli.js\" hook post-tool-use",
|
|
9
9
|
"timeout": 60,
|
|
10
|
-
"statusMessage": "(OmO) Checking LSP Diagnostics",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Checking LSP Diagnostics",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\lsp\\dist\\cli.js\" hook post-tool-use"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/components/teammode/dist/cli.js\" hook post-tool-use",
|
|
10
10
|
"timeout": 10,
|
|
11
|
-
"statusMessage": "(OmO) Checking Thread Title Hygiene",
|
|
11
|
+
"statusMessage": "(OmO 4.16.2) Checking Thread Title Hygiene",
|
|
12
12
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\teammode\\dist\\cli.js\" hook post-tool-use"
|
|
13
13
|
}
|
|
14
14
|
]
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/rules/dist/cli.js\" hook post-tool-use",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO) Matching Project Rules",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Matching Project Rules",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\rules\\dist\\cli.js\" hook post-tool-use"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/ulw-loop/dist/cli.js\" hook pre-tool-use",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO) Enforcing Unlimited Goal Budget",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Enforcing Unlimited Goal Budget",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\ulw-loop\\dist\\cli.js\" hook pre-tool-use"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/git-bash/dist/cli.js\" hook pre-tool-use",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO) Recommending Git Bash MCP",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Recommending Git Bash MCP",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\git-bash\\dist\\cli.js\" hook pre-tool-use"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/scripts/auto-update.mjs\" hook session-start",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO) Checking Auto Update",
|
|
10
|
+
"statusMessage": "(OmO 4.16.2) Checking Auto Update",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\scripts\\auto-update.mjs\" hook session-start"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
|
|
9
9
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
|
|
10
10
|
"timeout": 30,
|
|
11
|
-
"statusMessage": "(OmO) Checking Bootstrap Provisioning"
|
|
11
|
+
"statusMessage": "(OmO 4.16.2) Checking Bootstrap Provisioning"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|