cclaw-cli 0.5.4 → 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 +3 -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 +34 -34
- package/dist/content/hooks.d.ts +4 -6
- package/dist/content/hooks.js +104 -523
- 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 +10 -48
- package/dist/content/session-hooks.js +8 -8
- package/dist/content/skills.js +9 -16
- package/dist/content/stage-schema.js +80 -121
- 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 +16 -47
- package/dist/flow-state.js +1 -1
- package/dist/harness-adapters.js +1 -1
- package/dist/install.js +22 -48
- package/dist/policy.js +1 -4
- package/dist/runs.d.ts +9 -9
- package/dist/runs.js +107 -320
- 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/README.md
CHANGED
|
@@ -27,10 +27,10 @@ sequenceDiagram
|
|
|
27
27
|
participant U as User
|
|
28
28
|
participant H as Harness
|
|
29
29
|
participant V as cclaw Hooks + Skills
|
|
30
|
-
participant S as State +
|
|
30
|
+
participant S as State + Knowledge
|
|
31
31
|
U->>H: /cc <idea>
|
|
32
32
|
H->>V: Load stage contract + HARD-GATE
|
|
33
|
-
V->>S: Read context (state/
|
|
33
|
+
V->>S: Read context (state/knowledge)
|
|
34
34
|
V-->>H: Structured execution guidance
|
|
35
35
|
H->>S: Write artifacts + checkpoint
|
|
36
36
|
S-->>U: Next stage is explicit
|
|
@@ -42,8 +42,8 @@ sequenceDiagram
|
|
|
42
42
|
- **Installer-first architecture:** generates files and hooks; does not run a hidden control plane.
|
|
43
43
|
- **Hard-gated quality:** each stage has non-skippable constraints that reduce AI drift.
|
|
44
44
|
- **Cross-harness parity:** same behavior model across Claude Code, Cursor, Codex, OpenCode.
|
|
45
|
-
- **Compounding context:** flow state +
|
|
46
|
-
- **
|
|
45
|
+
- **Compounding context:** flow state + project knowledge get rehydrated on new sessions automatically.
|
|
46
|
+
- **Incremental delivery:** active artifacts stay in one place; `cclaw archive` snapshots completed features into dated run folders.
|
|
47
47
|
|
|
48
48
|
## Compared To Top References
|
|
49
49
|
|
|
@@ -73,6 +73,7 @@ Core installer lifecycle:
|
|
|
73
73
|
```bash
|
|
74
74
|
npx cclaw-cli sync
|
|
75
75
|
npx cclaw-cli doctor
|
|
76
|
+
npx cclaw-cli archive --name <feature-name>
|
|
76
77
|
npx cclaw-cli upgrade
|
|
77
78
|
npx cclaw-cli uninstall
|
|
78
79
|
```
|
|
@@ -113,14 +114,10 @@ Required repository secret:
|
|
|
113
114
|
├── commands/
|
|
114
115
|
├── hooks/
|
|
115
116
|
├── templates/
|
|
116
|
-
├── artifacts/ # active
|
|
117
|
+
├── artifacts/ # active feature artifacts
|
|
117
118
|
├── state/
|
|
118
|
-
├──
|
|
119
|
-
|
|
120
|
-
│ ├── artifacts/ # canonical run artifacts
|
|
121
|
-
│ ├── run.json
|
|
122
|
-
│ └── handoff.md
|
|
123
|
-
└── learnings.jsonl
|
|
119
|
+
├── knowledge.md # append-only rule/pattern/lesson log
|
|
120
|
+
└── runs/ # archived feature snapshots (YYYY-MM-DD-feature-name)
|
|
124
121
|
```
|
|
125
122
|
|
|
126
123
|
## License
|
package/dist/artifact-linter.js
CHANGED
|
@@ -3,20 +3,10 @@ import path from "node:path";
|
|
|
3
3
|
import { RUNTIME_ROOT } from "./constants.js";
|
|
4
4
|
import { exists } from "./fs-utils.js";
|
|
5
5
|
import { orderedStageSchemas, stageSchema } from "./content/stage-schema.js";
|
|
6
|
-
import { readFlowState } from "./runs.js";
|
|
7
6
|
async function resolveArtifactPath(projectRoot, fileName) {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const runId = activeRunId.trim();
|
|
12
|
-
if (runId.length > 0) {
|
|
13
|
-
const canonicalRelPath = path.join(RUNTIME_ROOT, "runs", runId, "artifacts", fileName);
|
|
14
|
-
const canonicalAbsPath = path.join(projectRoot, canonicalRelPath);
|
|
15
|
-
if (await exists(canonicalAbsPath)) {
|
|
16
|
-
return { absPath: canonicalAbsPath, relPath: canonicalRelPath };
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return { absPath: fallbackAbsPath, relPath: fallbackRelPath };
|
|
7
|
+
const relPath = path.join(RUNTIME_ROOT, "artifacts", fileName);
|
|
8
|
+
const absPath = path.join(projectRoot, relPath);
|
|
9
|
+
return { absPath, relPath };
|
|
20
10
|
}
|
|
21
11
|
function normalizeHeadingTitle(title) {
|
|
22
12
|
return title.trim().replace(/\s+/g, " ");
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import type { HarnessId } from "./types.js";
|
|
3
|
-
type CommandName = "init" | "sync" | "doctor" | "upgrade" | "uninstall";
|
|
3
|
+
type CommandName = "init" | "sync" | "doctor" | "upgrade" | "uninstall" | "archive";
|
|
4
4
|
interface ParsedArgs {
|
|
5
5
|
command?: CommandName;
|
|
6
6
|
harnesses?: HarnessId[];
|
|
7
7
|
reconcileGates?: boolean;
|
|
8
|
+
archiveName?: string;
|
|
8
9
|
}
|
|
9
10
|
declare function parseHarnesses(raw: string): HarnessId[];
|
|
10
11
|
declare function parseArgs(argv: string[]): ParsedArgs;
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,8 @@ import { HARNESS_IDS } from "./types.js";
|
|
|
7
7
|
import { doctorChecks, doctorSucceeded } from "./doctor.js";
|
|
8
8
|
import { initCclaw, syncCclaw, uninstallCclaw, upgradeCclaw } from "./install.js";
|
|
9
9
|
import { error, info } from "./logger.js";
|
|
10
|
-
|
|
10
|
+
import { archiveRun } from "./runs.js";
|
|
11
|
+
const INSTALLER_COMMANDS = ["init", "sync", "doctor", "upgrade", "uninstall", "archive"];
|
|
11
12
|
function usage() {
|
|
12
13
|
return `cclaw - installer-first flow toolkit
|
|
13
14
|
|
|
@@ -15,6 +16,7 @@ Usage:
|
|
|
15
16
|
cclaw init [--harnesses=claude,cursor,opencode,codex]
|
|
16
17
|
cclaw sync
|
|
17
18
|
cclaw doctor [--reconcile-gates]
|
|
19
|
+
cclaw archive [--name=feature-name]
|
|
18
20
|
cclaw upgrade
|
|
19
21
|
cclaw uninstall
|
|
20
22
|
`;
|
|
@@ -43,6 +45,10 @@ function parseArgs(argv) {
|
|
|
43
45
|
}
|
|
44
46
|
if (flag === "--reconcile-gates") {
|
|
45
47
|
parsed.reconcileGates = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (flag.startsWith("--name=")) {
|
|
51
|
+
parsed.archiveName = flag.replace("--name=", "").trim();
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
54
|
return parsed;
|
|
@@ -80,6 +86,11 @@ async function runCommand(parsed, ctx) {
|
|
|
80
86
|
info(ctx, "Upgraded .cclaw runtime and regenerated generated files");
|
|
81
87
|
return 0;
|
|
82
88
|
}
|
|
89
|
+
if (command === "archive") {
|
|
90
|
+
const archived = await archiveRun(ctx.cwd, parsed.archiveName);
|
|
91
|
+
info(ctx, `Archived active artifacts to ${archived.archivePath}. Flow state reset to brainstorm.`);
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
83
94
|
await uninstallCclaw(ctx.cwd);
|
|
84
95
|
info(ctx, "Removed .cclaw runtime and generated shim files");
|
|
85
96
|
return 0;
|
package/dist/config.js
CHANGED
|
@@ -12,8 +12,6 @@ const ALLOWED_CONFIG_KEYS = new Set([
|
|
|
12
12
|
"flowVersion",
|
|
13
13
|
"harnesses",
|
|
14
14
|
"autoAdvance",
|
|
15
|
-
"globalLearnings",
|
|
16
|
-
"globalLearningsPath",
|
|
17
15
|
"promptGuardMode",
|
|
18
16
|
"gitHookGuards"
|
|
19
17
|
]);
|
|
@@ -37,7 +35,6 @@ export function createDefaultConfig(harnesses = DEFAULT_HARNESSES) {
|
|
|
37
35
|
flowVersion: FLOW_VERSION,
|
|
38
36
|
harnesses,
|
|
39
37
|
autoAdvance: false,
|
|
40
|
-
globalLearnings: false,
|
|
41
38
|
promptGuardMode: "advisory",
|
|
42
39
|
gitHookGuards: false
|
|
43
40
|
};
|
|
@@ -79,20 +76,6 @@ export async function readConfig(projectRoot) {
|
|
|
79
76
|
: DEFAULT_HARNESSES;
|
|
80
77
|
const autoAdvanceRaw = parsed.autoAdvance;
|
|
81
78
|
const autoAdvance = typeof autoAdvanceRaw === "boolean" ? autoAdvanceRaw : false;
|
|
82
|
-
const globalLearningsRaw = parsed.globalLearnings;
|
|
83
|
-
if (Object.prototype.hasOwnProperty.call(parsed, "globalLearnings") &&
|
|
84
|
-
typeof globalLearningsRaw !== "boolean") {
|
|
85
|
-
throw configValidationError(fullPath, `"globalLearnings" must be a boolean`);
|
|
86
|
-
}
|
|
87
|
-
const globalLearnings = typeof globalLearningsRaw === "boolean" ? globalLearningsRaw : false;
|
|
88
|
-
const globalLearningsPathRaw = parsed.globalLearningsPath;
|
|
89
|
-
if (Object.prototype.hasOwnProperty.call(parsed, "globalLearningsPath") &&
|
|
90
|
-
typeof globalLearningsPathRaw !== "string") {
|
|
91
|
-
throw configValidationError(fullPath, `"globalLearningsPath" must be a string`);
|
|
92
|
-
}
|
|
93
|
-
const globalLearningsPath = typeof globalLearningsPathRaw === "string" && globalLearningsPathRaw.trim().length > 0
|
|
94
|
-
? globalLearningsPathRaw.trim()
|
|
95
|
-
: undefined;
|
|
96
79
|
const promptGuardModeRaw = parsed.promptGuardMode;
|
|
97
80
|
if (Object.prototype.hasOwnProperty.call(parsed, "promptGuardMode") &&
|
|
98
81
|
promptGuardModeRaw !== "advisory" &&
|
|
@@ -111,8 +94,6 @@ export async function readConfig(projectRoot) {
|
|
|
111
94
|
flowVersion: parsed.flowVersion ?? FLOW_VERSION,
|
|
112
95
|
harnesses,
|
|
113
96
|
autoAdvance,
|
|
114
|
-
globalLearnings,
|
|
115
|
-
globalLearningsPath,
|
|
116
97
|
promptGuardMode,
|
|
117
98
|
gitHookGuards
|
|
118
99
|
};
|
|
@@ -6,13 +6,7 @@ export function commandContract(stage) {
|
|
|
6
6
|
const reads = schema.crossStageTrace.readsFrom;
|
|
7
7
|
const readsLine = reads.length > 0 ? reads.join(", ") : "(first stage)";
|
|
8
8
|
const hydrationLines = reads.length > 0
|
|
9
|
-
? reads
|
|
10
|
-
.map((readPath) => {
|
|
11
|
-
const parts = readPath.split("/");
|
|
12
|
-
const fileName = parts[parts.length - 1] ?? readPath;
|
|
13
|
-
return `- Canonical: \`.cclaw/runs/<activeRunId>/artifacts/${fileName}\` (fallback: \`${readPath}\`)`;
|
|
14
|
-
})
|
|
15
|
-
.join("\n")
|
|
9
|
+
? reads.map((readPath) => `- \`${readPath}\``).join("\n")
|
|
16
10
|
: "- (first stage — no upstream artifacts)";
|
|
17
11
|
const gateIds = schema.requiredGates
|
|
18
12
|
.map((g) => `\`${g.id}\``)
|
|
@@ -26,16 +20,17 @@ ${schema.hardGate}
|
|
|
26
20
|
|
|
27
21
|
## In / Out
|
|
28
22
|
- **Reads:** ${readsLine}
|
|
29
|
-
- **Writes:** \`.cclaw/artifacts/${schema.artifactFile}\`
|
|
23
|
+
- **Writes:** \`.cclaw/artifacts/${schema.artifactFile}\`
|
|
30
24
|
- **Next:** \`/cc-next\` (updates flow-state and loads the next stage)
|
|
31
25
|
|
|
32
26
|
## Context Hydration (mandatory before stage work)
|
|
33
|
-
1. Read \`.cclaw/state/flow-state.json
|
|
34
|
-
2. Resolve
|
|
27
|
+
1. Read \`.cclaw/state/flow-state.json\`.
|
|
28
|
+
2. Resolve active artifact root: \`.cclaw/artifacts/\`.
|
|
35
29
|
3. Load required upstream artifacts for this stage:
|
|
36
30
|
${hydrationLines}
|
|
37
|
-
4.
|
|
38
|
-
5. Write stage output to \`.cclaw/artifacts/${schema.artifactFile}\`.
|
|
31
|
+
4. Load \`.cclaw/knowledge.md\` and apply relevant entries.
|
|
32
|
+
5. Write stage output to \`.cclaw/artifacts/${schema.artifactFile}\`.
|
|
33
|
+
6. Do NOT copy artifacts into \`.cclaw/runs/\`; archival is handled only by \`cclaw archive\`.
|
|
39
34
|
|
|
40
35
|
## Gates
|
|
41
36
|
${gateIds}
|
package/dist/content/examples.js
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
1
|
const STAGE_EXAMPLES = {
|
|
2
|
-
brainstorm: `###
|
|
2
|
+
brainstorm: `### Route selection
|
|
3
3
|
|
|
4
|
-
**
|
|
5
|
-
**
|
|
4
|
+
- **Route:** Complex Route
|
|
5
|
+
- **Why:** touches CI behavior, release checks, and CLI flow across multiple components.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
**A2:** "No production rollout automation; only release metadata validation + publish safety checks."
|
|
7
|
+
### Round 1 grounding
|
|
9
8
|
|
|
10
|
-
**
|
|
11
|
-
**
|
|
9
|
+
- **Grounding summary:** "We are improving release reliability for the platform team. Success means invalid release preconditions are caught before publish with explicit operator feedback."
|
|
10
|
+
- **User confirmation:** confirmed.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
**A4:** "CI-first in GitHub Actions, but reproducible locally with npm scripts."
|
|
12
|
+
### Round 2 forcing questions (boundaries/constraints)
|
|
15
13
|
|
|
16
|
-
**
|
|
17
|
-
**
|
|
14
|
+
**Q1:** "If release metadata is invalid, do we block publishing hard or only warn?"
|
|
15
|
+
**A1:** "Block hard."
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
**Decision impact:** release checks become mandatory gates with no warning-only fallback.
|
|
20
18
|
|
|
21
|
-
**
|
|
19
|
+
**Q2:** "Do we allow new runtime dependencies for speed, or keep runtime dependency set unchanged?"
|
|
20
|
+
**A2:** "Keep runtime dependencies unchanged."
|
|
22
21
|
|
|
23
|
-
**
|
|
22
|
+
**Decision impact:** implementation should reuse existing tooling and built-in capabilities.
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
### Grounding checkpoint after Round 2
|
|
26
25
|
|
|
27
|
-
**
|
|
26
|
+
- **Fixed:** hard-block behavior, no new runtime dependencies.
|
|
27
|
+
- **Unknown:** rollback command details and status reporting format.
|
|
28
28
|
|
|
29
|
-
###
|
|
29
|
+
### Round 3 forcing questions (trade-offs)
|
|
30
30
|
|
|
31
|
-
**
|
|
31
|
+
**Q3:** "For v1, prioritize rapid delivery or maximum configurability?"
|
|
32
|
+
**A3:** "Rapid delivery."
|
|
32
33
|
|
|
33
|
-
**
|
|
34
|
+
**Decision impact:** choose a minimal deterministic validation surface; defer advanced configuration.
|
|
34
35
|
|
|
35
|
-
###
|
|
36
|
+
### Options comparison
|
|
36
37
|
|
|
37
|
-
|
|
|
38
|
+
| Option | Pros | Cons | Effort | Recommendation |
|
|
38
39
|
| --- | --- | --- | --- | --- |
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
40
|
+
| Script-only checks | Lowest implementation cost | Weak reuse and long-term maintainability | Low | Useful fallback, not preferred |
|
|
41
|
+
| Reusable validation module | Reusable across CI and local runs | Slightly higher upfront design effort | Medium | **Recommended** |
|
|
42
|
+
| Full release framework rewrite | Highest long-term flexibility | High risk and delivery delay | High | Not recommended for v1 |
|
|
42
43
|
|
|
43
44
|
### Approved Direction
|
|
44
45
|
|
|
45
|
-
We will
|
|
46
|
+
We will implement a **reusable release validation module** used by CI and local tooling, aligned with hard-block safety and no-new-runtime-dependency constraints.
|
|
46
47
|
|
|
47
48
|
### Open Questions
|
|
48
49
|
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
- Should mobile clients reuse the same event channel contract or expose a separate polling endpoint?
|
|
50
|
+
- What exact rollback command sequence should be documented for failed publish attempts?
|
|
51
|
+
- Should status output include machine-readable JSON in addition to markdown?
|
|
52
52
|
|
|
53
53
|
### Assumptions (explicit)
|
|
54
54
|
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
55
|
+
- CI remains the primary execution path; local flow mirrors CI checks.
|
|
56
|
+
- Existing release metadata files remain the source of truth.
|
|
57
|
+
- v1 prioritizes deterministic behavior over broad customization.
|
|
58
58
|
|
|
59
59
|
### Constraints
|
|
60
60
|
|
|
61
|
-
- No
|
|
62
|
-
-
|
|
61
|
+
- No additional runtime dependencies in validation path.
|
|
62
|
+
- Validation overhead should remain acceptable for routine CI execution.
|
|
63
63
|
|
|
64
64
|
### Notes for the next stage
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Carry fixed trade-off decisions directly into scope in/out boundaries and deferred list.`,
|
|
67
67
|
scope: `### Scope contract
|
|
68
68
|
|
|
69
69
|
**Mode selected:** SELECTIVE EXPANSION
|
package/dist/content/hooks.d.ts
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hook generators for all supported harnesses.
|
|
3
3
|
*
|
|
4
|
-
* SessionStart: injects using-cclaw + flow state +
|
|
4
|
+
* SessionStart: injects using-cclaw + flow state + knowledge + checkpoint/activity summary.
|
|
5
5
|
* Stop: writes checkpoint.json and reminds about flow consistency.
|
|
6
|
-
*
|
|
6
|
+
* Harness hook JSON wiring is generated in observe.ts.
|
|
7
7
|
*/
|
|
8
8
|
export interface HookRuntimeOptions {
|
|
9
|
-
globalLearningsEnabled?: boolean;
|
|
10
|
-
globalLearningsPath?: string;
|
|
11
9
|
}
|
|
12
10
|
/** Shared bash preamble for generated hook scripts. */
|
|
13
11
|
export declare const RUNTIME_SHELL_DETECT_ROOT = "HARNESS=\"codex\"\nif [ -n \"${CLAUDE_PROJECT_DIR:-}\" ]; then\n HARNESS=\"claude\"\nelif [ -n \"${CURSOR_PROJECT_DIR:-}\" ] || [ -n \"${CURSOR_PROJECT_ROOT:-}\" ]; then\n HARNESS=\"cursor\"\nelif [ -n \"${OPENCODE_PROJECT_DIR:-}\" ] || [ -n \"${OPENCODE_PROJECT_ROOT:-}\" ]; then\n HARNESS=\"opencode\"\nfi\n\nROOT=\"\"\nfor candidate in \"${CCLAW_PROJECT_ROOT:-}\" \"${CLAUDE_PROJECT_DIR:-}\" \"${CURSOR_PROJECT_DIR:-}\" \"${CURSOR_PROJECT_ROOT:-}\" \"${OPENCODE_PROJECT_DIR:-}\" \"${OPENCODE_PROJECT_ROOT:-}\" \"${PWD:-}\"; do\n if [ -n \"$candidate\" ] && [ -d \"$candidate/.cclaw\" ]; then\n ROOT=\"$candidate\"\n break\n fi\ndone\nif [ -z \"$ROOT\" ]; then\n ROOT=\"${CCLAW_PROJECT_ROOT:-${CLAUDE_PROJECT_DIR:-${CURSOR_PROJECT_DIR:-${CURSOR_PROJECT_ROOT:-${OPENCODE_PROJECT_DIR:-${OPENCODE_PROJECT_ROOT:-${PWD}}}}}}}\"\nfi";
|
|
14
|
-
export declare function sessionStartScript(
|
|
12
|
+
export declare function sessionStartScript(_options?: HookRuntimeOptions): string;
|
|
15
13
|
export declare function stopCheckpointScript(): string;
|
|
16
14
|
export { claudeHooksJsonWithObservation as claudeHooksJson } from "./observe.js";
|
|
17
15
|
export { cursorHooksJsonWithObservation as cursorHooksJson } from "./observe.js";
|
|
18
16
|
export { codexHooksJsonWithObservation as codexHooksJson } from "./observe.js";
|
|
19
|
-
export declare function opencodePluginJs(
|
|
17
|
+
export declare function opencodePluginJs(_options?: HookRuntimeOptions): string;
|
|
20
18
|
export declare function hooksAgentsMdBlock(): string;
|