litclaude-ai 0.3.30 → 0.3.31
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/CHANGELOG.md +9 -0
- package/README.md +5 -5
- package/README_ko-KR.md +5 -5
- package/RELEASE_CHECKLIST.md +19 -8
- package/package.json +1 -1
- package/plugins/litclaude/.claude-plugin/plugin.json +1 -1
- package/plugins/litclaude/bin/litclaude-hook.js +7 -1
- package/plugins/litclaude/bin/litclaude-mcp.js +1 -1
- package/plugins/litclaude/lib/litgoal/autoloop.mjs +71 -8
- package/plugins/litclaude/lib/litgoal/cli.mjs +14 -1
- package/plugins/litclaude/skills/visual-qa/SKILL.md +29 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.31 - 2026-07-22 — litgoal lifecycle and visual QA hardening
|
|
4
|
+
|
|
5
|
+
- Made duplicate litgoal creation byte-preserving, required explicit replacement
|
|
6
|
+
for a different active objective, and rejected completion with empty criteria.
|
|
7
|
+
- Made all-pass autoloops complete and disarm durably with idempotent completion
|
|
8
|
+
receipts, repairable ledger writes, and fail-open preservation of corrupt counters.
|
|
9
|
+
- Clarified visual QA backend ownership, authentication boundaries, bounded waits,
|
|
10
|
+
advisory metrics, blocked states, and observed cleanup receipts.
|
|
11
|
+
|
|
3
12
|
## 0.3.30 - 2026-07-19 — LitResearch scientific records and public-reader hardening
|
|
4
13
|
|
|
5
14
|
- Added root-owned append-only claim/evidence records, bounded expansion and
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
<p align="center">
|
|
11
11
|
<img src="https://img.shields.io/badge/npm-litclaude--ai-cb3837" />
|
|
12
|
-
<img src="https://img.shields.io/badge/version-0.3.
|
|
12
|
+
<img src="https://img.shields.io/badge/version-0.3.31-2ea44f" />
|
|
13
13
|
<img src="https://img.shields.io/badge/Claude%20Code-plugin-blueviolet" />
|
|
14
14
|
<img src="https://img.shields.io/badge/license-MIT-blue" />
|
|
15
15
|
</p>
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
> `litclaude@litclaude-ai`, so normal `claude` launches can load the
|
|
23
23
|
> LitClaude skills and hooks without a long `--plugin-dir` command.
|
|
24
24
|
|
|
25
|
-
This checkout is prepared as `litclaude-ai@0.3.
|
|
25
|
+
This checkout is prepared as `litclaude-ai@0.3.31` for personal install
|
|
26
26
|
convenience. The repo can remain quiet; preparing npm package metadata here does
|
|
27
27
|
not imply public repo promotion, marketplace publication, or advertisement.
|
|
28
|
-
Future package releases still require explicit user approval. The v0.3.30 release material strengthens LitResearch with root-owned scientific evidence records, DOI/PDF lifecycle receipts, bounded route coverage, and a connection-pinned public-source reader with inert-content and secret-redaction guarantees. The v0.3.29 release material bundles exact-source `lit-handoff` and `lit-scientific-visualization` skills with Claude-native commands, exact-bare hook invocation, visible LITBURN banners, installed-payload integrity checks, and read-only scientific dependency diagnostics. The v0.3.28 release material requires explicit leading start-work invocations so diagnostic or copied mentions remain inert. The v0.3.27 release material adds a structured, animated five-stage installer with a success or failure receipt while preserving deterministic automation output. The v0.3.26 release material adds adaptive objective-achievable planning, draft-plan review, and orchestration readiness hardening. The v0.3.25 release material aligns portable details, public-read, litgoal status JSON, and evidence wording. The v0.3.24 release material aligns auxiliary skill inventories and advisory probes. The v0.3.23
|
|
28
|
+
Future package releases still require explicit user approval. The v0.3.31 release material hardens litgoal creation, replacement, completion, and autoloop receipts while making visual QA browser ownership, bounded waits, blocked states, and cleanup evidence explicit. The v0.3.30 release material strengthens LitResearch with root-owned scientific evidence records, DOI/PDF lifecycle receipts, bounded route coverage, and a connection-pinned public-source reader with inert-content and secret-redaction guarantees. The v0.3.29 release material bundles exact-source `lit-handoff` and `lit-scientific-visualization` skills with Claude-native commands, exact-bare hook invocation, visible LITBURN banners, installed-payload integrity checks, and read-only scientific dependency diagnostics. The v0.3.28 release material requires explicit leading start-work invocations so diagnostic or copied mentions remain inert. The v0.3.27 release material adds a structured, animated five-stage installer with a success or failure receipt while preserving deterministic automation output. The v0.3.26 release material adds adaptive objective-achievable planning, draft-plan review, and orchestration readiness hardening. The v0.3.25 release material aligns portable details, public-read, litgoal status JSON, and evidence wording. The v0.3.24 release material aligns auxiliary skill inventories and advisory probes. The v0.3.23
|
|
29
29
|
release materials inject the bundled skill bodies for bare `hyperplan`,
|
|
30
30
|
`litresearch`, `lit research`, `init-deep`, and explicit `$start-work` prompt-hook routes while
|
|
31
31
|
preserving the v0.3.19 adversarial planning skill, the v0.3.18 read-only `lit-recap` session recap surface, the v0.3.17 separate-worker native `/goal` launcher, the v0.3.16
|
|
@@ -131,7 +131,7 @@ directory, the normal install command works:
|
|
|
131
131
|
|
|
132
132
|
```bash
|
|
133
133
|
cd /tmp
|
|
134
|
-
npx --yes litclaude-ai@0.3.
|
|
134
|
+
npx --yes litclaude-ai@0.3.31 install
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
Validate the installed plugin:
|
|
@@ -144,7 +144,7 @@ The installer also sets Claude Code's `statusLine` command to the packaged
|
|
|
144
144
|
LitClaude HUD. A typical no-color render starts like:
|
|
145
145
|
|
|
146
146
|
```text
|
|
147
|
-
[🔥LITCLAUDE v0.3.
|
|
147
|
+
[🔥LITCLAUDE v0.3.31] | O4.8 │ ctx [▎░░] 9%/1000k │ 5h [▏░] 4% ↻2h15m │ 1w [▊░] 35% ↻3d6h │ git main +3 ✓
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
The `↻` suffix is a compact rate-limit reset countdown. It is separated from
|
package/README_ko-KR.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
<p align="center">
|
|
11
11
|
<img src="https://img.shields.io/badge/npm-litclaude--ai-cb3837" />
|
|
12
|
-
<img src="https://img.shields.io/badge/version-0.3.
|
|
12
|
+
<img src="https://img.shields.io/badge/version-0.3.31-2ea44f" />
|
|
13
13
|
<img src="https://img.shields.io/badge/Claude%20Code-plugin-blueviolet" />
|
|
14
14
|
<img src="https://img.shields.io/badge/license-MIT-blue" />
|
|
15
15
|
</p>
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
> 설치되므로, 매번 긴 `--plugin-dir` 없이 일반 `claude` 실행에서
|
|
27
27
|
> LitClaude skill과 hook을 불러올 수 있습니다.
|
|
28
28
|
|
|
29
|
-
현재 checkout은 `litclaude-ai@0.3.
|
|
29
|
+
현재 checkout은 `litclaude-ai@0.3.31` 배포 준비용으로 정리되어 있습니다. 목적은
|
|
30
30
|
다른 PC에서도 빠르게 설치하기 위한 개인용 package metadata를 갖추는 것입니다.
|
|
31
31
|
npm package metadata를 준비했다고 해서 홍보, 공개 저장소 운영, Claude
|
|
32
32
|
marketplace 등록을 의미하지는 않습니다. 새 버전 배포는 항상 별도의 명시적
|
|
33
|
-
승인 후에 진행합니다. v0.3.30 release material은 root-owned scientific evidence record, DOI/PDF lifecycle receipt, bounded route coverage, connection-pinned public-source reader, inert-content 및 secret-redaction 보장을 포함하는 LitResearch 강화판입니다. v0.3.29 release material은 exact-source `lit-handoff`와 `lit-scientific-visualization` skill, Claude-native command, exact-bare hook invocation, visible LITBURN banner, installed-payload integrity check, read-only scientific dependency diagnostic을 함께 포함합니다. v0.3.28 release material은 start-work 호출을 prompt 선두의 명시적 invocation으로 제한해 진단문이나 복사된 언급을 비활성 상태로 유지합니다. v0.3.27 release material은 success/failure receipt와 deterministic automation output을 갖춘 5-stage animated installer를 추가합니다. v0.3.26 release material은 adaptive objective-achievable planning, draft-plan review, orchestration readiness hardening을 추가합니다. v0.3.25 release material은 portable details, public-read, litgoal status JSON, evidence wording을 정렬합니다. v0.3.24 release material은 auxiliary skill inventory와 advisory probe를 정렬합니다. v0.3.23 release material은 bare `hyperplan`,
|
|
33
|
+
승인 후에 진행합니다. v0.3.31 release material은 litgoal 생성·교체·완료와 autoloop receipt를 강화하고 visual QA의 browser ownership, bounded wait, blocked state, cleanup evidence를 명확히 합니다. v0.3.30 release material은 root-owned scientific evidence record, DOI/PDF lifecycle receipt, bounded route coverage, connection-pinned public-source reader, inert-content 및 secret-redaction 보장을 포함하는 LitResearch 강화판입니다. v0.3.29 release material은 exact-source `lit-handoff`와 `lit-scientific-visualization` skill, Claude-native command, exact-bare hook invocation, visible LITBURN banner, installed-payload integrity check, read-only scientific dependency diagnostic을 함께 포함합니다. v0.3.28 release material은 start-work 호출을 prompt 선두의 명시적 invocation으로 제한해 진단문이나 복사된 언급을 비활성 상태로 유지합니다. v0.3.27 release material은 success/failure receipt와 deterministic automation output을 갖춘 5-stage animated installer를 추가합니다. v0.3.26 release material은 adaptive objective-achievable planning, draft-plan review, orchestration readiness hardening을 추가합니다. v0.3.25 release material은 portable details, public-read, litgoal status JSON, evidence wording을 정렬합니다. v0.3.24 release material은 auxiliary skill inventory와 advisory probe를 정렬합니다. v0.3.23 release material은 bare `hyperplan`,
|
|
34
34
|
`litresearch`, `lit research`, `init-deep`, explicit `$start-work` prompt-hook route에
|
|
35
35
|
bundled skill body를 주입하면서, v0.3.19 adversarial planning
|
|
36
36
|
skill, v0.3.18 read-only `lit-recap` session recap surface, v0.3.17 별도 worker 기반 native `/goal`
|
|
@@ -131,7 +131,7 @@ checkout을 먼저 해석해서 `sh: litclaude-ai: command not found`로 실패
|
|
|
131
131
|
|
|
132
132
|
```bash
|
|
133
133
|
cd /tmp
|
|
134
|
-
npx --yes litclaude-ai@0.3.
|
|
134
|
+
npx --yes litclaude-ai@0.3.31 install
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
설치 상태를 확인합니다.
|
|
@@ -144,7 +144,7 @@ installer는 Claude Code의 `statusLine` command도 packaged LitClaude HUD로
|
|
|
144
144
|
설정합니다. 색상을 제거한 예시는 다음처럼 시작합니다.
|
|
145
145
|
|
|
146
146
|
```text
|
|
147
|
-
[🔥LITCLAUDE v0.3.
|
|
147
|
+
[🔥LITCLAUDE v0.3.31] | O4.8 │ ctx [▎░░] 9%/1000k │ 5h [▏░] 4% ↻2h15m │ 1w [▊░] 35% ↻3d6h │ git main +3 ✓
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
`↻` 표시는 rate-limit reset까지 남은 시간을 짧게 보여주는 countdown입니다.
|
package/RELEASE_CHECKLIST.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# LitClaude Release Checklist
|
|
2
2
|
|
|
3
|
-
Status: `litclaude-ai@0.3.
|
|
4
|
-
|
|
3
|
+
Status: `litclaude-ai@0.3.31` is the current release candidate — guarded litgoal
|
|
4
|
+
creation and replacement, durable idempotent autoloop completion, and explicit
|
|
5
|
+
visual QA backend ownership, bounded waits, blocked states, and cleanup receipts,
|
|
6
|
+
plus root-owned scientific evidence records, DOI/PDF lifecycle receipts, bounded route coverage,
|
|
5
7
|
connection-pinned public-source reads, inert-content receipts, and deep secret
|
|
6
8
|
redaction, plus bundled
|
|
7
9
|
exact-source `lit-handoff` and `lit-scientific-visualization` skills with
|
|
@@ -23,9 +25,9 @@ side-effect-free, the launcher starts only a separate Claude Code
|
|
|
23
25
|
print/background worker, and the release preserves the Korean polishing
|
|
24
26
|
command, strict multi-agent review pipeline, fidelity guardrails, package
|
|
25
27
|
hygiene checks, native route gates, and safe start-work handoff behavior.
|
|
26
|
-
`package.json` is aligned to `0.3.
|
|
27
|
-
`plugins/litclaude/.claude-plugin/plugin.json` is aligned to `0.3.
|
|
28
|
-
plugin-local MCP server reports `0.3.
|
|
28
|
+
`package.json` is aligned to `0.3.31`,
|
|
29
|
+
`plugins/litclaude/.claude-plugin/plugin.json` is aligned to `0.3.31`, and the
|
|
30
|
+
plugin-local MCP server reports `0.3.31`.
|
|
29
31
|
|
|
30
32
|
This release carries the v0.2.2 Dynamic workflow hardening surfaces:
|
|
31
33
|
`/dynamic-workflow`, `workflow-check --json`, native `/goal` fallback guidance,
|
|
@@ -69,6 +71,15 @@ Use this track when testing from the current checkout:
|
|
|
69
71
|
|
|
70
72
|
No npm publication is required for this track.
|
|
71
73
|
|
|
74
|
+
## v0.3.31 Litgoal Lifecycle and Visual QA Gates
|
|
75
|
+
|
|
76
|
+
Before requesting publication approval, confirm duplicate objectives remain
|
|
77
|
+
byte-preserving, different active objectives require explicit replacement, and
|
|
78
|
+
empty criteria cannot complete. Confirm all-pass autoloops complete and disarm
|
|
79
|
+
once with repairable ledger receipts, corrupt counters remain untouched on the
|
|
80
|
+
fail-open path, and visual QA uses only an owned project Playwright setup or an
|
|
81
|
+
explicit current-session Chrome binding with bounded waits and observed cleanup.
|
|
82
|
+
|
|
72
83
|
## v0.3.30 LitResearch and Public Reader Gates
|
|
73
84
|
|
|
74
85
|
Before requesting publication approval, confirm the installed LitResearch body
|
|
@@ -111,9 +122,9 @@ checkout and from an isolated install of the packed tarball:
|
|
|
111
122
|
Before requesting publication approval, confirm these artifacts from the current
|
|
112
123
|
checkout:
|
|
113
124
|
|
|
114
|
-
- `package.json` version is `0.3.
|
|
115
|
-
- `plugins/litclaude/.claude-plugin/plugin.json` version is `0.3.
|
|
116
|
-
- `plugins/litclaude/bin/litclaude-mcp.js` reports server version `0.3.
|
|
125
|
+
- `package.json` version is `0.3.31`.
|
|
126
|
+
- `plugins/litclaude/.claude-plugin/plugin.json` version is `0.3.31`.
|
|
127
|
+
- `plugins/litclaude/bin/litclaude-mcp.js` reports server version `0.3.31`.
|
|
117
128
|
- Prompt-hook tests cover bundled `SKILL.md` body injection for bare `hyperplan`, `litresearch`, `lit research`, `init-deep`, and explicit leading `$start-work`; diagnostic/copy mentions stay inert while leading natural-language `lit start work` stays BLOCKED.
|
|
118
129
|
- `lit search` and `lit query` route to `/litclaude:litresearch` without activating on slash mentions, code spans, or non-lit prompts.
|
|
119
130
|
- Litresearch web lanes require public API/feed preference, validator-first checks, route traces, prompt-injection quarantine, and honest auth/paywall/private-data stop reasons.
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ import { transcriptHasContextPressure } from "../lib/context-pressure.mjs";
|
|
|
6
6
|
import { extractMutatedFilePaths } from "../lib/mutated-file-paths.mjs";
|
|
7
7
|
import { litgoalGoalsPath } from "../lib/litgoal/paths.mjs";
|
|
8
8
|
import { readLitgoalState } from "../lib/litgoal/state.mjs";
|
|
9
|
-
import { evaluateAutoloop, readAutoloopState, writeAutoloopState } from "../lib/litgoal/autoloop.mjs";
|
|
9
|
+
import { completeAutoloopGoal, evaluateAutoloop, readAutoloopState, writeAutoloopState } from "../lib/litgoal/autoloop.mjs";
|
|
10
10
|
import { buildNativeGoalBindingGuidance, normalizeGoalObjective } from "../lib/native-goal-binding.mjs";
|
|
11
11
|
|
|
12
12
|
const eventName = process.argv[2] ?? "";
|
|
@@ -408,6 +408,12 @@ switch (eventName) {
|
|
|
408
408
|
console.log(JSON.stringify({ decision: "block", reason: decision.reason }));
|
|
409
409
|
} else if (decision.action === "cap") {
|
|
410
410
|
console.log(JSON.stringify({ continue: false, stopReason: decision.stopReason }));
|
|
411
|
+
} else if (
|
|
412
|
+
decision.why !== "kill-switch"
|
|
413
|
+
&& (decision.why === "all-criteria-pass"
|
|
414
|
+
|| state?.checkpoints?.some(({ generatedBy }) => generatedBy === "stop-hook-autoloop"))
|
|
415
|
+
) {
|
|
416
|
+
completeAutoloopGoal(cwd);
|
|
411
417
|
}
|
|
412
418
|
// action === "allow" (or counter write failed below): emit nothing -> stop is allowed.
|
|
413
419
|
} catch {
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
// stopping only while it can durably increment this counter under the cap. If the
|
|
4
4
|
// counter cannot be read or written, the hook fails SAFE (allows stopping) rather
|
|
5
5
|
// than risk a runaway loop. State lives at `.litclaude/litgoal/autoloop.json`.
|
|
6
|
-
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
-
import {
|
|
8
|
+
import { appendLitgoalLedger } from "./ledger.mjs";
|
|
9
|
+
import { litgoalGoalsPath, litgoalLedgerPath, litgoalLockDir, litgoalStateDir } from "./paths.mjs";
|
|
10
|
+
import { readLitgoalState, withLitgoalLock, writeLitgoalState } from "./state.mjs";
|
|
9
11
|
|
|
10
12
|
export const litgoalAutoloopPath = (cwd = process.cwd()) => join(litgoalStateDir(cwd), "autoloop.json");
|
|
11
13
|
|
|
@@ -14,12 +16,25 @@ export const AUTOLOOP_MAX_BLOCKS = 8;
|
|
|
14
16
|
export const AUTOLOOP_MAX_MS = 30 * 60 * 1000;
|
|
15
17
|
|
|
16
18
|
export const readAutoloopState = (cwd = process.cwd()) => {
|
|
19
|
+
const path = litgoalAutoloopPath(cwd);
|
|
20
|
+
if (!existsSync(path)) return null;
|
|
21
|
+
let parsed;
|
|
17
22
|
try {
|
|
18
|
-
|
|
19
|
-
return parsed && typeof parsed === "object" ? parsed : null;
|
|
23
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
20
24
|
} catch {
|
|
21
|
-
|
|
25
|
+
throw new Error("corrupt autoloop state");
|
|
22
26
|
}
|
|
27
|
+
if (
|
|
28
|
+
!parsed
|
|
29
|
+
|| typeof parsed !== "object"
|
|
30
|
+
|| !Number.isInteger(parsed.blockCount)
|
|
31
|
+
|| parsed.blockCount < 0
|
|
32
|
+
|| !Number.isFinite(parsed.firstBlockAt)
|
|
33
|
+
|| parsed.firstBlockAt < 0
|
|
34
|
+
) {
|
|
35
|
+
throw new Error("invalid autoloop state");
|
|
36
|
+
}
|
|
37
|
+
return parsed;
|
|
23
38
|
};
|
|
24
39
|
|
|
25
40
|
export const writeAutoloopState = (cwd, state) => {
|
|
@@ -36,6 +51,50 @@ export const writeAutoloopState = (cwd, state) => {
|
|
|
36
51
|
export const resetAutoloopState = (cwd, now = Date.now()) =>
|
|
37
52
|
writeAutoloopState(cwd, { blockCount: 0, firstBlockAt: now });
|
|
38
53
|
|
|
54
|
+
export const completeAutoloopGoal = (cwd = process.cwd()) =>
|
|
55
|
+
withLitgoalLock(litgoalLockDir(cwd), () => {
|
|
56
|
+
const state = readLitgoalState(litgoalGoalsPath(cwd), null);
|
|
57
|
+
if (!state) return { completed: false };
|
|
58
|
+
|
|
59
|
+
let checkpoint = state.checkpoints?.find(({ generatedBy }) => generatedBy === "stop-hook-autoloop");
|
|
60
|
+
const criteria = Array.isArray(state.criteria) ? state.criteria : [];
|
|
61
|
+
const canComplete = state.status === "active"
|
|
62
|
+
&& state.autoloop === true
|
|
63
|
+
&& criteria.length > 0
|
|
64
|
+
&& criteria.every((criterion) => criterion?.status === "pass");
|
|
65
|
+
if (!checkpoint && !canComplete) return { completed: false };
|
|
66
|
+
|
|
67
|
+
if (!checkpoint) {
|
|
68
|
+
const createdAt = new Date().toISOString();
|
|
69
|
+
checkpoint = {
|
|
70
|
+
status: "complete",
|
|
71
|
+
note: "Autoloop completed after all success criteria passed.",
|
|
72
|
+
createdAt,
|
|
73
|
+
generatedBy: "stop-hook-autoloop",
|
|
74
|
+
completionId: `stop-hook-autoloop:${state.createdAt ?? createdAt}`,
|
|
75
|
+
};
|
|
76
|
+
state.status = "complete";
|
|
77
|
+
state.autoloop = false;
|
|
78
|
+
state.checkpoints = [...(state.checkpoints ?? []), checkpoint];
|
|
79
|
+
state.updatedAt = createdAt;
|
|
80
|
+
writeLitgoalState(litgoalGoalsPath(cwd), state);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const ledgerPath = litgoalLedgerPath(cwd);
|
|
84
|
+
const entries = existsSync(ledgerPath)
|
|
85
|
+
? readFileSync(ledgerPath, "utf8").trim().split("\n").filter(Boolean).map((line) => JSON.parse(line))
|
|
86
|
+
: [];
|
|
87
|
+
if (!entries.some((entry) => entry.event === "goal.completed" && entry.completionId === checkpoint.completionId)) {
|
|
88
|
+
appendLitgoalLedger(ledgerPath, {
|
|
89
|
+
event: "goal.completed",
|
|
90
|
+
status: "complete",
|
|
91
|
+
generatedBy: checkpoint.generatedBy,
|
|
92
|
+
completionId: checkpoint.completionId,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return { completed: true, checkpoint };
|
|
96
|
+
});
|
|
97
|
+
|
|
39
98
|
// Pure decision function for the Stop hook — kept side-effect-free so it is unit
|
|
40
99
|
// testable without touching the filesystem or the process. Returns one of:
|
|
41
100
|
// { action: "allow" } -> let the session stop
|
|
@@ -47,8 +106,10 @@ export const evaluateAutoloop = ({ env = {}, state, autoloopState, now = Date.no
|
|
|
47
106
|
return { action: "allow", why: "no-active-autoloop-goal" };
|
|
48
107
|
}
|
|
49
108
|
const criteria = Array.isArray(state.criteria) ? state.criteria : [];
|
|
50
|
-
const remaining = criteria.
|
|
51
|
-
|
|
109
|
+
const remaining = criteria.length === 0
|
|
110
|
+
? [{ id: "criteria-required", status: "missing", description: "no success criteria are defined" }]
|
|
111
|
+
: criteria.filter((c) => !c || c.status !== "pass");
|
|
112
|
+
if (criteria.length > 0 && remaining.length === 0) return { action: "allow", why: "all-criteria-pass" };
|
|
52
113
|
|
|
53
114
|
const auto = autoloopState && typeof autoloopState === "object"
|
|
54
115
|
? autoloopState
|
|
@@ -68,7 +129,9 @@ export const evaluateAutoloop = ({ env = {}, state, autoloopState, now = Date.no
|
|
|
68
129
|
|
|
69
130
|
const nextCount = blockCount + 1;
|
|
70
131
|
const list = remaining
|
|
71
|
-
.map((c) =>
|
|
132
|
+
.map((c) => c
|
|
133
|
+
? ` - ${c.id} [${c.status}]: ${c.description ?? c.scenario ?? ""}`
|
|
134
|
+
: " - criterion-invalid [missing]: invalid criterion")
|
|
72
135
|
.join("\n");
|
|
73
136
|
const reason =
|
|
74
137
|
`LitClaude litgoal still active: "${state.objective}". ${remaining.length} criterion(s) not yet pass:\n${list}\n` +
|
|
@@ -12,7 +12,7 @@ import { resetAutoloopState } from "./autoloop.mjs";
|
|
|
12
12
|
import { NativeWorkerError, runNativeWorker } from "./native-worker.mjs";
|
|
13
13
|
|
|
14
14
|
const subcommands = [
|
|
15
|
-
["create-goals", "Create durable goal records
|
|
15
|
+
["create-goals", "Create durable goal records; use --replace for a fresh cycle."],
|
|
16
16
|
["status", "Print the current litgoal status."],
|
|
17
17
|
["criteria", "List or update success criteria."],
|
|
18
18
|
["record-evidence", "Record evidence as JSON."],
|
|
@@ -121,7 +121,16 @@ const createGoals = (cwd, args) => {
|
|
|
121
121
|
// Opt-in: `--autoloop` arms the LitClaude Stop hook to keep the session running
|
|
122
122
|
// (a /goal-equivalent loop) until every criterion passes. Default off.
|
|
123
123
|
const autoloop = hasFlag(args, "--autoloop");
|
|
124
|
+
const replace = hasFlag(args, "--replace");
|
|
124
125
|
return withLitgoalLock(litgoalLockDir(cwd), () => {
|
|
126
|
+
const existing = readState(cwd);
|
|
127
|
+
if (existing?.objective === brief && !replace) {
|
|
128
|
+
return { ...existing, message: "The same objective already exists; no changes made." };
|
|
129
|
+
}
|
|
130
|
+
if (existing?.status === "active" && existing.objective !== brief && !replace) {
|
|
131
|
+
throw new LitgoalStateError("different active objective exists; use --replace to start a fresh cycle");
|
|
132
|
+
}
|
|
133
|
+
|
|
125
134
|
const timestamp = nowIso();
|
|
126
135
|
const state = {
|
|
127
136
|
version: 1,
|
|
@@ -146,6 +155,7 @@ const createGoals = (cwd, args) => {
|
|
|
146
155
|
objective: brief,
|
|
147
156
|
status: state.status,
|
|
148
157
|
autoloop,
|
|
158
|
+
replaced: Boolean(existing && replace),
|
|
149
159
|
criteria: state.criteria.map(({ id, status }) => ({ id, status })),
|
|
150
160
|
});
|
|
151
161
|
return state;
|
|
@@ -196,6 +206,9 @@ const checkpoint = (cwd, args) =>
|
|
|
196
206
|
throw new LitgoalCliError("invalid checkpoint status");
|
|
197
207
|
}
|
|
198
208
|
const criteria = state.criteria ?? [];
|
|
209
|
+
if (status === "complete" && criteria.length === 0) {
|
|
210
|
+
throw new LitgoalStateError("non-empty criteria must pass before completion");
|
|
211
|
+
}
|
|
199
212
|
if (status === "complete" && !criteria.every((criterion) => criterion.status === "pass")) {
|
|
200
213
|
throw new LitgoalStateError("criteria must pass before completion");
|
|
201
214
|
}
|
|
@@ -137,11 +137,38 @@ discard it and regenerate before using it as evidence.
|
|
|
137
137
|
|
|
138
138
|
### Web
|
|
139
139
|
|
|
140
|
+
#### Browser backend order and ownership
|
|
141
|
+
|
|
142
|
+
Use the project's Playwright setup first: an existing dependency, test config,
|
|
143
|
+
fixtures, browser binary, and command already owned by the project. Do not install
|
|
144
|
+
Playwright, download browsers, or add a replacement runner during QA. If project
|
|
145
|
+
Playwright is absent or cannot cover the required surface, the only fallback is an
|
|
146
|
+
explicitly user-enabled Claude Chrome capability. The capability must be callable in
|
|
147
|
+
the current session through an observed tool or binding; never infer it from
|
|
148
|
+
documentation, a binary on `PATH`, a browser window, or a past session.
|
|
149
|
+
|
|
150
|
+
Reuse only a current session binding or a healthy server with verified PID, port, and
|
|
151
|
+
command ownership before connection. Do not adopt an unknown process or create a
|
|
152
|
+
cross-repo daemon. There is no cookie or profile sharing, automatic authenticated
|
|
153
|
+
persistence, dependency install, or host config mutation. No dependency install or
|
|
154
|
+
host config mutation is allowed. Do not copy browser profile directories, cookies,
|
|
155
|
+
local storage, tokens, or credentials between backends. If an authenticated state is
|
|
156
|
+
required but no user-approved current-session binding provides it, stop rather than
|
|
157
|
+
weakening this boundary.
|
|
158
|
+
|
|
159
|
+
Diff ratios, similarity scores, timings, and coverage counts are evidence metrics.
|
|
160
|
+
These metrics are advisory unless hardened by a checked-in threshold and a
|
|
161
|
+
deterministic project test. They direct review but cannot independently produce PASS.
|
|
162
|
+
Bound navigation, capture, and server-health waits with explicit timeouts. On
|
|
163
|
+
unavailable capability, ownership ambiguity, or timeout, report `BLOCKED:` with the
|
|
164
|
+
attempted backend and reason, then include a cleanup receipt listing stopped processes,
|
|
165
|
+
closed session bindings, removed temporary captures, and any intentionally retained
|
|
166
|
+
evidence. Never report cleanup that was not observed.
|
|
167
|
+
|
|
140
168
|
1. Capture a REFERENCE image: the user's mock/target, or a known-good baseline.
|
|
141
169
|
Save as PNG.
|
|
142
170
|
2. Capture the ACTUAL rendered screenshot at the same viewport size using the
|
|
143
|
-
|
|
144
|
-
PNG.
|
|
171
|
+
selected backend above. Save as PNG.
|
|
145
172
|
3. Run the diff and keep the JSON:
|
|
146
173
|
|
|
147
174
|
```
|