cclaw-cli 0.48.35 → 0.49.0
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.js +0 -4
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +0 -3
- package/dist/content/contexts.d.ts +11 -2
- package/dist/content/contexts.js +17 -58
- package/dist/content/meta-skill.js +0 -3
- package/dist/content/utility-skills.js +7 -6
- package/dist/doctor.js +0 -64
- package/dist/install.js +1 -163
- package/dist/policy.js +0 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -143,14 +143,10 @@ function buildInitSurfacePreview(harnesses) {
|
|
|
143
143
|
".cclaw/config.yaml",
|
|
144
144
|
".cclaw/commands/*.md",
|
|
145
145
|
".cclaw/skills/*/SKILL.md",
|
|
146
|
-
".cclaw/contexts/*.md",
|
|
147
146
|
".cclaw/templates/*",
|
|
148
147
|
".cclaw/agents/*.md",
|
|
149
148
|
".cclaw/hooks/*",
|
|
150
149
|
".cclaw/rules/**",
|
|
151
|
-
".cclaw/adapters/*.md",
|
|
152
|
-
".cclaw/custom-skills/README.md",
|
|
153
|
-
".cclaw/worktrees/**",
|
|
154
150
|
".cclaw/features/** (legacy snapshots, read-only migration)",
|
|
155
151
|
".cclaw/runs/**",
|
|
156
152
|
".cclaw/artifacts/**",
|
package/dist/constants.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare const DEFAULT_HARNESSES: HarnessId[];
|
|
|
19
19
|
export declare const EVALS_ROOT = ".cclaw/evals";
|
|
20
20
|
export declare const EVALS_CONFIG_PATH = ".cclaw/evals/config.yaml";
|
|
21
21
|
export declare const EVALS_DIRS: readonly [".cclaw/evals", ".cclaw/evals/corpus", ".cclaw/evals/rubrics", ".cclaw/evals/baselines", ".cclaw/evals/reports"];
|
|
22
|
-
export declare const REQUIRED_DIRS: readonly [".cclaw", ".cclaw/commands", ".cclaw/skills", ".cclaw/contexts", ".cclaw/templates", ".cclaw/artifacts", ".cclaw/
|
|
22
|
+
export declare const REQUIRED_DIRS: readonly [".cclaw", ".cclaw/commands", ".cclaw/skills", ".cclaw/contexts", ".cclaw/templates", ".cclaw/artifacts", ".cclaw/state", ".cclaw/runs", ".cclaw/rules", ".cclaw/agents", ".cclaw/hooks", ".cclaw/evals", ".cclaw/evals/corpus", ".cclaw/evals/rubrics", ".cclaw/evals/baselines", ".cclaw/evals/reports"];
|
|
23
23
|
export declare const REQUIRED_GITIGNORE_PATTERNS: readonly ["# cclaw generated artifacts", ".cclaw/", "# cclaw evals: user-owned, track in git", "!.cclaw/evals/", "!.cclaw/evals/config.yaml", "!.cclaw/evals/corpus/", "!.cclaw/evals/corpus/**", "!.cclaw/evals/rubrics/", "!.cclaw/evals/rubrics/**", "!.cclaw/evals/baselines/", "!.cclaw/evals/baselines/**", ".claude/commands/cc-*.md", ".claude/commands/cc.md", ".cursor/commands/cc-*.md", ".cursor/commands/cc.md", ".opencode/commands/cc-*.md", ".opencode/commands/cc.md", ".agents/skills/cc/SKILL.md", ".agents/skills/cc-*/SKILL.md", ".claude/hooks/hooks.json", ".cursor/hooks.json", ".codex/hooks.json", ".opencode/plugins/cclaw-plugin.mjs", ".cursor/rules/cclaw-workflow.mdc"];
|
|
24
24
|
/**
|
|
25
25
|
* Canonical stage -> skill folder mapping.
|
package/dist/constants.js
CHANGED
|
@@ -74,14 +74,11 @@ export const REQUIRED_DIRS = [
|
|
|
74
74
|
`${RUNTIME_ROOT}/contexts`,
|
|
75
75
|
`${RUNTIME_ROOT}/templates`,
|
|
76
76
|
`${RUNTIME_ROOT}/artifacts`,
|
|
77
|
-
`${RUNTIME_ROOT}/worktrees`,
|
|
78
77
|
`${RUNTIME_ROOT}/state`,
|
|
79
78
|
`${RUNTIME_ROOT}/runs`,
|
|
80
79
|
`${RUNTIME_ROOT}/rules`,
|
|
81
|
-
`${RUNTIME_ROOT}/adapters`,
|
|
82
80
|
`${RUNTIME_ROOT}/agents`,
|
|
83
81
|
`${RUNTIME_ROOT}/hooks`,
|
|
84
|
-
`${RUNTIME_ROOT}/custom-skills`,
|
|
85
82
|
...EVALS_DIRS
|
|
86
83
|
];
|
|
87
84
|
export const REQUIRED_GITIGNORE_PATTERNS = [
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
export declare const DEFAULT_CONTEXT_MODE = "default";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Valid context mode identifiers used by the session hooks and the
|
|
4
|
+
* `context-engineering` skill. Mode bodies no longer live as separate
|
|
5
|
+
* `.cclaw/contexts/<mode>.md` files — the guidance was merged into the
|
|
6
|
+
* `context-engineering` skill. This list only exists so `doctor` can
|
|
7
|
+
* validate that `state/context-mode.json#activeMode` references a known
|
|
8
|
+
* mode name.
|
|
9
|
+
*/
|
|
10
|
+
export declare const AVAILABLE_CONTEXT_MODES: readonly ["default", "execution", "review", "incident"];
|
|
11
|
+
/** Legacy alias: kept so existing imports keep typechecking. */
|
|
12
|
+
export declare const CONTEXT_MODES: Record<string, true>;
|
|
4
13
|
export interface ContextModeState {
|
|
5
14
|
activeMode: string;
|
|
6
15
|
updatedAt: string;
|
package/dist/content/contexts.js
CHANGED
|
@@ -1,65 +1,24 @@
|
|
|
1
1
|
export const DEFAULT_CONTEXT_MODE = "default";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Use when plan/spec are approved and the goal is high-throughput delivery.
|
|
19
|
-
|
|
20
|
-
## Focus
|
|
21
|
-
- Prioritize deterministic implementation flow (RED -> GREEN -> REFACTOR).
|
|
22
|
-
- Minimize conversational overhead; keep updates concise and evidence-first.
|
|
23
|
-
- Batch machine-only checks through subagent dispatch where supported.
|
|
24
|
-
|
|
25
|
-
## Decision posture
|
|
26
|
-
- Avoid reopening settled design debates unless a blocker appears.
|
|
27
|
-
- Stop immediately on failing quality gates or unresolved critical findings.
|
|
28
|
-
`,
|
|
29
|
-
review: `# Context Mode: review
|
|
30
|
-
|
|
31
|
-
Use for deep validation, risk discovery, and merge readiness.
|
|
32
|
-
|
|
33
|
-
## Focus
|
|
34
|
-
- Bias toward finding concrete defects, regressions, and evidence gaps.
|
|
35
|
-
- Cross-check spec, plan, tests, and implementation alignment.
|
|
36
|
-
- Treat unsupported claims as unverified until backed by command output.
|
|
37
|
-
|
|
38
|
-
## Decision posture
|
|
39
|
-
- Classify findings by severity and expected blast radius.
|
|
40
|
-
- Block ship decisions when critical issues remain unresolved.
|
|
41
|
-
`,
|
|
42
|
-
incident: `# Context Mode: incident
|
|
43
|
-
|
|
44
|
-
Use for production failures, emergency regressions, or urgent stabilization.
|
|
45
|
-
|
|
46
|
-
## Focus
|
|
47
|
-
- Reproduce first, then isolate, then fix.
|
|
48
|
-
- Favor smallest safe change with rollback clarity.
|
|
49
|
-
- Preserve timeline and evidence for post-incident learning.
|
|
50
|
-
|
|
51
|
-
## Decision posture
|
|
52
|
-
- Prefer containment over optimization.
|
|
53
|
-
- Require explicit evidence for declaring recovery complete.
|
|
54
|
-
`
|
|
55
|
-
};
|
|
56
|
-
export function contextModeFiles() {
|
|
57
|
-
return { ...CONTEXT_MODES };
|
|
58
|
-
}
|
|
2
|
+
/**
|
|
3
|
+
* Valid context mode identifiers used by the session hooks and the
|
|
4
|
+
* `context-engineering` skill. Mode bodies no longer live as separate
|
|
5
|
+
* `.cclaw/contexts/<mode>.md` files — the guidance was merged into the
|
|
6
|
+
* `context-engineering` skill. This list only exists so `doctor` can
|
|
7
|
+
* validate that `state/context-mode.json#activeMode` references a known
|
|
8
|
+
* mode name.
|
|
9
|
+
*/
|
|
10
|
+
export const AVAILABLE_CONTEXT_MODES = [
|
|
11
|
+
"default",
|
|
12
|
+
"execution",
|
|
13
|
+
"review",
|
|
14
|
+
"incident"
|
|
15
|
+
];
|
|
16
|
+
/** Legacy alias: kept so existing imports keep typechecking. */
|
|
17
|
+
export const CONTEXT_MODES = Object.fromEntries(AVAILABLE_CONTEXT_MODES.map((mode) => [mode, true]));
|
|
59
18
|
export function createInitialContextModeState(nowIso = new Date().toISOString()) {
|
|
60
19
|
return {
|
|
61
20
|
activeMode: DEFAULT_CONTEXT_MODE,
|
|
62
21
|
updatedAt: nowIso,
|
|
63
|
-
availableModes:
|
|
22
|
+
availableModes: [...AVAILABLE_CONTEXT_MODES]
|
|
64
23
|
};
|
|
65
24
|
}
|
|
@@ -106,9 +106,6 @@ Load utility skills only when triggered by the current task:
|
|
|
106
106
|
- iron-laws as policy arbitration when instructions conflict
|
|
107
107
|
- language rule packs from \`.cclaw/config.yaml\` when enabled
|
|
108
108
|
|
|
109
|
-
Custom project skills under \`.cclaw/custom-skills/\` are opt-in supplements,
|
|
110
|
-
never mandatory delegations.
|
|
111
|
-
|
|
112
109
|
## Protocol references
|
|
113
110
|
|
|
114
111
|
Do not inline these protocols in stage skills; cite by path:
|
|
@@ -565,11 +565,12 @@ Do not keep stale or oversized context loaded when task intent changes. Context
|
|
|
565
565
|
|
|
566
566
|
## Context Modes
|
|
567
567
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
- \`
|
|
571
|
-
- \`
|
|
572
|
-
- \`
|
|
568
|
+
Four intentional postures tracked via \`.cclaw/state/context-mode.json\`:
|
|
569
|
+
|
|
570
|
+
- \`default\` — balanced execution. Follow active stage, keep changes scoped, escalate real trade-offs only.
|
|
571
|
+
- \`execution\` — high-throughput delivery after spec/plan lock. RED→GREEN→REFACTOR. Evidence-first, minimal chatter.
|
|
572
|
+
- \`review\` — deep validation. Bias toward concrete defects, unsupported claims treated as unverified.
|
|
573
|
+
- \`incident\` — stabilization. Reproduce, isolate, fix smallest safe change first. Preserve evidence.
|
|
573
574
|
|
|
574
575
|
## Mode Switching Protocol
|
|
575
576
|
|
|
@@ -578,7 +579,7 @@ Modes are stored in \`.cclaw/contexts/\`:
|
|
|
578
579
|
- \`activeMode\`: target mode id
|
|
579
580
|
- \`updatedAt\`: current ISO timestamp
|
|
580
581
|
3. Announce mode change in-session with one-line reason.
|
|
581
|
-
4.
|
|
582
|
+
4. Keep applying the posture above until the next explicit mode switch.
|
|
582
583
|
|
|
583
584
|
## Payload Hygiene Rules
|
|
584
585
|
|
package/dist/doctor.js
CHANGED
|
@@ -1241,62 +1241,6 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
1241
1241
|
ok: await exists(path.join(projectRoot, RUNTIME_ROOT, "state", "harness-gaps.json")),
|
|
1242
1242
|
details: `${RUNTIME_ROOT}/state/harness-gaps.json must exist for tiered harness capability tracking`
|
|
1243
1243
|
});
|
|
1244
|
-
const adapterManifestPath = path.join(projectRoot, RUNTIME_ROOT, "adapters", "manifest.json");
|
|
1245
|
-
const adapterManifestExists = await exists(adapterManifestPath);
|
|
1246
|
-
checks.push({
|
|
1247
|
-
name: "state:adapter_manifest_exists",
|
|
1248
|
-
ok: adapterManifestExists,
|
|
1249
|
-
details: `${RUNTIME_ROOT}/adapters/manifest.json must exist for harness adapter provenance`
|
|
1250
|
-
});
|
|
1251
|
-
if (adapterManifestExists) {
|
|
1252
|
-
let harnessesOk = false;
|
|
1253
|
-
let harnessesDetails = "";
|
|
1254
|
-
let sourcesOk = false;
|
|
1255
|
-
let sourcesDetails = "";
|
|
1256
|
-
try {
|
|
1257
|
-
const parsed = JSON.parse(await fs.readFile(adapterManifestPath, "utf8"));
|
|
1258
|
-
const manifestHarnesses = Array.isArray(parsed.harnesses)
|
|
1259
|
-
? parsed.harnesses.filter((entry) => typeof entry === "string")
|
|
1260
|
-
: [];
|
|
1261
|
-
const expectedHarnesses = configuredHarnesses.length > 0
|
|
1262
|
-
? [...new Set(configuredHarnesses)].sort()
|
|
1263
|
-
: null;
|
|
1264
|
-
const actualHarnesses = [...new Set(manifestHarnesses)].sort();
|
|
1265
|
-
harnessesOk = expectedHarnesses
|
|
1266
|
-
? actualHarnesses.length === expectedHarnesses.length &&
|
|
1267
|
-
actualHarnesses.every((harness, index) => harness === expectedHarnesses[index])
|
|
1268
|
-
: actualHarnesses.length > 0;
|
|
1269
|
-
harnessesDetails = expectedHarnesses
|
|
1270
|
-
? harnessesOk
|
|
1271
|
-
? `adapter manifest harnesses match config.yaml: ${actualHarnesses.join(", ")}`
|
|
1272
|
-
: `adapter manifest harnesses [${actualHarnesses.join(", ")}] do not match config.yaml [${expectedHarnesses.join(", ")}]`
|
|
1273
|
-
: harnessesOk
|
|
1274
|
-
? `adapter manifest declares harnesses: ${actualHarnesses.join(", ")}`
|
|
1275
|
-
: "adapter manifest must declare at least one harness";
|
|
1276
|
-
const commandSource = typeof parsed.commandSource === "string" ? parsed.commandSource.trim() : "";
|
|
1277
|
-
const skillSource = typeof parsed.skillSource === "string" ? parsed.skillSource.trim() : "";
|
|
1278
|
-
sourcesOk = commandSource.length > 0 && skillSource.length > 0;
|
|
1279
|
-
sourcesDetails = sourcesOk
|
|
1280
|
-
? `adapter manifest source globs are set (commandSource=${commandSource}; skillSource=${skillSource})`
|
|
1281
|
-
: "adapter manifest must include non-empty commandSource and skillSource";
|
|
1282
|
-
}
|
|
1283
|
-
catch {
|
|
1284
|
-
harnessesOk = false;
|
|
1285
|
-
harnessesDetails = "adapter manifest must be valid JSON with a harnesses array";
|
|
1286
|
-
sourcesOk = false;
|
|
1287
|
-
sourcesDetails = "adapter manifest must be valid JSON with source globs";
|
|
1288
|
-
}
|
|
1289
|
-
checks.push({
|
|
1290
|
-
name: "state:adapter_manifest_harnesses",
|
|
1291
|
-
ok: harnessesOk,
|
|
1292
|
-
details: harnessesDetails
|
|
1293
|
-
});
|
|
1294
|
-
checks.push({
|
|
1295
|
-
name: "state:adapter_manifest_sources",
|
|
1296
|
-
ok: sourcesOk,
|
|
1297
|
-
details: sourcesDetails
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
1244
|
const contextModeStatePath = path.join(projectRoot, RUNTIME_ROOT, "state", "context-mode.json");
|
|
1301
1245
|
checks.push({
|
|
1302
1246
|
name: "state:context_mode_exists",
|
|
@@ -1319,14 +1263,6 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
1319
1263
|
details: `${RUNTIME_ROOT}/state/context-mode.json must reference one of: ${Object.keys(CONTEXT_MODES).join(", ")} (default=${DEFAULT_CONTEXT_MODE})`
|
|
1320
1264
|
});
|
|
1321
1265
|
}
|
|
1322
|
-
for (const mode of Object.keys(CONTEXT_MODES)) {
|
|
1323
|
-
const modePath = path.join(projectRoot, RUNTIME_ROOT, "contexts", `${mode}.md`);
|
|
1324
|
-
checks.push({
|
|
1325
|
-
name: `contexts:mode:${mode}`,
|
|
1326
|
-
ok: await exists(modePath),
|
|
1327
|
-
details: modePath
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
1266
|
await ensureFeatureSystem(projectRoot, { repair: false });
|
|
1331
1267
|
const activeFeature = await readActiveFeature(projectRoot, { repair: false });
|
|
1332
1268
|
let flowState = createInitialFlowState();
|
package/dist/install.js
CHANGED
|
@@ -5,7 +5,7 @@ import { promisify } from "node:util";
|
|
|
5
5
|
import { CCLAW_VERSION, FLOW_VERSION, REQUIRED_DIRS, RUNTIME_ROOT } from "./constants.js";
|
|
6
6
|
import { writeConfig, createDefaultConfig, readConfig, configPath, detectLanguageRulePacks, detectAdvancedKeys } from "./config.js";
|
|
7
7
|
import { stageCommandContract } from "./content/contracts.js";
|
|
8
|
-
import {
|
|
8
|
+
import { createInitialContextModeState } from "./content/contexts.js";
|
|
9
9
|
import { learnSkillMarkdown, learnCommandContract } from "./content/learnings.js";
|
|
10
10
|
import { nextCommandContract, nextCommandSkillMarkdown } from "./content/next-command.js";
|
|
11
11
|
import { ideateCommandContract, ideateCommandSkillMarkdown } from "./content/ideate-command.js";
|
|
@@ -799,151 +799,6 @@ async function ensureKnowledgeStore(projectRoot) {
|
|
|
799
799
|
await fs.rm(legacyMdPath, { force: true });
|
|
800
800
|
}
|
|
801
801
|
}
|
|
802
|
-
async function ensureCustomSkillsScaffold(projectRoot) {
|
|
803
|
-
const customDir = runtimePath(projectRoot, "custom-skills");
|
|
804
|
-
await ensureDir(customDir);
|
|
805
|
-
const readmePath = path.join(customDir, "README.md");
|
|
806
|
-
if (!(await exists(readmePath))) {
|
|
807
|
-
await writeFileSafe(readmePath, CUSTOM_SKILLS_README);
|
|
808
|
-
}
|
|
809
|
-
const examplePath = path.join(customDir, "example", "SKILL.md");
|
|
810
|
-
if (!(await exists(examplePath))) {
|
|
811
|
-
await writeFileSafe(examplePath, CUSTOM_SKILLS_EXAMPLE);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
const CUSTOM_SKILLS_README = `# Custom Skills (sync-safe)
|
|
815
|
-
|
|
816
|
-
This directory is **never overwritten** by \`cclaw sync\` or \`cclaw upgrade\`. Use it
|
|
817
|
-
to add project-specific skills that complement the managed skills under
|
|
818
|
-
\`.cclaw/skills/\`.
|
|
819
|
-
|
|
820
|
-
## When to add a custom skill
|
|
821
|
-
|
|
822
|
-
- A repeatable lens specific to **this project** (e.g. "billing-domain", "kafka-message-contracts").
|
|
823
|
-
- A team convention you want every agent session to load.
|
|
824
|
-
- A domain checklist that does not generalize to other projects.
|
|
825
|
-
|
|
826
|
-
If the skill is general (security, performance, accessibility, etc.) prefer
|
|
827
|
-
contributing it upstream instead — the managed skills receive maintenance.
|
|
828
|
-
|
|
829
|
-
## File format — public API (stable contract)
|
|
830
|
-
|
|
831
|
-
Each skill lives at \`.cclaw/custom-skills/<folder>/SKILL.md\`. The format is a
|
|
832
|
-
**stable public API**: \`cclaw sync\` and \`cclaw upgrade\` will not rewrite
|
|
833
|
-
custom skills, and the fields below are guaranteed to be respected by the
|
|
834
|
-
meta-skill router and the stage hooks.
|
|
835
|
-
|
|
836
|
-
### Frontmatter (YAML, required)
|
|
837
|
-
|
|
838
|
-
\`\`\`yaml
|
|
839
|
-
---
|
|
840
|
-
# Required fields
|
|
841
|
-
name: <kebab-case-skill-name>
|
|
842
|
-
description: >
|
|
843
|
-
One sentence (≤180 chars) that triggers semantic routing. Include the
|
|
844
|
-
concrete situation and the expected action
|
|
845
|
-
(e.g. "Audit Kafka topic contracts when a producer or consumer signature changes").
|
|
846
|
-
|
|
847
|
-
# Optional fields (omit when not applicable)
|
|
848
|
-
stages: [design, spec, tdd, review] # flow stages this skill applies to
|
|
849
|
-
triggers:
|
|
850
|
-
- "kafka topic"
|
|
851
|
-
- "producer.schema"
|
|
852
|
-
- "consumer.schema"
|
|
853
|
-
hardGate: false # true => skill body MUST include a ## HARD-GATE section
|
|
854
|
-
owners: ["@team-messaging"] # informational routing hint, not enforced
|
|
855
|
-
version: 0.1.0 # semver; bump when hardGate or algorithm changes
|
|
856
|
-
---
|
|
857
|
-
\`\`\`
|
|
858
|
-
|
|
859
|
-
### Field contract
|
|
860
|
-
|
|
861
|
-
| Field | Type | Required | Meaning |
|
|
862
|
-
|---|---|---|---|
|
|
863
|
-
| \`name\` | string (kebab-case) | yes | Unique id used by the router and by \`/cc-view status\` diagnostics. |
|
|
864
|
-
| \`description\` | string ≤180 chars (single line OR YAML \`>\` folded) | yes | Drives semantic routing. Include trigger + action. |
|
|
865
|
-
| \`stages\` | array of flow stages | no | When present, the meta-skill only surfaces this skill during those stages. Omit for "any stage". |
|
|
866
|
-
| \`triggers\` | array of strings | no | Extra literal substrings that route to this skill when found in the user prompt or the active artifact. |
|
|
867
|
-
| \`hardGate\` | boolean | no | When \`true\`, the body MUST include a \`## HARD-GATE\` section; the agent treats the rule as non-skippable. |
|
|
868
|
-
| \`owners\` | array of strings | no | Informational only — surfaced to the user, never enforced. |
|
|
869
|
-
| \`version\` | semver string | no | Bump when you change the HARD-GATE or algorithm so reviewers can spot changes. |
|
|
870
|
-
|
|
871
|
-
### Body sections (markdown, recommended order)
|
|
872
|
-
|
|
873
|
-
\`\`\`markdown
|
|
874
|
-
# <Skill title>
|
|
875
|
-
|
|
876
|
-
## Overview
|
|
877
|
-
One-paragraph summary; context for when this skill is loaded.
|
|
878
|
-
|
|
879
|
-
## When to use
|
|
880
|
-
- Bullet list of situations where this skill adds value.
|
|
881
|
-
|
|
882
|
-
## When NOT to use
|
|
883
|
-
- Situations where loading this skill is context bloat or wrong.
|
|
884
|
-
|
|
885
|
-
## HARD-GATE (REQUIRED when frontmatter hardGate: true)
|
|
886
|
-
Phrase it as a refusal:
|
|
887
|
-
> Do not <X> while <Y>.
|
|
888
|
-
|
|
889
|
-
## Algorithm / checklist
|
|
890
|
-
1. Concrete, observable steps with evidence (file:line, artifact, or knowledge entry).
|
|
891
|
-
|
|
892
|
-
## Output protocol
|
|
893
|
-
Where the artifact / chat output lives and what shape it takes.
|
|
894
|
-
|
|
895
|
-
## Anti-patterns
|
|
896
|
-
- Common failure modes to reject.
|
|
897
|
-
\`\`\`
|
|
898
|
-
|
|
899
|
-
### Stage association semantics
|
|
900
|
-
|
|
901
|
-
- \`stages: []\` or missing → skill is available at any stage. The meta-skill still only surfaces it when \`description\` or \`triggers\` match the prompt.
|
|
902
|
-
- \`stages: [review]\` → skill is offered only during the review stage.
|
|
903
|
-
- Custom skills **never** become mandatory delegations. They are opt-in lenses. If you need a mandatory dispatch, add a proper managed specialist under \`.cclaw/skills/\` instead.
|
|
904
|
-
|
|
905
|
-
## Routing
|
|
906
|
-
|
|
907
|
-
Custom skills are surfaced via the \`using-cclaw\` meta-skill at session start.
|
|
908
|
-
Mention the skill name in your prompt or let the agent semantic-route to it
|
|
909
|
-
based on the description + triggers + stages frontmatter.
|
|
910
|
-
|
|
911
|
-
## Versioning & removal
|
|
912
|
-
|
|
913
|
-
Custom skills are user-owned. Bump \`version\` when you change the HARD-GATE or
|
|
914
|
-
algorithm; delete or edit them at any time — \`cclaw sync\` will not touch them.
|
|
915
|
-
`;
|
|
916
|
-
const CUSTOM_SKILLS_EXAMPLE = `---
|
|
917
|
-
name: example-custom-skill
|
|
918
|
-
description: "Replace this with a one-sentence description that triggers when the skill should be used. Delete or rename this folder when you add a real skill."
|
|
919
|
-
---
|
|
920
|
-
|
|
921
|
-
# Example Custom Skill
|
|
922
|
-
|
|
923
|
-
This is a placeholder. Use it as a starting template, then delete or rename
|
|
924
|
-
the \`example/\` folder.
|
|
925
|
-
|
|
926
|
-
## When to use
|
|
927
|
-
|
|
928
|
-
- A real, repeatable situation in **this** project that needs a consistent lens.
|
|
929
|
-
|
|
930
|
-
## HARD-GATE (optional)
|
|
931
|
-
|
|
932
|
-
Drop this section if no hard rule applies. Keep it crisp:
|
|
933
|
-
|
|
934
|
-
> Do not <X> while <Y>.
|
|
935
|
-
|
|
936
|
-
## Algorithm
|
|
937
|
-
|
|
938
|
-
1. Step one — observable, file:line evidence required.
|
|
939
|
-
2. Step two — produce a named artifact, not a vibe.
|
|
940
|
-
3. Step three — escalate / hand off / record knowledge entry.
|
|
941
|
-
|
|
942
|
-
## Anti-patterns
|
|
943
|
-
|
|
944
|
-
- Treating this skill as advisory when the situation matches the trigger.
|
|
945
|
-
- Loading this skill when the situation clearly does not match (context bloat).
|
|
946
|
-
`;
|
|
947
802
|
async function ensureSessionStateFiles(projectRoot) {
|
|
948
803
|
const stateDir = runtimePath(projectRoot, "state");
|
|
949
804
|
await ensureDir(stateDir);
|
|
@@ -1020,11 +875,6 @@ async function writeRulebook(projectRoot) {
|
|
|
1020
875
|
await writeFileSafe(runtimePath(projectRoot, "rules", "RULES.md"), RULEBOOK_MARKDOWN);
|
|
1021
876
|
await writeFileSafe(runtimePath(projectRoot, "rules", "rules.json"), `${JSON.stringify(buildRulesJson(), null, 2)}\n`);
|
|
1022
877
|
}
|
|
1023
|
-
async function writeContextModes(projectRoot) {
|
|
1024
|
-
for (const [mode, content] of Object.entries(contextModeFiles())) {
|
|
1025
|
-
await writeFileSafe(runtimePath(projectRoot, "contexts", `${mode}.md`), content);
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
878
|
async function writeCursorWorkflowRule(projectRoot, harnesses) {
|
|
1029
879
|
const rulePath = path.join(projectRoot, CURSOR_RULE_REL_PATH);
|
|
1030
880
|
if (!harnesses.includes("cursor")) {
|
|
@@ -1073,15 +923,6 @@ async function writeState(projectRoot, config, forceReset = false) {
|
|
|
1073
923
|
const state = createInitialFlowState({ track: config.defaultTrack ?? "standard" });
|
|
1074
924
|
await writeFileSafe(statePath, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
|
|
1075
925
|
}
|
|
1076
|
-
async function writeAdapterManifest(projectRoot, harnesses) {
|
|
1077
|
-
const manifest = {
|
|
1078
|
-
generatedAt: new Date().toISOString(),
|
|
1079
|
-
harnesses,
|
|
1080
|
-
commandSource: `${RUNTIME_ROOT}/commands/*.md`,
|
|
1081
|
-
skillSource: `${RUNTIME_ROOT}/skills/*/SKILL.md`
|
|
1082
|
-
};
|
|
1083
|
-
await writeFileSafe(runtimePath(projectRoot, "adapters", "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
1084
|
-
}
|
|
1085
926
|
async function writeHarnessGapsState(projectRoot, harnesses) {
|
|
1086
927
|
const report = harnesses.map((harness) => {
|
|
1087
928
|
const capabilities = HARNESS_ADAPTERS[harness].capabilities;
|
|
@@ -1304,7 +1145,6 @@ async function materializeRuntime(projectRoot, config, forceStateReset) {
|
|
|
1304
1145
|
writeCommandContracts(projectRoot, config.defaultTrack ?? "standard"),
|
|
1305
1146
|
writeUtilityCommands(projectRoot, config),
|
|
1306
1147
|
writeSkills(projectRoot, config),
|
|
1307
|
-
writeContextModes(projectRoot),
|
|
1308
1148
|
writeArtifactTemplates(projectRoot),
|
|
1309
1149
|
writeEvalScaffold(projectRoot),
|
|
1310
1150
|
writeRulebook(projectRoot)
|
|
@@ -1312,10 +1152,8 @@ async function materializeRuntime(projectRoot, config, forceStateReset) {
|
|
|
1312
1152
|
await writeState(projectRoot, config, forceStateReset);
|
|
1313
1153
|
await ensureRunSystem(projectRoot, { createIfMissing: false });
|
|
1314
1154
|
await ensureSessionStateFiles(projectRoot);
|
|
1315
|
-
await writeAdapterManifest(projectRoot, harnesses);
|
|
1316
1155
|
await writeHarnessGapsState(projectRoot, harnesses);
|
|
1317
1156
|
await ensureKnowledgeStore(projectRoot);
|
|
1318
|
-
await ensureCustomSkillsScaffold(projectRoot);
|
|
1319
1157
|
await writeHooks(projectRoot, config);
|
|
1320
1158
|
await syncDisabledHarnessArtifacts(projectRoot, harnesses);
|
|
1321
1159
|
await syncManagedGitHooks(projectRoot, config);
|
package/dist/policy.js
CHANGED
|
@@ -181,10 +181,6 @@ export async function policyChecks(projectRoot, options = {}) {
|
|
|
181
181
|
{ file: runtimeFile("skills/frontend-accessibility/SKILL.md"), needle: "## HARD-GATE", name: "utility_skill:frontend_accessibility:hard_gate" },
|
|
182
182
|
{ file: runtimeFile("skills/frontend-accessibility/SKILL.md"), needle: "## Checklist", name: "utility_skill:frontend_accessibility:checklist" },
|
|
183
183
|
{ file: runtimeFile("skills/frontend-accessibility/SKILL.md"), needle: "## Anti-Patterns", name: "utility_skill:frontend_accessibility:anti_patterns" },
|
|
184
|
-
{ file: runtimeFile("contexts/default.md"), needle: "Context Mode: default", name: "context_mode:default" },
|
|
185
|
-
{ file: runtimeFile("contexts/execution.md"), needle: "Context Mode: execution", name: "context_mode:execution" },
|
|
186
|
-
{ file: runtimeFile("contexts/review.md"), needle: "Context Mode: review", name: "context_mode:review" },
|
|
187
|
-
{ file: runtimeFile("contexts/incident.md"), needle: "Context Mode: incident", name: "context_mode:incident" },
|
|
188
184
|
{ file: runtimeFile("hooks/run-hook.mjs"), needle: "activeRunId", name: "hooks:session_start:active_run" },
|
|
189
185
|
{ file: runtimeFile("hooks/run-hook.mjs"), needle: "checkpoint.json", name: "hooks:session_start:checkpoint_ref" },
|
|
190
186
|
{ file: runtimeFile("hooks/run-hook.mjs"), needle: "stage-activity.jsonl", name: "hooks:session_start:activity_ref" },
|