@dtmd/temper 0.0.4 → 0.0.6
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 +10 -12
- package/dist/src/assembly.d.ts +32 -16
- package/dist/src/assembly.js +11 -10
- package/dist/src/builtins.d.ts +104 -40
- package/dist/src/builtins.js +130 -53
- package/dist/src/claude-code.d.ts +7 -9
- package/dist/src/claude-code.js +6 -8
- package/dist/src/contract.d.ts +47 -24
- package/dist/src/contract.js +35 -9
- package/dist/src/declarations.d.ts +25 -103
- package/dist/src/declarations.js +311 -47
- package/dist/src/emit.d.ts +13 -32
- package/dist/src/emit.js +136 -53
- package/dist/src/generated/AssemblyFactRow.d.ts +29 -0
- package/dist/src/generated/AssemblyFactRow.js +2 -0
- package/dist/src/generated/BoundRow.d.ts +14 -0
- package/dist/src/generated/BoundRow.js +2 -0
- package/dist/src/generated/CharsetRow.d.ts +15 -0
- package/dist/src/generated/CharsetRow.js +2 -0
- package/dist/src/generated/ClauseRow.d.ts +97 -0
- package/dist/src/generated/ClauseRow.js +1 -0
- package/dist/src/generated/CollectionEntryRow.d.ts +23 -0
- package/dist/src/generated/CollectionEntryRow.js +2 -0
- package/dist/src/generated/CollectionEntryWire.d.ts +17 -0
- package/dist/src/generated/CollectionEntryWire.js +2 -0
- package/dist/src/generated/CountBoundRow.d.ts +13 -0
- package/dist/src/generated/CountBoundRow.js +2 -0
- package/dist/src/generated/Declarations.d.ts +72 -0
- package/dist/src/generated/Declarations.js +1 -0
- package/dist/src/generated/DegreeBoundRow.d.ts +15 -0
- package/dist/src/generated/DegreeBoundRow.js +1 -0
- package/dist/src/generated/EdgeBoundRow.d.ts +13 -0
- package/dist/src/generated/EdgeBoundRow.js +2 -0
- package/dist/src/generated/EmbeddedMember.d.ts +45 -0
- package/dist/src/generated/EmbeddedMember.js +1 -0
- package/dist/src/generated/EmbeddedMemberCollectionEntry.d.ts +21 -0
- package/dist/src/generated/EmbeddedMemberCollectionEntry.js +1 -0
- package/dist/src/generated/FeatureValue.d.ts +23 -0
- package/dist/src/generated/FeatureValue.js +1 -0
- package/dist/src/generated/Features.d.ts +82 -0
- package/dist/src/generated/Features.js +1 -0
- package/dist/src/generated/FencedBlock.d.ts +24 -0
- package/dist/src/generated/FencedBlock.js +2 -0
- package/dist/src/generated/IncludeRow.d.ts +18 -0
- package/dist/src/generated/IncludeRow.js +2 -0
- package/dist/src/generated/KindFactRow.d.ts +51 -0
- package/dist/src/generated/KindFactRow.js +1 -0
- package/dist/src/generated/LayoutRegionRow.d.ts +29 -0
- package/dist/src/generated/LayoutRegionRow.js +2 -0
- package/dist/src/generated/LayoutRow.d.ts +12 -0
- package/dist/src/generated/LayoutRow.js +1 -0
- package/dist/src/generated/MentionRow.d.ts +17 -0
- package/dist/src/generated/MentionRow.js +2 -0
- package/dist/src/generated/NestedMemberRow.d.ts +39 -0
- package/dist/src/generated/NestedMemberRow.js +1 -0
- package/dist/src/generated/Payload.d.ts +25 -0
- package/dist/src/generated/Payload.js +1 -0
- package/dist/src/generated/PayloadMember.d.ts +31 -0
- package/dist/src/generated/PayloadMember.js +2 -0
- package/dist/src/generated/RangeBoundRow.d.ts +15 -0
- package/dist/src/generated/RangeBoundRow.js +2 -0
- package/dist/src/generated/RequirementRow.d.ts +40 -0
- package/dist/src/generated/RequirementRow.js +1 -0
- package/dist/src/generated/SatisfiesRow.d.ts +14 -0
- package/dist/src/generated/SatisfiesRow.js +2 -0
- package/dist/src/generated/Section.d.ts +21 -0
- package/dist/src/generated/Section.js +2 -0
- package/dist/src/generated/SectionContainsRow.d.ts +14 -0
- package/dist/src/generated/SectionContainsRow.js +2 -0
- package/dist/src/generated/ValueType.d.ts +9 -0
- package/dist/src/generated/ValueType.js +2 -0
- package/dist/src/generated/index.d.ts +29 -0
- package/dist/src/generated/index.js +1 -0
- package/dist/src/index.d.ts +14 -18
- package/dist/src/index.js +10 -13
- package/dist/src/kind.d.ts +163 -41
- package/dist/src/kind.js +24 -24
- package/dist/src/needs.d.ts +8 -8
- package/dist/src/needs.js +7 -7
- package/dist/src/prose.d.ts +75 -28
- package/dist/src/prose.js +0 -0
- package/package.json +1 -1
- package/dist/src/genres.d.ts +0 -38
- package/dist/src/genres.js +0 -24
package/dist/src/builtins.js
CHANGED
|
@@ -1,28 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The built-in Claude Code kinds — the face nouns a harness author imports
|
|
3
|
-
*
|
|
2
|
+
* The built-in Claude Code kinds — the face nouns a harness author imports.
|
|
3
|
+
* Each is an
|
|
4
4
|
* ordinary `kind<T>()` value built with the same constructor every provider uses
|
|
5
5
|
* (ownership not privilege). Their five facts are external facts about the Claude
|
|
6
6
|
* Code harness, cited at the point of claim.
|
|
7
7
|
*
|
|
8
8
|
* These are the SDK's own provider-face exports, surfaced through the
|
|
9
|
-
* `@dtmd/temper/claude-code` subpath
|
|
10
|
-
*
|
|
9
|
+
* `@dtmd/temper/claude-code` subpath
|
|
10
|
+
* — never from the root.
|
|
11
11
|
*/
|
|
12
12
|
import { kind } from "./kind.js";
|
|
13
|
-
import { allowedChars, clause, deny, forbiddenKeys, maxLen, maxLines, minLen, nameMatchesDir, required, } from "./contract.js";
|
|
13
|
+
import { allowedChars, clause, deny, forbiddenKeys, maxLen, maxLines, minLen, nameMatchesDir, required, uniqueName, } from "./contract.js";
|
|
14
14
|
/**
|
|
15
15
|
* `skill` — `.claude/skills/<name>/SKILL.md`, a directory unit, YAML frontmatter
|
|
16
|
-
* carrying `name` then `description`; registers
|
|
16
|
+
* carrying `name` then `description`; registers on both documented invocation
|
|
17
|
+
* channels — user-invoked (`/name`) and description-trigger — modulated per
|
|
18
|
+
* member by the `disable-model-invocation`/`user-invocable` fields
|
|
17
19
|
* (code.claude.com/docs/en/skills, agentskills.io/specification, retrieved
|
|
18
|
-
* 2026-07-
|
|
20
|
+
* 2026-07-07).
|
|
19
21
|
*/
|
|
20
22
|
export const skill = kind({
|
|
21
23
|
name: "skill",
|
|
22
24
|
locus: { kind: "at", root: ".claude/skills", glob: "*/SKILL.md" },
|
|
23
25
|
format: "yaml-frontmatter",
|
|
24
26
|
unitShape: "directory",
|
|
25
|
-
registration: { via: "description-trigger", field: "description" },
|
|
27
|
+
registration: [{ via: "user-invoked" }, { via: "description-trigger", field: "description" }],
|
|
28
|
+
identityField: "name",
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* `command` — `.claude/commands/*.md`, the skill surface's legacy file placement
|
|
32
|
+
* (Claude Code merged commands into skills; code.claude.com/docs/en/skills,
|
|
33
|
+
* retrieved 2026-07-07): a lone file (identity from the stem, so no
|
|
34
|
+
* `identityField` — like `rule`), the skill's field schema by import, registering
|
|
35
|
+
* on the same two documented invocation channels as `skill`.
|
|
36
|
+
*/
|
|
37
|
+
export const command = kind({
|
|
38
|
+
name: "command",
|
|
39
|
+
locus: { kind: "at", root: ".claude/commands", glob: "*.md" },
|
|
40
|
+
format: "yaml-frontmatter",
|
|
41
|
+
unitShape: "file",
|
|
42
|
+
registration: [{ via: "user-invoked" }, { via: "description-trigger", field: "description" }],
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* `agent` — every markdown file under `.claude/agents`, discovered recursively (a
|
|
46
|
+
* containing subdirectory is purely organizational), YAML frontmatter carrying
|
|
47
|
+
* `name` then `description`; identity is the `name` field (never the filename),
|
|
48
|
+
* the named-field mode; registers on the description-trigger channel only — no
|
|
49
|
+
* user-invoked slash command (code.claude.com/docs/en/sub-agents, retrieved
|
|
50
|
+
* 2026-07-07).
|
|
51
|
+
*/
|
|
52
|
+
export const agent = kind({
|
|
53
|
+
name: "agent",
|
|
54
|
+
locus: { kind: "at", root: ".claude/agents", glob: "**/*.md" },
|
|
55
|
+
format: "yaml-frontmatter",
|
|
56
|
+
unitShape: "named-field",
|
|
57
|
+
registration: [{ via: "description-trigger", field: "description" }],
|
|
26
58
|
identityField: "name",
|
|
27
59
|
});
|
|
28
60
|
/**
|
|
@@ -35,7 +67,7 @@ export const rule = kind({
|
|
|
35
67
|
locus: { kind: "at", root: ".claude/rules", glob: "*.md" },
|
|
36
68
|
format: "yaml-frontmatter",
|
|
37
69
|
unitShape: "file",
|
|
38
|
-
registration: { via: "paths-match", field: "paths" },
|
|
70
|
+
registration: [{ via: "paths-match", field: "paths" }],
|
|
39
71
|
});
|
|
40
72
|
/**
|
|
41
73
|
* `memory` — a root `<name>.md` (`CLAUDE.md`, `AGENTS.md`), a lone file loaded
|
|
@@ -48,14 +80,13 @@ export const memory = kind({
|
|
|
48
80
|
name: "memory",
|
|
49
81
|
locus: { kind: "at", root: ".", glob: "**/CLAUDE.md" },
|
|
50
82
|
unitShape: "file",
|
|
51
|
-
registration: { via: "always" },
|
|
83
|
+
registration: [{ via: "always" }],
|
|
52
84
|
});
|
|
53
85
|
/**
|
|
54
|
-
* The
|
|
86
|
+
* The default contract for `skill` — Anthropic's documented skill contract: the Agent
|
|
55
87
|
* Skills open standard (agentskills.io), Anthropic's platform upload
|
|
56
|
-
* validation, and Claude Code's own docs
|
|
57
|
-
*
|
|
58
|
-
* "named for its source"). All sources retrieved 2026-07-01.
|
|
88
|
+
* validation, and Claude Code's own docs.
|
|
89
|
+
* All sources retrieved 2026-07-09.
|
|
59
90
|
*
|
|
60
91
|
* Checks the strictest documented profile: the spec and upload validation are
|
|
61
92
|
* hard, Claude Code's runtime is deliberately forgiving ("All fields are
|
|
@@ -67,7 +98,7 @@ export const memory = kind({
|
|
|
67
98
|
* description actually triggers well or reads third-person (semantic);
|
|
68
99
|
* vagueness/no-op detection (semantic); gerund naming (judgment). Two
|
|
69
100
|
* decidable spec rules are also absent, pending a vocabulary addition (a
|
|
70
|
-
* narrow shape predicate
|
|
101
|
+
* narrow shape predicate governs additions): the name
|
|
71
102
|
* must not start/end with a hyphen or contain consecutive hyphens; likewise
|
|
72
103
|
* the platform's "no XML tags in the description."
|
|
73
104
|
*
|
|
@@ -78,73 +109,116 @@ export const memory = kind({
|
|
|
78
109
|
* that is not a command; `metadata` is the sanctioned home for versioning —
|
|
79
110
|
* there is no top-level `version` field.
|
|
80
111
|
*/
|
|
81
|
-
export const
|
|
112
|
+
export const skillDefaultContract = [
|
|
82
113
|
clause(required("name"), {
|
|
83
114
|
severity: "required",
|
|
84
115
|
guidance: "Every skill declares a `name` — the slug the harness binds to. Claude Code alone would default it from the directory name, but a nameless skill is not portable: the spec and Anthropic's upload validation both require it.",
|
|
85
|
-
cite: "https://agentskills.io/specification#frontmatter (retrieved 2026-07-
|
|
116
|
+
cite: "https://agentskills.io/specification#frontmatter (retrieved 2026-07-09)",
|
|
86
117
|
}),
|
|
87
118
|
clause(minLen("name", 1), {
|
|
88
119
|
severity: "required",
|
|
89
120
|
guidance: "A present-but-empty name fails the spec's 1-64 character bound.",
|
|
90
|
-
cite: "https://agentskills.io/specification#name-field (retrieved 2026-07-
|
|
121
|
+
cite: "https://agentskills.io/specification#name-field (retrieved 2026-07-09)",
|
|
91
122
|
}),
|
|
92
123
|
clause(allowedChars("name", { ranges: ["a-z", "0-9"], chars: "-" }), {
|
|
93
124
|
severity: "required",
|
|
94
125
|
guidance: "Lowercase letters, digits, and hyphens only — `PDF-Processing` is the spec's own counter-example. The charset also keeps XML out of the name, which Anthropic's upload validation separately forbids.",
|
|
95
|
-
cite: "https://agentskills.io/specification#name-field (retrieved 2026-07-
|
|
126
|
+
cite: "https://agentskills.io/specification#name-field (retrieved 2026-07-09)",
|
|
96
127
|
}),
|
|
97
128
|
clause(maxLen("name", 64), {
|
|
98
129
|
severity: "required",
|
|
99
130
|
guidance: "Keep the name short and slug-like; it becomes a directory and an id.",
|
|
100
|
-
cite: "https://agentskills.io/specification#name-field (retrieved 2026-07-
|
|
131
|
+
cite: "https://agentskills.io/specification#name-field (retrieved 2026-07-09)",
|
|
101
132
|
}),
|
|
102
133
|
clause(deny("name", ["anthropic", "claude"]), {
|
|
103
134
|
severity: "required",
|
|
104
135
|
guidance: "Reserved words, enforced by Anthropic's platform upload validation (not by the open spec, and not by Claude Code's runtime — which itself ships a `claude-api` skill). Keep them out if the skill will ever travel through the API or claude.ai.",
|
|
105
|
-
cite: "https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview#skill-structure (retrieved 2026-07-
|
|
136
|
+
cite: "https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview#skill-structure (retrieved 2026-07-09)",
|
|
106
137
|
}),
|
|
107
138
|
clause(nameMatchesDir(), {
|
|
108
139
|
severity: "required",
|
|
109
140
|
guidance: "The spec requires the name to match its parent directory. Claude Code decouples the two (the frontmatter name is a display label; the directory names the slash command, except for a plugin-root SKILL.md) — but a mismatch is a portability trap and a reader trap even where it loads.",
|
|
110
|
-
cite: "https://agentskills.io/specification#name-field (retrieved 2026-07-
|
|
141
|
+
cite: "https://agentskills.io/specification#name-field (retrieved 2026-07-09)",
|
|
111
142
|
}),
|
|
112
143
|
clause(required("description"), {
|
|
113
144
|
severity: "required",
|
|
114
145
|
guidance: "The description is how the model chooses this skill from potentially 100+ available — it is the skill's API. Claude Code would fall back to the body's first paragraph; the spec and upload validation require it declared.",
|
|
115
|
-
cite: "https://agentskills.io/specification#frontmatter (retrieved 2026-07-
|
|
146
|
+
cite: "https://agentskills.io/specification#frontmatter (retrieved 2026-07-09)",
|
|
116
147
|
}),
|
|
117
148
|
clause(minLen("description", 1), {
|
|
118
149
|
severity: "required",
|
|
119
150
|
guidance: "Say both what the skill does and when to use it, with the keywords a user would naturally say. Write in third person — the text is injected into the system prompt, and inconsistent point-of-view causes discovery problems.",
|
|
120
|
-
cite: "https://agentskills.io/specification#description-field (retrieved 2026-07-
|
|
151
|
+
cite: "https://agentskills.io/specification#description-field (retrieved 2026-07-09)",
|
|
121
152
|
}),
|
|
122
153
|
clause(maxLen("description", 1024), {
|
|
123
154
|
severity: "required",
|
|
124
155
|
guidance: "The spec's cap. Claude Code additionally truncates the skill listing at 1,536 combined characters (description + when_to_use) — truncation, not rejection, but text past the fold cannot help the model choose.",
|
|
125
|
-
cite: "https://agentskills.io/specification#description-field (retrieved 2026-07-
|
|
156
|
+
cite: "https://agentskills.io/specification#description-field (retrieved 2026-07-09)",
|
|
126
157
|
}),
|
|
127
158
|
clause(maxLen("compatibility", 500), {
|
|
128
159
|
severity: "required",
|
|
129
160
|
guidance: "Optional field; when present the spec caps it at 500 characters. Most skills do not need it.",
|
|
130
|
-
cite: "https://agentskills.io/specification#frontmatter (retrieved 2026-07-
|
|
161
|
+
cite: "https://agentskills.io/specification#frontmatter (retrieved 2026-07-09)",
|
|
131
162
|
}),
|
|
132
163
|
clause(maxLines(500), {
|
|
133
164
|
severity: "advisory",
|
|
134
165
|
guidance: "Progressive disclosure: keep SKILL.md under 500 lines and move detailed reference material to separate files, one level deep. Once a skill loads, its body stays in context across turns — every line is a recurring token cost. The context window is a public good.",
|
|
135
|
-
cite: "https://agentskills.io/specification#progressive-disclosure (retrieved 2026-07-
|
|
166
|
+
cite: "https://agentskills.io/specification#progressive-disclosure (retrieved 2026-07-09)",
|
|
136
167
|
}),
|
|
137
168
|
clause(forbiddenKeys(["globs", "alwaysApply"]), {
|
|
138
169
|
severity: "required",
|
|
139
170
|
guidance: "Cursor `.mdc` keys. Nothing in the Agent Skills spec or Claude Code's documented frontmatter accepts them — a skill authored with them is carrying dead configuration that another tool's semantics silently fail to apply.",
|
|
140
|
-
cite: "https://agentskills.io/specification#frontmatter (retrieved 2026-07-
|
|
171
|
+
cite: "https://agentskills.io/specification#frontmatter (retrieved 2026-07-09)",
|
|
172
|
+
}),
|
|
173
|
+
];
|
|
174
|
+
/**
|
|
175
|
+
* The default contract for `command` — `skillDefaultContract`'s clauses minus `nameMatchesDir`: a
|
|
176
|
+
* command is a lone file with no parent directory to match, so the one clause
|
|
177
|
+
* that ranges over the directory relationship does not apply; every other
|
|
178
|
+
* documented skill-schema recommendation, name-requiredness included, still
|
|
179
|
+
* governs a command by the same import (code.claude.com/docs/en/skills,
|
|
180
|
+
* retrieved 2026-07-07).
|
|
181
|
+
*/
|
|
182
|
+
export const commandDefaultContract = skillDefaultContract.filter((entry) => entry.predicate.key !== "name-matches-dir");
|
|
183
|
+
/**
|
|
184
|
+
* The default contract for `agent` — Anthropic's documented subagent contract
|
|
185
|
+
* (code.claude.com/docs/en/sub-agents, retrieved 2026-07-07): `name` and
|
|
186
|
+
* `description` are the only required fields, `name` is a "unique identifier
|
|
187
|
+
* using lowercase letters and hyphens" (no digits, unlike a skill's `name`), and
|
|
188
|
+
* "keep `name` values unique across the whole tree" — a same-scope collision
|
|
189
|
+
* loads only one definition.
|
|
190
|
+
*
|
|
191
|
+
* Deliberately narrow, like `ruleDefaultContract`: undecidable properties (whether the
|
|
192
|
+
* description triggers well, model/permissionMode's semi-open vocabularies) stay
|
|
193
|
+
* out of the gate — the format documents little else that is decidable.
|
|
194
|
+
*/
|
|
195
|
+
export const agentDefaultContract = [
|
|
196
|
+
clause(required("name"), {
|
|
197
|
+
severity: "required",
|
|
198
|
+
guidance: "Every subagent declares a `name` — its unique identifier. Claude Code binds identity to this field alone, never the filename, so a nameless subagent cannot be delegated to.",
|
|
199
|
+
cite: "https://code.claude.com/docs/en/sub-agents (retrieved 2026-07-07)",
|
|
200
|
+
}),
|
|
201
|
+
clause(allowedChars("name", { ranges: ["a-z"], chars: "-" }), {
|
|
202
|
+
severity: "required",
|
|
203
|
+
guidance: "Lowercase letters and hyphens only — no digits, unlike a skill's `[a-z0-9-]` name. Hooks receive this value as `agent_type`.",
|
|
204
|
+
cite: "https://code.claude.com/docs/en/sub-agents (retrieved 2026-07-07)",
|
|
205
|
+
}),
|
|
206
|
+
clause(uniqueName(), {
|
|
207
|
+
severity: "required",
|
|
208
|
+
guidance: "Keep `name` values unique across the whole tree — when two files in one scope declare the same name, Claude Code loads only one of them, silently shadowing the other.",
|
|
209
|
+
cite: "https://code.claude.com/docs/en/sub-agents (retrieved 2026-07-07)",
|
|
210
|
+
}),
|
|
211
|
+
clause(required("description"), {
|
|
212
|
+
severity: "required",
|
|
213
|
+
guidance: "The description is how Claude decides when to delegate to this subagent — write it so the trigger is unambiguous.",
|
|
214
|
+
cite: "https://code.claude.com/docs/en/sub-agents (retrieved 2026-07-07)",
|
|
141
215
|
}),
|
|
142
216
|
];
|
|
143
217
|
/**
|
|
144
|
-
* The
|
|
218
|
+
* The default contract for `rule` — Anthropic's documented contract for a Claude Code
|
|
145
219
|
* rules file, sourced from the memory docs (`.claude/rules/` landed in
|
|
146
220
|
* v2.0.64; `packages/rule.anthropic/PACKAGE.md`, the curated authoring
|
|
147
|
-
* reference this migrates verbatim). All sources retrieved 2026-07-
|
|
221
|
+
* reference this migrates verbatim). All sources retrieved 2026-07-09.
|
|
148
222
|
*
|
|
149
223
|
* `paths` is the one documented frontmatter key for rules: glob patterns
|
|
150
224
|
* (brace expansion supported) that scope the rule to matching files. Rules
|
|
@@ -152,9 +226,9 @@ export const skillFloor = [
|
|
|
152
226
|
* rules load when Claude reads a matching file. Note skills now take a
|
|
153
227
|
* `paths` key too — the two schemas are separate. (Guidance only: an
|
|
154
228
|
* optional field asserts nothing decidable, so it carries no clause of its
|
|
155
|
-
* own
|
|
229
|
+
* own: `required` is the one
|
|
156
230
|
* presence predicate, and its absence is not itself a predicate.)
|
|
157
|
-
* https://code.claude.com/docs/en/memory#path-specific-rules (retrieved 2026-07-
|
|
231
|
+
* https://code.claude.com/docs/en/memory#path-specific-rules (retrieved 2026-07-09)
|
|
158
232
|
*
|
|
159
233
|
* What the clauses cannot carry, as guidance: keep a rule to facts Claude
|
|
160
234
|
* should hold whenever the rule is in scope — concrete enough to verify ("use
|
|
@@ -166,29 +240,28 @@ export const skillFloor = [
|
|
|
166
240
|
* behavior drifts, and test a change by watching whether Claude's behavior
|
|
167
241
|
* actually shifts.
|
|
168
242
|
*/
|
|
169
|
-
export const
|
|
243
|
+
export const ruleDefaultContract = [
|
|
170
244
|
clause(forbiddenKeys(["description", "globs", "alwaysApply"]), {
|
|
171
245
|
severity: "required",
|
|
172
246
|
guidance: "Cursor `.mdc` keys. Claude Code's documented rules schema is `paths`-only; a rule authored with Cursor frontmatter is configuration another tool's semantics silently fail to honor — the rule loads, the scoping you meant does not. (That Claude Code ignores unknown keys is observed behavior, not documented contract — the documented schema is the citation.)",
|
|
173
|
-
cite: "https://code.claude.com/docs/en/memory#path-specific-rules (retrieved 2026-07-
|
|
247
|
+
cite: "https://code.claude.com/docs/en/memory#path-specific-rules (retrieved 2026-07-09)",
|
|
174
248
|
}),
|
|
175
249
|
clause(maxLines(200), {
|
|
176
250
|
severity: "advisory",
|
|
177
251
|
guidance: "Unconditional rules are always-on context, paid every session: the docs' size target is under 200 lines per memory file — 'longer files consume more context and reduce adherence.' (Distinct from the hard 200-line/25KB cutoff, which applies only to auto-memory MEMORY.md; rules load in full regardless of length.) For each line ask: would removing it cause Claude to make mistakes? If not, cut it.",
|
|
178
|
-
cite: "https://code.claude.com/docs/en/memory#write-effective-instructions (retrieved 2026-07-
|
|
252
|
+
cite: "https://code.claude.com/docs/en/memory#write-effective-instructions (retrieved 2026-07-09)",
|
|
179
253
|
}),
|
|
180
254
|
];
|
|
181
255
|
/**
|
|
182
|
-
* The
|
|
256
|
+
* The default contract for the qualified `claude-code.memory` kind — Anthropic's
|
|
183
257
|
* documented contract for a project `CLAUDE.md` (`packages/memory.anthropic/PACKAGE.md`,
|
|
184
|
-
* the curated authoring reference this migrates verbatim). Retrieved 2026-07-
|
|
258
|
+
* the curated authoring reference this migrates verbatim). Retrieved 2026-07-09.
|
|
185
259
|
*
|
|
186
260
|
* Deliberately near-empty, because the format is: `CLAUDE.md` is plain
|
|
187
261
|
* markdown with no documented frontmatter and no required fields
|
|
188
|
-
* (code.claude.com/docs/en/memory, retrieved 2026-07-
|
|
262
|
+
* (code.claude.com/docs/en/memory, retrieved 2026-07-09), so there is no
|
|
189
263
|
* schema to gate — manufacturing a required field or a forbidden-key list
|
|
190
|
-
* would fake a check the format does not carry
|
|
191
|
-
* law 3: decidable clauses only). The single clause is a context-cost
|
|
264
|
+
* would fake a check the format does not carry. The single clause is a context-cost
|
|
192
265
|
* budget; everything else the contract could say is guidance.
|
|
193
266
|
*
|
|
194
267
|
* What the clauses cannot carry, as guidance: a `paths:` frontmatter block
|
|
@@ -206,29 +279,33 @@ export const ruleFloor = [
|
|
|
206
279
|
* directory, not below it. Personal, un-shared notes go in `CLAUDE.local.md`
|
|
207
280
|
* (gitignored), appended after `CLAUDE.md` at its level.
|
|
208
281
|
*/
|
|
209
|
-
export const
|
|
282
|
+
export const memoryAnthropicDefaultContract = [
|
|
210
283
|
clause(maxLines(200), {
|
|
211
284
|
severity: "advisory",
|
|
212
285
|
guidance: "CLAUDE.md is always-on context, paid every session. The memory docs' size target is under 200 lines per memory file — 'longer files consume more context and reduce adherence.' For each line ask: would removing it cause Claude to make mistakes? If not, cut it. (Advisory: Claude Code loads the file in full regardless of length; this is a context-cost budget, not a hard cutoff.)",
|
|
213
|
-
cite: "https://code.claude.com/docs/en/memory#write-effective-instructions (retrieved 2026-07-
|
|
286
|
+
cite: "https://code.claude.com/docs/en/memory#write-effective-instructions (retrieved 2026-07-09)",
|
|
214
287
|
}),
|
|
215
288
|
];
|
|
216
289
|
/**
|
|
217
|
-
* The
|
|
290
|
+
* The default contract for the qualified `agents-md.memory` kind — the AGENTS.md
|
|
218
291
|
* standard's contract for a memory file, which is that there is almost none
|
|
219
292
|
* (`packages/memory.agents-md/PACKAGE.md`, the curated authoring reference
|
|
220
293
|
* this migrates). Guidance-only, and that is the honest encoding: `AGENTS.md`
|
|
221
294
|
* "is just standard Markdown" with no required fields, no sections, and no
|
|
222
|
-
* frontmatter (agents.md, retrieved 2026-07-
|
|
223
|
-
* constrains nothing. A
|
|
295
|
+
* frontmatter (agents.md, retrieved 2026-07-09); the format deliberately
|
|
296
|
+
* constrains nothing. A default contract that manufactured a required field, a size
|
|
224
297
|
* gate, or a forbidden-key list would assert a contract the standard
|
|
225
|
-
* disclaims
|
|
298
|
+
* disclaims. Even the tempting size
|
|
226
299
|
* number is a *tool's* rule, not the format's: agents read the closest
|
|
227
|
-
* `AGENTS.md` in the tree (nested, nearest-wins
|
|
228
|
-
* chain root-to-cwd and stops once
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
300
|
+
* `AGENTS.md` in the tree (nested, nearest-wins; agents.md, retrieved
|
|
301
|
+
* 2026-07-09); Codex concatenates the chain root-to-cwd and stops once
|
|
302
|
+
* combined size hits a byte budget, not a per-file line count
|
|
303
|
+
* (`project_doc_max_bytes`, 32 KiB default;
|
|
304
|
+
* developers.openai.com/codex/guides/agents-md, retrieved 2026-07-09);
|
|
305
|
+
* Gemini CLI reads `GEMINI.md` by default and only treats `AGENTS.md` as an
|
|
306
|
+
* alias when configured via `context.fileName` (geminicli.com/docs/cli/gemini-md,
|
|
307
|
+
* retrieved 2026-07-09); Claude Code does not read `AGENTS.md` natively —
|
|
308
|
+
* bridge it with a `CLAUDE.md` that `@AGENTS.md`-imports it
|
|
309
|
+
* (code.claude.com/docs/en/memory, retrieved 2026-07-09).
|
|
233
310
|
*/
|
|
234
|
-
export const
|
|
311
|
+
export const memoryAgentsMdDefaultContract = [];
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The `@dtmd/temper/claude-code` subpath — the first-party Claude Code
|
|
3
|
-
* provider face
|
|
4
|
-
* package — the provider face is a subpath export"). A harness author who
|
|
3
|
+
* provider face. A harness author who
|
|
5
4
|
* targets Claude Code imports the built-in kinds from here, never the root:
|
|
6
|
-
* the root carries only the six-noun core, and identity travels by import
|
|
7
|
-
*
|
|
8
|
-
* specifier like any other. The built-in
|
|
9
|
-
*
|
|
10
|
-
* too: adoption is `import { skill, skillFloor } from "@dtmd/temper/claude-code"`.
|
|
5
|
+
* the root carries only the six-noun core, and identity travels by import,
|
|
6
|
+
* so a subpath specifier is a full module
|
|
7
|
+
* specifier like any other. The built-in default contracts join the kinds here
|
|
8
|
+
* too: adoption is `import { skill, skillDefaultContract } from "@dtmd/temper/claude-code"`.
|
|
11
9
|
*/
|
|
12
|
-
export type { Memory, Rule, Skill } from "./builtins.js";
|
|
13
|
-
export { memory,
|
|
10
|
+
export type { Agent, Memory, Rule, Skill } from "./builtins.js";
|
|
11
|
+
export { agent, agentDefaultContract, command, commandDefaultContract, memory, memoryAgentsMdDefaultContract, memoryAnthropicDefaultContract, rule, ruleDefaultContract, skill, skillDefaultContract, } from "./builtins.js";
|
|
14
12
|
export type { Blocks, File, Prose, Text } from "./prose.js";
|
|
15
13
|
export { blocks, file, text } from "./prose.js";
|
package/dist/src/claude-code.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The `@dtmd/temper/claude-code` subpath — the first-party Claude Code
|
|
3
|
-
* provider face
|
|
4
|
-
* package — the provider face is a subpath export"). A harness author who
|
|
3
|
+
* provider face. A harness author who
|
|
5
4
|
* targets Claude Code imports the built-in kinds from here, never the root:
|
|
6
|
-
* the root carries only the six-noun core, and identity travels by import
|
|
7
|
-
*
|
|
8
|
-
* specifier like any other. The built-in
|
|
9
|
-
*
|
|
10
|
-
* too: adoption is `import { skill, skillFloor } from "@dtmd/temper/claude-code"`.
|
|
5
|
+
* the root carries only the six-noun core, and identity travels by import,
|
|
6
|
+
* so a subpath specifier is a full module
|
|
7
|
+
* specifier like any other. The built-in default contracts join the kinds here
|
|
8
|
+
* too: adoption is `import { skill, skillDefaultContract } from "@dtmd/temper/claude-code"`.
|
|
11
9
|
*/
|
|
12
|
-
export { memory,
|
|
10
|
+
export { agent, agentDefaultContract, command, commandDefaultContract, memory, memoryAgentsMdDefaultContract, memoryAnthropicDefaultContract, rule, ruleDefaultContract, skill, skillDefaultContract, } from "./builtins.js";
|
|
13
11
|
export { blocks, file, text } from "./prose.js";
|
package/dist/src/contract.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Contracts — clauses and requirements as typed values
|
|
2
|
+
* Contracts — clauses and requirements as typed values.
|
|
3
3
|
* A clause is `predicate · severity · guidance · cite`; a requirement is
|
|
4
|
-
* `
|
|
5
|
-
* at the seam
|
|
4
|
+
* `prose · kind · required · clauses? · verifiedBy?`. Both erase to compiled data
|
|
5
|
+
* at the seam: the author composes typed objects, the engine
|
|
6
6
|
* consumes their rows. The predicate vocabulary is the closed algebra — a clause
|
|
7
|
-
* outside it is a squiggle, not a runtime rejection
|
|
8
|
-
* walls).
|
|
7
|
+
* outside it is a squiggle, not a runtime rejection.
|
|
9
8
|
*/
|
|
10
9
|
import type { KindDefinition } from "./kind.js";
|
|
11
10
|
/** A clause's delivery posture: `required` gate-blocks, `advisory` reports. */
|
|
12
11
|
export type Severity = "required" | "advisory";
|
|
13
12
|
/**
|
|
14
|
-
* A member of the closed predicate algebra
|
|
13
|
+
* A member of the closed predicate algebra. Both a kind's
|
|
15
14
|
* own `expect` clauses and a requirement's `clauses` compile to the row's full
|
|
16
15
|
* `key`/`field`/`severity`/argument shape (`declarations.ts` `clauseRow`): a
|
|
17
16
|
* floor clause's own `bound`/`charset`/`keys`/`values` ride the row alongside
|
|
@@ -28,21 +27,29 @@ export interface Predicate {
|
|
|
28
27
|
readonly args?: Readonly<Record<string, number>>;
|
|
29
28
|
/**
|
|
30
29
|
* `membership`'s target requirement name — a separate slot from `field` (the
|
|
31
|
-
* checked field) since `membership` names both
|
|
32
|
-
* at the node-set scope").
|
|
30
|
+
* checked field) since `membership` names both.
|
|
33
31
|
*/
|
|
34
32
|
readonly target?: string;
|
|
35
|
-
/** `allowed_chars`'s declared character class
|
|
33
|
+
/** `allowed_chars`'s declared character class. */
|
|
36
34
|
readonly charset?: Charset;
|
|
37
35
|
/** `forbidden_keys`'s forbidden key list. */
|
|
38
36
|
readonly keys?: readonly string[];
|
|
39
37
|
/** `enum`/`deny`'s permitted or forbidden value list. */
|
|
40
38
|
readonly values?: readonly string[];
|
|
39
|
+
/** `range`'s inclusive numeric bound. */
|
|
40
|
+
readonly range?: {
|
|
41
|
+
readonly min: number;
|
|
42
|
+
readonly max: number;
|
|
43
|
+
};
|
|
44
|
+
/** `section_contains`'s heading-text prefix and the marker each governed section must carry. */
|
|
45
|
+
readonly section?: {
|
|
46
|
+
readonly heading: string;
|
|
47
|
+
readonly marker: string;
|
|
48
|
+
};
|
|
41
49
|
}
|
|
42
50
|
/**
|
|
43
51
|
* The character class `allowed_chars` admits — inclusive ranges plus individual
|
|
44
|
-
* characters, e.g. `[a-z0-9-]
|
|
45
|
-
* not a general `pattern` clause"). Each range is a `"<lo>-<hi>"` two-character
|
|
52
|
+
* characters, e.g. `[a-z0-9-]`. Each range is a `"<lo>-<hi>"` two-character
|
|
46
53
|
* span (`src/contract.rs` `parse_range`'s wire spelling).
|
|
47
54
|
*/
|
|
48
55
|
export interface Charset {
|
|
@@ -69,6 +76,23 @@ export declare const deny: (field: string, values: readonly string[]) => Predica
|
|
|
69
76
|
export declare const requireSections: () => Predicate;
|
|
70
77
|
/** The member's name matches its directory. */
|
|
71
78
|
export declare const nameMatchesDir: () => Predicate;
|
|
79
|
+
/** Names are unique within the artifact kind (a scope-wide identity collision). */
|
|
80
|
+
export declare const uniqueName: () => Predicate;
|
|
81
|
+
/**
|
|
82
|
+
* The named field may be present — always satisfied, recording the key as part of a
|
|
83
|
+
* declared (closed) schema. `dependency-exists` has no constructor: the engine holds
|
|
84
|
+
* it back absent a decidable reference syntax, so a hand-authored clause would fail
|
|
85
|
+
* admissibility.
|
|
86
|
+
*/
|
|
87
|
+
export declare const optional: (field: string) => Predicate;
|
|
88
|
+
/** The field's numeric value lies within the inclusive `[min, max]` bound. */
|
|
89
|
+
export declare const range: (field: string, min: number, max: number) => Predicate;
|
|
90
|
+
/** The field's value is one of `values`. Spelled `enumOf` — `enum` is a reserved word. */
|
|
91
|
+
export declare const enumOf: (field: string, values: readonly string[]) => Predicate;
|
|
92
|
+
/** The named body marker is defined (e.g. `disable-model-invocation`). */
|
|
93
|
+
export declare const mustDefine: (marker: string) => Predicate;
|
|
94
|
+
/** Every body section whose heading *starts with* `heading` carries `marker` in its body. */
|
|
95
|
+
export declare const sectionContains: (heading: string, marker: string) => Predicate;
|
|
72
96
|
/** The satisfier set's size lies in the inclusive `[min, max]` bound. */
|
|
73
97
|
export declare const count: (bounds: {
|
|
74
98
|
min?: number;
|
|
@@ -92,7 +116,7 @@ export declare const degree: (bounds: {
|
|
|
92
116
|
/**
|
|
93
117
|
* A clause — a predicate the author marks with a severity, the just-in-time
|
|
94
118
|
* guidance the predicate cannot encode, and the external-fact `cite` that makes
|
|
95
|
-
* a maintained floor auditable
|
|
119
|
+
* a maintained floor auditable.
|
|
96
120
|
*/
|
|
97
121
|
export interface Clause {
|
|
98
122
|
readonly predicate: Predicate;
|
|
@@ -107,22 +131,21 @@ export declare function clause(predicate: Predicate, opts: {
|
|
|
107
131
|
cite?: string;
|
|
108
132
|
}): Clause;
|
|
109
133
|
/**
|
|
110
|
-
* A requirement — a named obligation on the harness
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* `
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* wires the behavioral remainder.
|
|
134
|
+
* A requirement — a named obligation on the harness. `prose` is the authored
|
|
135
|
+
* intent, carried never interpreted; `kind` constrains what may fill it **by
|
|
136
|
+
* import** (a value, never a string); `required` is the posture declaration;
|
|
137
|
+
* `clauses` are the requirement's own set-/edge-scope demands — ordinary
|
|
138
|
+
* [`Clause`] values whose predicates range over the satisfier set
|
|
139
|
+
* (`count`/`unique`/`membership`) or its graph neighborhood (`degree`), the
|
|
140
|
+
* same four-channel clause as everywhere; `verifiedBy` wires the behavioral
|
|
141
|
+
* remainder.
|
|
119
142
|
*/
|
|
120
143
|
export interface Requirement {
|
|
121
|
-
readonly
|
|
122
|
-
readonly kind?: KindDefinition<
|
|
144
|
+
readonly prose: string;
|
|
145
|
+
readonly kind?: KindDefinition<never>;
|
|
123
146
|
readonly required?: boolean;
|
|
124
147
|
readonly clauses?: readonly Clause[];
|
|
125
148
|
readonly verifiedBy?: string;
|
|
126
149
|
}
|
|
127
|
-
/** An identity helper — types a requirement literal at the keystroke
|
|
150
|
+
/** An identity helper — types a requirement literal at the keystroke. */
|
|
128
151
|
export declare function requirement(init: Requirement): Requirement;
|
package/dist/src/contract.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Contracts — clauses and requirements as typed values
|
|
2
|
+
* Contracts — clauses and requirements as typed values.
|
|
3
3
|
* A clause is `predicate · severity · guidance · cite`; a requirement is
|
|
4
|
-
* `
|
|
5
|
-
* at the seam
|
|
4
|
+
* `prose · kind · required · clauses? · verifiedBy?`. Both erase to compiled data
|
|
5
|
+
* at the seam: the author composes typed objects, the engine
|
|
6
6
|
* consumes their rows. The predicate vocabulary is the closed algebra — a clause
|
|
7
|
-
* outside it is a squiggle, not a runtime rejection
|
|
8
|
-
* walls).
|
|
7
|
+
* outside it is a squiggle, not a runtime rejection.
|
|
9
8
|
*/
|
|
10
|
-
// Node-scope predicates
|
|
9
|
+
// Node-scope predicates.
|
|
11
10
|
/** A field or marker is present. */
|
|
12
11
|
export const required = (field) => ({ key: "required", field });
|
|
13
12
|
/** The field's parsed scalar type is as declared. */
|
|
@@ -36,8 +35,35 @@ export const deny = (field, values) => ({
|
|
|
36
35
|
export const requireSections = () => ({ key: "require_sections" });
|
|
37
36
|
/** The member's name matches its directory. */
|
|
38
37
|
export const nameMatchesDir = () => ({ key: "name-matches-dir" });
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
/** Names are unique within the artifact kind (a scope-wide identity collision). */
|
|
39
|
+
export const uniqueName = () => ({ key: "unique-name" });
|
|
40
|
+
/**
|
|
41
|
+
* The named field may be present — always satisfied, recording the key as part of a
|
|
42
|
+
* declared (closed) schema. `dependency-exists` has no constructor: the engine holds
|
|
43
|
+
* it back absent a decidable reference syntax, so a hand-authored clause would fail
|
|
44
|
+
* admissibility.
|
|
45
|
+
*/
|
|
46
|
+
export const optional = (field) => ({ key: "optional", field });
|
|
47
|
+
/** The field's numeric value lies within the inclusive `[min, max]` bound. */
|
|
48
|
+
export const range = (field, min, max) => ({
|
|
49
|
+
key: "range",
|
|
50
|
+
field,
|
|
51
|
+
range: { min, max },
|
|
52
|
+
});
|
|
53
|
+
/** The field's value is one of `values`. Spelled `enumOf` — `enum` is a reserved word. */
|
|
54
|
+
export const enumOf = (field, values) => ({
|
|
55
|
+
key: "enum",
|
|
56
|
+
field,
|
|
57
|
+
values,
|
|
58
|
+
});
|
|
59
|
+
/** The named body marker is defined (e.g. `disable-model-invocation`). */
|
|
60
|
+
export const mustDefine = (marker) => ({ key: "must_define", field: marker });
|
|
61
|
+
/** Every body section whose heading *starts with* `heading` carries `marker` in its body. */
|
|
62
|
+
export const sectionContains = (heading, marker) => ({
|
|
63
|
+
key: "section_contains",
|
|
64
|
+
section: { heading, marker },
|
|
65
|
+
});
|
|
66
|
+
// Node-set/edge-scope predicates — a requirement's set-scope demands ride
|
|
41
67
|
// these as ordinary clause values, the same four-channel `clause()` shape as
|
|
42
68
|
// the node-scope predicates above.
|
|
43
69
|
/** The satisfier set's size lies in the inclusive `[min, max]` bound. */
|
|
@@ -74,7 +100,7 @@ export const degree = (bounds) => {
|
|
|
74
100
|
export function clause(predicate, opts) {
|
|
75
101
|
return { predicate, severity: opts.severity, guidance: opts.guidance, cite: opts.cite };
|
|
76
102
|
}
|
|
77
|
-
/** An identity helper — types a requirement literal at the keystroke
|
|
103
|
+
/** An identity helper — types a requirement literal at the keystroke. */
|
|
78
104
|
export function requirement(init) {
|
|
79
105
|
return init;
|
|
80
106
|
}
|