cclaw-cli 0.5.3 → 0.5.5
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/README.md +8 -11
- package/dist/artifact-linter.js +41 -13
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +12 -1
- package/dist/config.js +0 -19
- package/dist/content/contracts.js +7 -12
- package/dist/content/examples.js +42 -26
- package/dist/content/hooks.d.ts +4 -6
- package/dist/content/hooks.js +105 -435
- package/dist/content/learnings.js +55 -203
- package/dist/content/meta-skill.js +8 -11
- package/dist/content/next-command.js +3 -3
- package/dist/content/observe.d.ts +4 -7
- package/dist/content/observe.js +81 -55
- package/dist/content/session-hooks.js +8 -8
- package/dist/content/skills.js +9 -16
- package/dist/content/stage-schema.js +80 -97
- package/dist/content/templates.d.ts +1 -1
- package/dist/content/templates.js +27 -48
- package/dist/delegation.js +7 -7
- package/dist/doctor.js +17 -34
- package/dist/flow-state.js +1 -1
- package/dist/harness-adapters.js +1 -1
- package/dist/install.js +23 -49
- package/dist/policy.js +1 -4
- package/dist/runs.d.ts +13 -9
- package/dist/runs.js +108 -317
- package/dist/trace-matrix.js +8 -18
- package/dist/types.d.ts +0 -4
- package/package.json +1 -1
- package/dist/learnings-summarizer.d.ts +0 -25
- package/dist/learnings-summarizer.js +0 -201
package/dist/trace-matrix.js
CHANGED
|
@@ -2,22 +2,13 @@ import fs from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { RUNTIME_ROOT } from "./constants.js";
|
|
4
4
|
import { exists } from "./fs-utils.js";
|
|
5
|
-
import { readFlowState } from "./runs.js";
|
|
6
5
|
function activeArtifactPath(projectRoot, name) {
|
|
7
6
|
return path.join(projectRoot, RUNTIME_ROOT, "artifacts", name);
|
|
8
7
|
}
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const runId = activeRunId.trim();
|
|
14
|
-
const candidates = runId.length > 0
|
|
15
|
-
? [canonicalRunArtifactPath(projectRoot, runId, name), activeArtifactPath(projectRoot, name)]
|
|
16
|
-
: [activeArtifactPath(projectRoot, name)];
|
|
17
|
-
for (const candidate of candidates) {
|
|
18
|
-
if (await exists(candidate)) {
|
|
19
|
-
return fs.readFile(candidate, "utf8");
|
|
20
|
-
}
|
|
8
|
+
async function readArtifact(projectRoot, name) {
|
|
9
|
+
const candidate = activeArtifactPath(projectRoot, name);
|
|
10
|
+
if (await exists(candidate)) {
|
|
11
|
+
return fs.readFile(candidate, "utf8");
|
|
21
12
|
}
|
|
22
13
|
return null;
|
|
23
14
|
}
|
|
@@ -120,11 +111,10 @@ function layer1LinesForCriterion(layer1, criterionId) {
|
|
|
120
111
|
return out;
|
|
121
112
|
}
|
|
122
113
|
export async function buildTraceMatrix(projectRoot) {
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
const review = await readArtifact(projectRoot, "07-review.md", activeRunId);
|
|
114
|
+
const spec = await readArtifact(projectRoot, "04-spec.md");
|
|
115
|
+
const plan = await readArtifact(projectRoot, "05-plan.md");
|
|
116
|
+
const tdd = await readArtifact(projectRoot, "06-tdd.md");
|
|
117
|
+
const review = await readArtifact(projectRoot, "07-review.md");
|
|
128
118
|
const criterionIds = spec ? parseAcceptanceCriterionIds(spec) : [];
|
|
129
119
|
const taskToAcs = plan ? parsePlanTaskAcLinks(plan) : new Map();
|
|
130
120
|
const allTaskIds = plan ? parsePlanTaskIds(plan) : [];
|
package/dist/types.d.ts
CHANGED
|
@@ -8,10 +8,6 @@ export interface VibyConfig {
|
|
|
8
8
|
harnesses: HarnessId[];
|
|
9
9
|
/** When true, stage skills instruct the agent to continue to the following stage after gates pass. */
|
|
10
10
|
autoAdvance?: boolean;
|
|
11
|
-
/** Merge project bootstrap learnings with a global learnings file. */
|
|
12
|
-
globalLearnings?: boolean;
|
|
13
|
-
/** Optional absolute or project-relative path to global learnings JSONL. */
|
|
14
|
-
globalLearningsPath?: string;
|
|
15
11
|
/** Prompt guard behavior for runtime write-risk detection hooks. */
|
|
16
12
|
promptGuardMode?: "advisory" | "strict";
|
|
17
13
|
/** When true, cclaw installs managed git pre-commit/pre-push wrappers. */
|
package/package.json
CHANGED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export interface ObservationRecord {
|
|
2
|
-
ts?: string;
|
|
3
|
-
event?: string;
|
|
4
|
-
tool?: string;
|
|
5
|
-
phase?: string;
|
|
6
|
-
stage?: string;
|
|
7
|
-
runId?: string;
|
|
8
|
-
data?: unknown;
|
|
9
|
-
}
|
|
10
|
-
export type LearningSource = "observed" | "user-stated" | "inferred";
|
|
11
|
-
export type LearningType = "pitfall" | "pattern" | "preference";
|
|
12
|
-
export interface LearningRecord {
|
|
13
|
-
ts: string;
|
|
14
|
-
skill: string;
|
|
15
|
-
type: LearningType;
|
|
16
|
-
key: string;
|
|
17
|
-
insight: string;
|
|
18
|
-
confidence: number;
|
|
19
|
-
source: LearningSource;
|
|
20
|
-
}
|
|
21
|
-
export interface SummarizeOutcome {
|
|
22
|
-
candidates: LearningRecord[];
|
|
23
|
-
appendable: LearningRecord[];
|
|
24
|
-
}
|
|
25
|
-
export declare function summarizeObservationLearnings(observationJsonl: string, existingLearningsJsonl: string, timestamp: string): SummarizeOutcome;
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
const ERROR_PATTERN = /(error|fail|timeout|exception)/iu;
|
|
2
|
-
const KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/u;
|
|
3
|
-
function parseJsonLine(line) {
|
|
4
|
-
const trimmed = line.trim();
|
|
5
|
-
if (!trimmed)
|
|
6
|
-
return null;
|
|
7
|
-
try {
|
|
8
|
-
const parsed = JSON.parse(trimmed);
|
|
9
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
10
|
-
return null;
|
|
11
|
-
return parsed;
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
function toText(value) {
|
|
18
|
-
if (typeof value === "string")
|
|
19
|
-
return value;
|
|
20
|
-
try {
|
|
21
|
-
return JSON.stringify(value);
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function asValidLearning(value) {
|
|
28
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
29
|
-
return null;
|
|
30
|
-
const obj = value;
|
|
31
|
-
const ts = obj.ts;
|
|
32
|
-
const skill = obj.skill;
|
|
33
|
-
const type = obj.type;
|
|
34
|
-
const key = obj.key;
|
|
35
|
-
const insight = obj.insight;
|
|
36
|
-
const confidence = obj.confidence;
|
|
37
|
-
const source = obj.source;
|
|
38
|
-
if (typeof ts !== "string" || !ts)
|
|
39
|
-
return null;
|
|
40
|
-
if (typeof skill !== "string" || !skill)
|
|
41
|
-
return null;
|
|
42
|
-
if (type !== "pitfall" && type !== "pattern" && type !== "preference")
|
|
43
|
-
return null;
|
|
44
|
-
if (typeof key !== "string" || !KEY_PATTERN.test(key))
|
|
45
|
-
return null;
|
|
46
|
-
if (typeof insight !== "string" || insight.trim().length < 16)
|
|
47
|
-
return null;
|
|
48
|
-
if (typeof confidence !== "number" || !Number.isInteger(confidence) || confidence < 1 || confidence > 10)
|
|
49
|
-
return null;
|
|
50
|
-
if (source !== "observed" && source !== "user-stated" && source !== "inferred")
|
|
51
|
-
return null;
|
|
52
|
-
return {
|
|
53
|
-
ts,
|
|
54
|
-
skill,
|
|
55
|
-
type,
|
|
56
|
-
key,
|
|
57
|
-
insight,
|
|
58
|
-
confidence,
|
|
59
|
-
source
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
function normalizeToken(value) {
|
|
63
|
-
const normalized = value.trim().replace(/[^A-Za-z0-9._-]+/gu, "-");
|
|
64
|
-
return normalized.replace(/^-+/u, "").replace(/-+$/u, "") || "unknown";
|
|
65
|
-
}
|
|
66
|
-
function maybeObservation(value) {
|
|
67
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
68
|
-
return null;
|
|
69
|
-
const obj = value;
|
|
70
|
-
return {
|
|
71
|
-
ts: typeof obj.ts === "string" ? obj.ts : undefined,
|
|
72
|
-
event: typeof obj.event === "string" ? obj.event : undefined,
|
|
73
|
-
tool: typeof obj.tool === "string" ? obj.tool : undefined,
|
|
74
|
-
phase: typeof obj.phase === "string" ? obj.phase : undefined,
|
|
75
|
-
stage: typeof obj.stage === "string" ? obj.stage : undefined,
|
|
76
|
-
runId: typeof obj.runId === "string" ? obj.runId : undefined,
|
|
77
|
-
data: obj.data
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function bestByConfidence(candidates) {
|
|
81
|
-
const table = new Map();
|
|
82
|
-
for (const candidate of candidates) {
|
|
83
|
-
const token = `${candidate.key}:${candidate.type}`;
|
|
84
|
-
const current = table.get(token);
|
|
85
|
-
if (!current || candidate.confidence > current.confidence) {
|
|
86
|
-
table.set(token, candidate);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return Array.from(table.values());
|
|
90
|
-
}
|
|
91
|
-
function buildCandidates(observations, timestamp) {
|
|
92
|
-
const toolUsage = new Map();
|
|
93
|
-
const toolErrors = new Map();
|
|
94
|
-
const stageErrors = new Map();
|
|
95
|
-
const longPayload = new Map();
|
|
96
|
-
for (const obs of observations) {
|
|
97
|
-
const tool = normalizeToken(obs.tool ?? "unknown");
|
|
98
|
-
const stage = normalizeToken(obs.stage ?? "none");
|
|
99
|
-
const payload = toText(obs.data);
|
|
100
|
-
toolUsage.set(tool, (toolUsage.get(tool) ?? 0) + 1);
|
|
101
|
-
if (payload.length >= 1500) {
|
|
102
|
-
longPayload.set(tool, (longPayload.get(tool) ?? 0) + 1);
|
|
103
|
-
}
|
|
104
|
-
if ((obs.event ?? "") === "tool_complete" && ERROR_PATTERN.test(payload)) {
|
|
105
|
-
toolErrors.set(tool, (toolErrors.get(tool) ?? 0) + 1);
|
|
106
|
-
stageErrors.set(stage, (stageErrors.get(stage) ?? 0) + 1);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
const candidates = [];
|
|
110
|
-
for (const [tool, errors] of toolErrors.entries()) {
|
|
111
|
-
if (errors < 3)
|
|
112
|
-
continue;
|
|
113
|
-
candidates.push({
|
|
114
|
-
ts: timestamp,
|
|
115
|
-
skill: "observation",
|
|
116
|
-
type: "pitfall",
|
|
117
|
-
key: `frequent-errors-${tool}`,
|
|
118
|
-
insight: `Tool ${tool} produced ${errors} error-like completions in a single session; add a preflight checklist before using it.`,
|
|
119
|
-
confidence: Math.min(9, 4 + Math.floor(errors / 2)),
|
|
120
|
-
source: "observed"
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
for (const [tool, total] of toolUsage.entries()) {
|
|
124
|
-
if (total < 8)
|
|
125
|
-
continue;
|
|
126
|
-
const errors = toolErrors.get(tool) ?? 0;
|
|
127
|
-
if (errors > Math.max(1, Math.floor(total * 0.15)))
|
|
128
|
-
continue;
|
|
129
|
-
candidates.push({
|
|
130
|
-
ts: timestamp,
|
|
131
|
-
skill: "observation",
|
|
132
|
-
type: "pattern",
|
|
133
|
-
key: `reliable-tool-${tool}`,
|
|
134
|
-
insight: `Tool ${tool} was used ${total} times with low failure rate; prefer it as a first option for similar tasks.`,
|
|
135
|
-
confidence: Math.min(8, 3 + Math.floor(total / 3)),
|
|
136
|
-
source: "observed"
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
for (const [stage, errors] of stageErrors.entries()) {
|
|
140
|
-
if (stage === "none" || errors < 4)
|
|
141
|
-
continue;
|
|
142
|
-
candidates.push({
|
|
143
|
-
ts: timestamp,
|
|
144
|
-
skill: "observation",
|
|
145
|
-
type: "pitfall",
|
|
146
|
-
key: `stage-hotspot-${stage}`,
|
|
147
|
-
insight: `Stage ${stage} produced ${errors} error-like tool completions in one session; add stage-specific checks before execution.`,
|
|
148
|
-
confidence: Math.min(8, 3 + Math.floor(errors / 2)),
|
|
149
|
-
source: "observed"
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
for (const [tool, count] of longPayload.entries()) {
|
|
153
|
-
if (count < 3)
|
|
154
|
-
continue;
|
|
155
|
-
candidates.push({
|
|
156
|
-
ts: timestamp,
|
|
157
|
-
skill: "observation",
|
|
158
|
-
type: "preference",
|
|
159
|
-
key: `truncate-heavy-payloads-${tool}`,
|
|
160
|
-
insight: `Tool ${tool} produced large payloads repeatedly; summarize outputs earlier to avoid context pressure.`,
|
|
161
|
-
confidence: Math.min(7, 3 + Math.floor(count / 2)),
|
|
162
|
-
source: "observed"
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
return bestByConfidence(candidates).filter((entry) => asValidLearning(entry) !== null);
|
|
166
|
-
}
|
|
167
|
-
function appendableCandidates(existing, candidates) {
|
|
168
|
-
const bestExisting = new Map();
|
|
169
|
-
for (const entry of existing) {
|
|
170
|
-
const token = `${entry.key}:${entry.type}`;
|
|
171
|
-
const current = bestExisting.get(token) ?? 0;
|
|
172
|
-
if (entry.confidence > current)
|
|
173
|
-
bestExisting.set(token, entry.confidence);
|
|
174
|
-
}
|
|
175
|
-
const appendable = [];
|
|
176
|
-
for (const candidate of candidates) {
|
|
177
|
-
const token = `${candidate.key}:${candidate.type}`;
|
|
178
|
-
const current = bestExisting.get(token) ?? 0;
|
|
179
|
-
if (candidate.confidence > current) {
|
|
180
|
-
appendable.push(candidate);
|
|
181
|
-
bestExisting.set(token, candidate.confidence);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return appendable;
|
|
185
|
-
}
|
|
186
|
-
export function summarizeObservationLearnings(observationJsonl, existingLearningsJsonl, timestamp) {
|
|
187
|
-
const observations = observationJsonl
|
|
188
|
-
.split(/\r?\n/gu)
|
|
189
|
-
.map(parseJsonLine)
|
|
190
|
-
.filter((value) => value !== null)
|
|
191
|
-
.map(maybeObservation)
|
|
192
|
-
.filter((value) => value !== null);
|
|
193
|
-
const existing = existingLearningsJsonl
|
|
194
|
-
.split(/\r?\n/gu)
|
|
195
|
-
.map(parseJsonLine)
|
|
196
|
-
.map((value) => (value ? asValidLearning(value) : null))
|
|
197
|
-
.filter((value) => value !== null);
|
|
198
|
-
const candidates = buildCandidates(observations, timestamp);
|
|
199
|
-
const appendable = appendableCandidates(existing, candidates);
|
|
200
|
-
return { candidates, appendable };
|
|
201
|
-
}
|