@dtmd/temper 0.0.10 → 0.0.12
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/src/assembly.d.ts +5 -5
- package/dist/src/builtins.d.ts +37 -55
- package/dist/src/builtins.js +52 -62
- package/dist/src/contract.d.ts +2 -3
- package/dist/src/contract.js +2 -3
- package/dist/src/declarations.d.ts +6 -5
- package/dist/src/declarations.js +13 -31
- package/dist/src/emit.d.ts +1 -22
- package/dist/src/emit.js +2 -2
- package/dist/src/generated/KindFactRow.d.ts +9 -0
- package/dist/src/kind.d.ts +6 -0
- package/package.json +3 -3
package/dist/src/assembly.d.ts
CHANGED
|
@@ -29,11 +29,11 @@ export interface Admission {
|
|
|
29
29
|
readonly admits: readonly KindDefinition<never>[];
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
|
-
* The declared enforcement-mode vocabulary — how firmly
|
|
33
|
-
*
|
|
34
|
-
* `block`: denies the
|
|
35
|
-
* `warn` (default): allows the
|
|
36
|
-
* live context. `note`: allows the
|
|
32
|
+
* The declared enforcement-mode vocabulary — how firmly a guard binds an
|
|
33
|
+
* intercepted action, split by where the finding goes.
|
|
34
|
+
* `block`: denies the action.
|
|
35
|
+
* `warn` (default): allows the action and surfaces the finding in-band, into the
|
|
36
|
+
* live context. `note`: allows the action and records the finding out-of-band
|
|
37
37
|
* only — the next report, never the session.
|
|
38
38
|
*/
|
|
39
39
|
export type EnforcementMode = "note" | "warn" | "block";
|
package/dist/src/builtins.d.ts
CHANGED
|
@@ -300,6 +300,12 @@ export interface Hook {
|
|
|
300
300
|
/** The tool-name filter a tool-scoped event fires on (`"*"`/`""`/absent = all). */
|
|
301
301
|
readonly matcher?: string;
|
|
302
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* The manifest Claude Code's harness-level settings reside in — the file the assembly's
|
|
305
|
+
* residual settings keys fold into as opaque residue, the same manifest the `hook` kind's
|
|
306
|
+
* registrations surface inside (code.claude.com/docs/en/settings, retrieved 2026-07-16).
|
|
307
|
+
*/
|
|
308
|
+
export declare const SETTINGS_MANIFEST = "settings.json";
|
|
303
309
|
/**
|
|
304
310
|
* `hook` — a `settings.json` `hooks.<Event>` registration member: a fields-only kind (no
|
|
305
311
|
* body slot), its members discovered off the `.claude/settings.json` manifest at the
|
|
@@ -569,11 +575,6 @@ export declare const pluginManifest: KindDefinition<PluginManifest>;
|
|
|
569
575
|
*
|
|
570
576
|
* Deliberately absent as undecidable: whether the `description` reads well, whether
|
|
571
577
|
* `keywords` aid discovery, whether `name` names the pack aptly.
|
|
572
|
-
*
|
|
573
|
-
* Authoring notes the clauses cannot carry: leave `version` unset while iterating, so the
|
|
574
|
-
* commit SHA drives updates and users are not stranded on a stale pin; set it once the
|
|
575
|
-
* plugin has a release cycle, and bump it every time — pushing commits without bumping is
|
|
576
|
-
* a no-op. Reach for `defaultEnabled: false` when the plugin costs money or scope on load.
|
|
577
578
|
*/
|
|
578
579
|
export declare const pluginManifestDefaultContract: readonly Clause[];
|
|
579
580
|
/**
|
|
@@ -713,14 +714,6 @@ export declare const marketplace: KindDefinition<Marketplace>;
|
|
|
713
714
|
* there is no predicate that decides it, and a clause that guessed would fire on true
|
|
714
715
|
* negatives. The enumerated deny list is the decidable subset; the impersonation rule rides
|
|
715
716
|
* as guidance below.
|
|
716
|
-
*
|
|
717
|
-
* Authoring notes the clauses cannot carry: a relative-path `source` resolves against a
|
|
718
|
-
* *local copy* of the marketplace, so it silently fails to resolve for users who added the
|
|
719
|
-
* marketplace by direct URL to `marketplace.json` — only that one file is downloaded. Reach
|
|
720
|
-
* for `github`, `url`, or `npm` when the catalog is distributed by URL. Where a git source
|
|
721
|
-
* pins both `ref` and `sha`, the `sha` is the effective pin. A marketplace entry's
|
|
722
|
-
* `defaultEnabled` beats the same field in the plugin's own `plugin.json`, while `version`
|
|
723
|
-
* runs the other way — `plugin.json` wins.
|
|
724
717
|
*/
|
|
725
718
|
export declare const marketplaceDefaultContract: readonly Clause[];
|
|
726
719
|
/**
|
|
@@ -803,13 +796,6 @@ export declare const settingsLocalDefaultContract: readonly Clause[];
|
|
|
803
796
|
* vagueness/no-op detection (semantic); gerund naming (judgment). Nothing
|
|
804
797
|
* decidable is held: the name's hyphen placement and the platform's "no XML
|
|
805
798
|
* tags in the description" are the two `shape` clauses below.
|
|
806
|
-
*
|
|
807
|
-
* Authoring notes the clauses cannot carry: prefer gerund or noun-phrase
|
|
808
|
-
* names (`processing-pdfs`, `pdf-processing`) over vague ones (`helper`,
|
|
809
|
-
* `utils`); `disable-model-invocation: true` for side-effectful workflows you
|
|
810
|
-
* want to time yourself; `user-invocable: false` for background knowledge
|
|
811
|
-
* that is not a command; `metadata` is the sanctioned home for versioning —
|
|
812
|
-
* there is no top-level `version` field.
|
|
813
799
|
*/
|
|
814
800
|
export declare const skillDefaultContract: readonly Clause[];
|
|
815
801
|
/**
|
|
@@ -830,12 +816,16 @@ export declare const skillDefaultContract: readonly Clause[];
|
|
|
830
816
|
*/
|
|
831
817
|
export declare const supportingDocDefaultContract: readonly Clause[];
|
|
832
818
|
/**
|
|
833
|
-
* The default contract for `command` —
|
|
834
|
-
*
|
|
835
|
-
*
|
|
836
|
-
*
|
|
837
|
-
*
|
|
838
|
-
* retrieved 2026-07-
|
|
819
|
+
* The default contract for `command` — deliberately empty. A command is a lone
|
|
820
|
+
* markdown file whose frontmatter is entirely optional, matching the Claude Code
|
|
821
|
+
* runtime's documented flexibility. Where a skill requires `name` and
|
|
822
|
+
* `description` by the Agent Skills open standard, a command file may carry any,
|
|
823
|
+
* all, or none of them — identity comes from the filename stem, not a field
|
|
824
|
+
* (code.claude.com/docs/en/slash-commands, retrieved 2026-07-22).
|
|
825
|
+
*
|
|
826
|
+
* A command that passes here holds no contract constraint and loads everywhere
|
|
827
|
+
* the format is honored. The strictness stays with the skill kind, which enforces
|
|
828
|
+
* the portable profile for skill directories.
|
|
839
829
|
*/
|
|
840
830
|
export declare const commandDefaultContract: readonly Clause[];
|
|
841
831
|
/**
|
|
@@ -865,16 +855,6 @@ export declare const agentDefaultContract: readonly Clause[];
|
|
|
865
855
|
* own: `required` is the one
|
|
866
856
|
* presence predicate, and its absence is not itself a predicate.)
|
|
867
857
|
* https://code.claude.com/docs/en/memory#path-specific-rules (retrieved 2026-07-15)
|
|
868
|
-
*
|
|
869
|
-
* What the clauses cannot carry, as guidance: keep a rule to facts Claude
|
|
870
|
-
* should hold whenever the rule is in scope — concrete enough to verify ("use
|
|
871
|
-
* 2-space indentation", not "format code properly"). If an entry is a
|
|
872
|
-
* multi-step procedure or only matters occasionally, it belongs in a skill
|
|
873
|
-
* (on-demand) rather than a rule (always-on). Prefer path-scoped rules when
|
|
874
|
-
* one convention governs scattered paths; prefer per-directory CLAUDE.md when
|
|
875
|
-
* directory owners maintain their own. Treat rules like code: prune them when
|
|
876
|
-
* behavior drifts, and test a change by watching whether Claude's behavior
|
|
877
|
-
* actually shifts.
|
|
878
858
|
*/
|
|
879
859
|
export declare const ruleDefaultContract: readonly Clause[];
|
|
880
860
|
/**
|
|
@@ -887,21 +867,6 @@ export declare const ruleDefaultContract: readonly Clause[];
|
|
|
887
867
|
* schema to gate — manufacturing a required field or a forbidden-key list
|
|
888
868
|
* would fake a check the format does not carry. The single clause is a context-cost
|
|
889
869
|
* budget; everything else the contract could say is guidance.
|
|
890
|
-
*
|
|
891
|
-
* What the clauses cannot carry, as guidance: a `paths:` frontmatter block
|
|
892
|
-
* belongs on a `.claude/rules/*.md` file, not on `CLAUDE.md` — the memory
|
|
893
|
-
* docs document `paths` only for rules, so a rules-style header on
|
|
894
|
-
* `CLAUDE.md` is dead configuration. Split a large file with `@path` imports
|
|
895
|
-
* (resolved relative to the importing file, absolute allowed, recursion
|
|
896
|
-
* capped at four hops; wrap a path in backticks to mention it without
|
|
897
|
-
* importing). If the repo already ships an `AGENTS.md` for other agents,
|
|
898
|
-
* don't duplicate it — create a `CLAUDE.md` that `@AGENTS.md`-imports it (or
|
|
899
|
-
* symlink, except on Windows where the import is the recommended bridge).
|
|
900
|
-
* Mind the loading asymmetry: every ancestor `CLAUDE.md` loads in full at
|
|
901
|
-
* launch, while files in subdirectories load only when Claude reads a file
|
|
902
|
-
* there — so a rule that must always hold belongs above the working
|
|
903
|
-
* directory, not below it. Personal, un-shared notes go in `CLAUDE.local.md`
|
|
904
|
-
* (gitignored), appended after `CLAUDE.md` at its level.
|
|
905
870
|
*/
|
|
906
871
|
export declare const memoryAnthropicDefaultContract: readonly Clause[];
|
|
907
872
|
/**
|
|
@@ -920,12 +885,29 @@ export declare const memoryAnthropicDefaultContract: readonly Clause[];
|
|
|
920
885
|
* vocabulary's when/enumOf/type extensions, addressing still cannot spell a path into the
|
|
921
886
|
* handler array (e.g., `hooks.<Event>[0].type`). A clause over it would range over a field
|
|
922
887
|
* the read never surfaces, so it is no clause at all — the addressing-reach gap remains.
|
|
923
|
-
* What the clauses cannot carry, as guidance: keep a handler's `type` among
|
|
924
|
-
* `command`/`http`/`mcp_tool`/`prompt`/`agent`; a `command` handler needs a `command`, an
|
|
925
|
-
* `http` handler a `url`; the `matcher` filters tool-scoped events and is inert on events
|
|
926
|
-
* that carry no tool (`UserPromptSubmit`, `Stop`, and their siblings).
|
|
927
888
|
*/
|
|
928
889
|
export declare const hookDefaultContract: readonly Clause[];
|
|
890
|
+
/**
|
|
891
|
+
* The `settings.json` lifecycle event and matcher one documented telemetry event-name
|
|
892
|
+
* projects its tap hook at. The event-name is the author-facing token a telemetry
|
|
893
|
+
* verifier names (`contract.ts`'s `telemetry`, the `roster.rs` admissibility set); the
|
|
894
|
+
* `event` is the `hooks.<Event>` key the tap registers under, and the `matcher` scopes
|
|
895
|
+
* the fire to the telemetry-relevant subset — each an external fact
|
|
896
|
+
* (code.claude.com/docs/en/hooks, retrieved 2026-07-17):
|
|
897
|
+
*
|
|
898
|
+
* - `InstructionsLoaded` fires on a rule/memory load; its matcher filters the load
|
|
899
|
+
* reason, and `path_glob_match` is the lazy per-path load the coverage tap reads.
|
|
900
|
+
* - `SkillInvoked` is a skill invocation, surfaced under `PostToolUse` with the tool-name
|
|
901
|
+
* matcher `Skill` — the tap's own read of a skill call.
|
|
902
|
+
* - `UserPromptExpansion` fires on a command expansion; its matcher filters the command
|
|
903
|
+
* name, `.*` capturing every one.
|
|
904
|
+
* - `ToolUse` fires after any tool call; its matcher filters the tool name, `.*`
|
|
905
|
+
* capturing every one.
|
|
906
|
+
*/
|
|
907
|
+
export declare const TELEMETRY_EVENT_HOOKS: Readonly<Record<string, {
|
|
908
|
+
readonly event: string;
|
|
909
|
+
readonly matcher: string;
|
|
910
|
+
}>>;
|
|
929
911
|
/**
|
|
930
912
|
* The default contract for `mcpServer` — Anthropic's documented `.mcp.json` contract
|
|
931
913
|
* (code.claude.com/docs/en/mcp, retrieved 2026-07-15). A server surfaces at `mcpServers.*`,
|
package/dist/src/builtins.js
CHANGED
|
@@ -48,6 +48,7 @@ export const skill = kind({
|
|
|
48
48
|
registration: [{ via: "user-invoked" }, { via: "description-trigger", field: "description" }],
|
|
49
49
|
identityField: "name",
|
|
50
50
|
templates: [{ kind: supportingDoc, path: "*.md" }],
|
|
51
|
+
guidance: "prefer gerund or noun-phrase names (`processing-pdfs`, `pdf-processing`) over vague ones (`helper`, `utils`); `disable-model-invocation: true` for side-effectful workflows you want to time yourself; `user-invocable: false` for background knowledge that is not a command; `metadata` is the sanctioned home for versioning — there is no top-level `version` field.",
|
|
51
52
|
});
|
|
52
53
|
/**
|
|
53
54
|
* `command` — `.claude/commands/*.md`, the skill surface's legacy file placement
|
|
@@ -90,6 +91,7 @@ export const rule = kind({
|
|
|
90
91
|
format: "yaml-frontmatter",
|
|
91
92
|
unitShape: "file",
|
|
92
93
|
registration: [{ via: "paths-match", field: "paths" }],
|
|
94
|
+
guidance: "keep a rule to facts Claude should hold whenever the rule is in scope — concrete enough to verify ('use 2-space indentation', not 'format code properly'). If an entry is a multi-step procedure or only matters occasionally, it belongs in a skill (on-demand) rather than a rule (always-on). Prefer path-scoped rules when one convention governs scattered paths; prefer per-directory CLAUDE.md when directory owners maintain their own. Treat rules like code: prune them when behavior drifts, and test a change by watching whether Claude's behavior actually shifts.",
|
|
93
95
|
});
|
|
94
96
|
/**
|
|
95
97
|
* `memory` — a root `<name>.md` (`CLAUDE.md`, `AGENTS.md`), a lone file loaded
|
|
@@ -105,7 +107,14 @@ export const memory = kind({
|
|
|
105
107
|
locus: { kind: "at", root: ".", glob: "**/CLAUDE.md" },
|
|
106
108
|
unitShape: "file",
|
|
107
109
|
registration: [{ via: "always" }],
|
|
110
|
+
guidance: "a `paths:` frontmatter block belongs on a `.claude/rules/*.md` file, not on `CLAUDE.md` — the memory docs document `paths` only for rules, so a rules-style header on `CLAUDE.md` is dead configuration. Split a large file with `@path` imports (resolved relative to the importing file, absolute allowed, recursion capped at four hops; wrap a path in backticks to mention it without importing). If the repo already ships an `AGENTS.md` for other agents, don't duplicate it — create a `CLAUDE.md` that `@AGENTS.md`-imports it (or symlink, except on Windows where the import is the recommended bridge). Mind the loading asymmetry: every ancestor `CLAUDE.md` loads in full at launch, while files in subdirectories load only when Claude reads a file there — so a rule that must always hold belongs above the working directory, not below it. Personal, un-shared notes go in `CLAUDE.local.md` (gitignored), appended after `CLAUDE.md` at its level.",
|
|
108
111
|
});
|
|
112
|
+
/**
|
|
113
|
+
* The manifest Claude Code's harness-level settings reside in — the file the assembly's
|
|
114
|
+
* residual settings keys fold into as opaque residue, the same manifest the `hook` kind's
|
|
115
|
+
* registrations surface inside (code.claude.com/docs/en/settings, retrieved 2026-07-16).
|
|
116
|
+
*/
|
|
117
|
+
export const SETTINGS_MANIFEST = "settings.json";
|
|
109
118
|
/**
|
|
110
119
|
* `hook` — a `settings.json` `hooks.<Event>` registration member: a fields-only kind (no
|
|
111
120
|
* body slot), its members discovered off the `.claude/settings.json` manifest at the
|
|
@@ -115,11 +124,12 @@ export const memory = kind({
|
|
|
115
124
|
*/
|
|
116
125
|
export const hook = kind({
|
|
117
126
|
name: "hook",
|
|
118
|
-
locus: { kind: "at", root: ".claude", glob:
|
|
127
|
+
locus: { kind: "at", root: ".claude", glob: SETTINGS_MANIFEST },
|
|
119
128
|
unitShape: "file",
|
|
120
129
|
registration: [{ via: "event", field: "event" }],
|
|
121
130
|
shape: "fields",
|
|
122
|
-
collectionAddress: { manifest:
|
|
131
|
+
collectionAddress: { manifest: SETTINGS_MANIFEST, keyPath: "hooks.<Event>", entryShape: "group-array(hooks;matcher)" },
|
|
132
|
+
guidance: "keep a handler's `type` among `command`/`http`/`mcp_tool`/`prompt`/`agent`; a `command` handler needs a `command`, an `http` handler a `url`; the `matcher` filters tool-scoped events and is inert on events that carry no tool (`UserPromptSubmit`, `Stop`, and their siblings).",
|
|
123
133
|
});
|
|
124
134
|
/**
|
|
125
135
|
* `mcpServer` — a `.mcp.json` `mcpServers.*` registration member: a fields-only kind (no
|
|
@@ -147,11 +157,11 @@ export const mcpServer = kind({
|
|
|
147
157
|
*/
|
|
148
158
|
export const installedPlugin = kind({
|
|
149
159
|
name: "installed-plugin",
|
|
150
|
-
locus: { kind: "at", root: ".claude", glob:
|
|
160
|
+
locus: { kind: "at", root: ".claude", glob: SETTINGS_MANIFEST },
|
|
151
161
|
unitShape: "file",
|
|
152
162
|
registration: [{ via: "enablement", field: "enabled" }],
|
|
153
163
|
shape: "fields",
|
|
154
|
-
collectionAddress: { manifest:
|
|
164
|
+
collectionAddress: { manifest: SETTINGS_MANIFEST, keyPath: "enabledPlugins.*", entryShape: "scalar(enabled)" },
|
|
155
165
|
// The marketplace half of the `<plugin>@<marketplace>` key is a declared edge to the
|
|
156
166
|
// `known-marketplace` member it names (decision 0039). The half is not an authored field
|
|
157
167
|
// — the engine splits it off the composite key at read (`src/kind.rs`, the read-time fold
|
|
@@ -190,11 +200,11 @@ export const installedPluginDefaultContract = [];
|
|
|
190
200
|
*/
|
|
191
201
|
export const knownMarketplace = kind({
|
|
192
202
|
name: "known-marketplace",
|
|
193
|
-
locus: { kind: "at", root: ".claude", glob:
|
|
203
|
+
locus: { kind: "at", root: ".claude", glob: SETTINGS_MANIFEST },
|
|
194
204
|
unitShape: "file",
|
|
195
205
|
registration: [{ via: "registry" }],
|
|
196
206
|
shape: "fields",
|
|
197
|
-
collectionAddress: { manifest:
|
|
207
|
+
collectionAddress: { manifest: SETTINGS_MANIFEST, keyPath: "extraKnownMarketplaces.*", entryShape: "object" },
|
|
198
208
|
});
|
|
199
209
|
/**
|
|
200
210
|
* The default contract for `known-marketplace` — **deliberately empty**. The format
|
|
@@ -222,6 +232,7 @@ export const pluginManifest = kind({
|
|
|
222
232
|
unitShape: "named-field",
|
|
223
233
|
registration: [],
|
|
224
234
|
identityField: "name",
|
|
235
|
+
guidance: "leave `version` unset while iterating, so the commit SHA drives updates and users are not stranded on a stale pin; set it once the plugin has a release cycle, and bump it every time — pushing commits without bumping is a no-op. Reach for `defaultEnabled: false` when the plugin costs money or scope on load.",
|
|
225
236
|
});
|
|
226
237
|
/**
|
|
227
238
|
* The default contract for `plugin-manifest` — the documented profile of `claude plugin
|
|
@@ -249,11 +260,6 @@ export const pluginManifest = kind({
|
|
|
249
260
|
*
|
|
250
261
|
* Deliberately absent as undecidable: whether the `description` reads well, whether
|
|
251
262
|
* `keywords` aid discovery, whether `name` names the pack aptly.
|
|
252
|
-
*
|
|
253
|
-
* Authoring notes the clauses cannot carry: leave `version` unset while iterating, so the
|
|
254
|
-
* commit SHA drives updates and users are not stranded on a stale pin; set it once the
|
|
255
|
-
* plugin has a release cycle, and bump it every time — pushing commits without bumping is
|
|
256
|
-
* a no-op. Reach for `defaultEnabled: false` when the plugin costs money or scope on load.
|
|
257
263
|
*/
|
|
258
264
|
export const pluginManifestDefaultContract = [
|
|
259
265
|
clause(required("name"), {
|
|
@@ -441,6 +447,7 @@ export const marketplace = kind({
|
|
|
441
447
|
unitShape: "named-field",
|
|
442
448
|
registration: [],
|
|
443
449
|
identityField: "name",
|
|
450
|
+
guidance: "a relative-path `source` resolves against a *local copy* of the marketplace, so it silently fails to resolve for users who added the marketplace by direct URL to `marketplace.json` — only that one file is downloaded. Reach for `github`, `url`, or `npm` when the catalog is distributed by URL. Where a git source pins both `ref` and `sha`, the `sha` is the effective pin. A marketplace entry's `defaultEnabled` beats the same field in the plugin's own `plugin.json`, while `version` runs the other way — `plugin.json` wins.",
|
|
444
451
|
});
|
|
445
452
|
/**
|
|
446
453
|
* The reserved marketplace names — reserved for official Anthropic use and refused to a
|
|
@@ -490,14 +497,6 @@ const RESERVED_MARKETPLACE_NAMES = [
|
|
|
490
497
|
* there is no predicate that decides it, and a clause that guessed would fire on true
|
|
491
498
|
* negatives. The enumerated deny list is the decidable subset; the impersonation rule rides
|
|
492
499
|
* as guidance below.
|
|
493
|
-
*
|
|
494
|
-
* Authoring notes the clauses cannot carry: a relative-path `source` resolves against a
|
|
495
|
-
* *local copy* of the marketplace, so it silently fails to resolve for users who added the
|
|
496
|
-
* marketplace by direct URL to `marketplace.json` — only that one file is downloaded. Reach
|
|
497
|
-
* for `github`, `url`, or `npm` when the catalog is distributed by URL. Where a git source
|
|
498
|
-
* pins both `ref` and `sha`, the `sha` is the effective pin. A marketplace entry's
|
|
499
|
-
* `defaultEnabled` beats the same field in the plugin's own `plugin.json`, while `version`
|
|
500
|
-
* runs the other way — `plugin.json` wins.
|
|
501
500
|
*/
|
|
502
501
|
export const marketplaceDefaultContract = [
|
|
503
502
|
clause(required("name"), {
|
|
@@ -661,13 +660,6 @@ export const settingsLocalDefaultContract = [
|
|
|
661
660
|
* vagueness/no-op detection (semantic); gerund naming (judgment). Nothing
|
|
662
661
|
* decidable is held: the name's hyphen placement and the platform's "no XML
|
|
663
662
|
* tags in the description" are the two `shape` clauses below.
|
|
664
|
-
*
|
|
665
|
-
* Authoring notes the clauses cannot carry: prefer gerund or noun-phrase
|
|
666
|
-
* names (`processing-pdfs`, `pdf-processing`) over vague ones (`helper`,
|
|
667
|
-
* `utils`); `disable-model-invocation: true` for side-effectful workflows you
|
|
668
|
-
* want to time yourself; `user-invocable: false` for background knowledge
|
|
669
|
-
* that is not a command; `metadata` is the sanctioned home for versioning —
|
|
670
|
-
* there is no top-level `version` field.
|
|
671
663
|
*/
|
|
672
664
|
export const skillDefaultContract = [
|
|
673
665
|
clause(required("name"), {
|
|
@@ -770,14 +762,18 @@ export const supportingDocDefaultContract = [
|
|
|
770
762
|
}),
|
|
771
763
|
];
|
|
772
764
|
/**
|
|
773
|
-
* The default contract for `command` —
|
|
774
|
-
*
|
|
775
|
-
*
|
|
776
|
-
*
|
|
777
|
-
*
|
|
778
|
-
* retrieved 2026-07-
|
|
765
|
+
* The default contract for `command` — deliberately empty. A command is a lone
|
|
766
|
+
* markdown file whose frontmatter is entirely optional, matching the Claude Code
|
|
767
|
+
* runtime's documented flexibility. Where a skill requires `name` and
|
|
768
|
+
* `description` by the Agent Skills open standard, a command file may carry any,
|
|
769
|
+
* all, or none of them — identity comes from the filename stem, not a field
|
|
770
|
+
* (code.claude.com/docs/en/slash-commands, retrieved 2026-07-22).
|
|
771
|
+
*
|
|
772
|
+
* A command that passes here holds no contract constraint and loads everywhere
|
|
773
|
+
* the format is honored. The strictness stays with the skill kind, which enforces
|
|
774
|
+
* the portable profile for skill directories.
|
|
779
775
|
*/
|
|
780
|
-
export const commandDefaultContract =
|
|
776
|
+
export const commandDefaultContract = [];
|
|
781
777
|
/**
|
|
782
778
|
* The default contract for `agent` — Anthropic's documented subagent contract
|
|
783
779
|
* (code.claude.com/docs/en/sub-agents, retrieved 2026-07-15): `name` and
|
|
@@ -826,16 +822,6 @@ export const agentDefaultContract = [
|
|
|
826
822
|
* own: `required` is the one
|
|
827
823
|
* presence predicate, and its absence is not itself a predicate.)
|
|
828
824
|
* https://code.claude.com/docs/en/memory#path-specific-rules (retrieved 2026-07-15)
|
|
829
|
-
*
|
|
830
|
-
* What the clauses cannot carry, as guidance: keep a rule to facts Claude
|
|
831
|
-
* should hold whenever the rule is in scope — concrete enough to verify ("use
|
|
832
|
-
* 2-space indentation", not "format code properly"). If an entry is a
|
|
833
|
-
* multi-step procedure or only matters occasionally, it belongs in a skill
|
|
834
|
-
* (on-demand) rather than a rule (always-on). Prefer path-scoped rules when
|
|
835
|
-
* one convention governs scattered paths; prefer per-directory CLAUDE.md when
|
|
836
|
-
* directory owners maintain their own. Treat rules like code: prune them when
|
|
837
|
-
* behavior drifts, and test a change by watching whether Claude's behavior
|
|
838
|
-
* actually shifts.
|
|
839
825
|
*/
|
|
840
826
|
export const ruleDefaultContract = [
|
|
841
827
|
clause(forbiddenKeys(["description", "globs", "alwaysApply"]), {
|
|
@@ -869,21 +855,6 @@ export const ruleDefaultContract = [
|
|
|
869
855
|
* schema to gate — manufacturing a required field or a forbidden-key list
|
|
870
856
|
* would fake a check the format does not carry. The single clause is a context-cost
|
|
871
857
|
* budget; everything else the contract could say is guidance.
|
|
872
|
-
*
|
|
873
|
-
* What the clauses cannot carry, as guidance: a `paths:` frontmatter block
|
|
874
|
-
* belongs on a `.claude/rules/*.md` file, not on `CLAUDE.md` — the memory
|
|
875
|
-
* docs document `paths` only for rules, so a rules-style header on
|
|
876
|
-
* `CLAUDE.md` is dead configuration. Split a large file with `@path` imports
|
|
877
|
-
* (resolved relative to the importing file, absolute allowed, recursion
|
|
878
|
-
* capped at four hops; wrap a path in backticks to mention it without
|
|
879
|
-
* importing). If the repo already ships an `AGENTS.md` for other agents,
|
|
880
|
-
* don't duplicate it — create a `CLAUDE.md` that `@AGENTS.md`-imports it (or
|
|
881
|
-
* symlink, except on Windows where the import is the recommended bridge).
|
|
882
|
-
* Mind the loading asymmetry: every ancestor `CLAUDE.md` loads in full at
|
|
883
|
-
* launch, while files in subdirectories load only when Claude reads a file
|
|
884
|
-
* there — so a rule that must always hold belongs above the working
|
|
885
|
-
* directory, not below it. Personal, un-shared notes go in `CLAUDE.local.md`
|
|
886
|
-
* (gitignored), appended after `CLAUDE.md` at its level.
|
|
887
858
|
*/
|
|
888
859
|
export const memoryAnthropicDefaultContract = [
|
|
889
860
|
clause(extent("lines", 200), {
|
|
@@ -947,10 +918,6 @@ const DOCUMENTED_HOOK_EVENTS = [
|
|
|
947
918
|
* vocabulary's when/enumOf/type extensions, addressing still cannot spell a path into the
|
|
948
919
|
* handler array (e.g., `hooks.<Event>[0].type`). A clause over it would range over a field
|
|
949
920
|
* the read never surfaces, so it is no clause at all — the addressing-reach gap remains.
|
|
950
|
-
* What the clauses cannot carry, as guidance: keep a handler's `type` among
|
|
951
|
-
* `command`/`http`/`mcp_tool`/`prompt`/`agent`; a `command` handler needs a `command`, an
|
|
952
|
-
* `http` handler a `url`; the `matcher` filters tool-scoped events and is inert on events
|
|
953
|
-
* that carry no tool (`UserPromptSubmit`, `Stop`, and their siblings).
|
|
954
921
|
*/
|
|
955
922
|
export const hookDefaultContract = [
|
|
956
923
|
clause(enumOf("event", DOCUMENTED_HOOK_EVENTS), {
|
|
@@ -959,6 +926,29 @@ export const hookDefaultContract = [
|
|
|
959
926
|
cite: "https://code.claude.com/docs/en/hooks (retrieved 2026-07-15)",
|
|
960
927
|
}),
|
|
961
928
|
];
|
|
929
|
+
/**
|
|
930
|
+
* The `settings.json` lifecycle event and matcher one documented telemetry event-name
|
|
931
|
+
* projects its tap hook at. The event-name is the author-facing token a telemetry
|
|
932
|
+
* verifier names (`contract.ts`'s `telemetry`, the `roster.rs` admissibility set); the
|
|
933
|
+
* `event` is the `hooks.<Event>` key the tap registers under, and the `matcher` scopes
|
|
934
|
+
* the fire to the telemetry-relevant subset — each an external fact
|
|
935
|
+
* (code.claude.com/docs/en/hooks, retrieved 2026-07-17):
|
|
936
|
+
*
|
|
937
|
+
* - `InstructionsLoaded` fires on a rule/memory load; its matcher filters the load
|
|
938
|
+
* reason, and `path_glob_match` is the lazy per-path load the coverage tap reads.
|
|
939
|
+
* - `SkillInvoked` is a skill invocation, surfaced under `PostToolUse` with the tool-name
|
|
940
|
+
* matcher `Skill` — the tap's own read of a skill call.
|
|
941
|
+
* - `UserPromptExpansion` fires on a command expansion; its matcher filters the command
|
|
942
|
+
* name, `.*` capturing every one.
|
|
943
|
+
* - `ToolUse` fires after any tool call; its matcher filters the tool name, `.*`
|
|
944
|
+
* capturing every one.
|
|
945
|
+
*/
|
|
946
|
+
export const TELEMETRY_EVENT_HOOKS = {
|
|
947
|
+
InstructionsLoaded: { event: "InstructionsLoaded", matcher: "path_glob_match" },
|
|
948
|
+
SkillInvoked: { event: "PostToolUse", matcher: "Skill" },
|
|
949
|
+
UserPromptExpansion: { event: "UserPromptExpansion", matcher: ".*" },
|
|
950
|
+
ToolUse: { event: "PostToolUse", matcher: ".*" },
|
|
951
|
+
};
|
|
962
952
|
/**
|
|
963
953
|
* Every documented `.mcp.json` server transport — the closed set a server entry's `type`
|
|
964
954
|
* is drawn from (code.claude.com/docs/en/mcp, retrieved 2026-07-15). `stdio` is the
|
package/dist/src/contract.d.ts
CHANGED
|
@@ -274,9 +274,8 @@ export declare const script: (path: string) => Verifier;
|
|
|
274
274
|
/**
|
|
275
275
|
* A telemetry verifier — the named documented harness events the emitted tap records
|
|
276
276
|
* to a local-locus log, judged by reading the field record. Each name must be a
|
|
277
|
-
* documented harness lifecycle event
|
|
278
|
-
* `
|
|
279
|
-
* 2026-07-17) — the gate checks each resolves, never records into it.
|
|
277
|
+
* documented harness lifecycle event — the gate checks each resolves, never records
|
|
278
|
+
* into it. See `TELEMETRY_EVENT_HOOKS` in `declarations.ts` for the vocabulary.
|
|
280
279
|
*/
|
|
281
280
|
export declare const telemetry: (events: readonly string[]) => Verifier;
|
|
282
281
|
/**
|
package/dist/src/contract.js
CHANGED
|
@@ -208,9 +208,8 @@ export const script = (path) => ({ species: "script", path });
|
|
|
208
208
|
/**
|
|
209
209
|
* A telemetry verifier — the named documented harness events the emitted tap records
|
|
210
210
|
* to a local-locus log, judged by reading the field record. Each name must be a
|
|
211
|
-
* documented harness lifecycle event
|
|
212
|
-
* `
|
|
213
|
-
* 2026-07-17) — the gate checks each resolves, never records into it.
|
|
211
|
+
* documented harness lifecycle event — the gate checks each resolves, never records
|
|
212
|
+
* into it. See `TELEMETRY_EVENT_HOOKS` in `declarations.ts` for the vocabulary.
|
|
214
213
|
*/
|
|
215
214
|
export const telemetry = (events) => ({ species: "telemetry", events });
|
|
216
215
|
/** An identity helper — types a requirement literal at the keystroke. */
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
* in lockstep.
|
|
10
10
|
*/
|
|
11
11
|
import type { Harness } from "./assembly.js";
|
|
12
|
-
import type { MentionScope } from "./prose.js";
|
|
13
12
|
import type { Declarations, Payload, RegistrationRow, SettingsRow } from "./generated/index.js";
|
|
14
13
|
export type { AssemblyFactRow, ClauseRow, Declarations, KindFactRow, RequirementRow, SatisfiesRow, } from "./generated/index.js";
|
|
15
14
|
/** The stable-sort ordering every declaration row family shares. */
|
|
@@ -56,6 +55,12 @@ export type RenderedExtents = ReadonlyMap<string, RenderedExtent>;
|
|
|
56
55
|
* If a fields-only member declares no collection address — it surfaces in no host manifest.
|
|
57
56
|
*/
|
|
58
57
|
export declare function registrationRows(harness: Harness): RegistrationRow[];
|
|
58
|
+
/**
|
|
59
|
+
* Builds a collision-safe dedup key for a tap hook (event, matcher) pair.
|
|
60
|
+
* Two distinct pairs cannot produce the same key (e.g., ("Foo", "BarBaz") ≠ ("FooBar", "Baz")).
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildTapHookDedupeKey(event: string, matcher: string): string;
|
|
59
64
|
/**
|
|
60
65
|
* The synthesized tap-hook `registration` rows — one deduped `hooks.<Event>`
|
|
61
66
|
* registration per (lifecycle event, matcher) any telemetry verifier names. Scans the
|
|
@@ -97,8 +102,6 @@ export declare function declaredAddresses(harness: Harness): Set<string>;
|
|
|
97
102
|
* flat `kind:name` mention of one has no discovery locus to defer to.
|
|
98
103
|
*/
|
|
99
104
|
export declare function declaredAtLocusKinds(harness: Harness): Set<string>;
|
|
100
|
-
/** The full {@link MentionScope} the program resolves a mention against — its addresses and its deferral kinds. */
|
|
101
|
-
export declare function mentionScope(harness: Harness): MentionScope;
|
|
102
105
|
/**
|
|
103
106
|
* Compile a harness into its seven declaration families — the erased program.
|
|
104
107
|
*
|
|
@@ -110,8 +113,6 @@ export declare function mentionScope(harness: Harness): MentionScope;
|
|
|
110
113
|
* or `extent` clause, so a whole compile goes through `emit`, never this alone.
|
|
111
114
|
*/
|
|
112
115
|
export declare function compileDeclarations(harness: Harness, placements?: EdgePlacements, extents?: RenderedExtents): Declarations;
|
|
113
|
-
/** The SDK's pinned engine/interchange version — the JSON pipe rides it in lockstep. */
|
|
114
|
-
export declare const SEAM_VERSION = 2;
|
|
115
116
|
/**
|
|
116
117
|
* Serialize the seam payload to the internal versioned JSON pipe — `encodeSeam`
|
|
117
118
|
* stamps `version`, so the caller supplies the rest of the {@link Payload}.
|
package/dist/src/declarations.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
12
12
|
import { isTextSpan, resolveLeaf } from "./prose.js";
|
|
13
|
+
import { SETTINGS_MANIFEST, TELEMETRY_EVENT_HOOKS } from "./builtins.js";
|
|
13
14
|
/**
|
|
14
15
|
* Compile one `Clause` into its lock row: the shared `key`/`field`/`severity`/
|
|
15
16
|
* `guidance`/`cite` columns — the clause's four channels surviving erasure
|
|
@@ -228,7 +229,7 @@ function collectionAddressRow(facts) {
|
|
|
228
229
|
* the same spelling, absent for the committed default. `templates` names the embedded kinds the
|
|
229
230
|
* corpus admits over it, and `content` lowers a declared layout (absent for a
|
|
230
231
|
* `file`-content kind). A registration kind extends the row with its `shape` marker and
|
|
231
|
-
* `collection_address`.
|
|
232
|
+
* `collection_address`. Advisory `guidance`/`cite` pair rides alongside (decision 0045).
|
|
232
233
|
*/
|
|
233
234
|
function kindFactRow(facts, admissions) {
|
|
234
235
|
if (facts.locus.kind === "embedded") {
|
|
@@ -250,6 +251,8 @@ function kindFactRow(facts, admissions) {
|
|
|
250
251
|
content: contentRow(facts.content),
|
|
251
252
|
shape: facts.shape,
|
|
252
253
|
collection_address: collectionAddressRow(facts),
|
|
254
|
+
guidance: facts.guidance,
|
|
255
|
+
cite: facts.cite,
|
|
253
256
|
};
|
|
254
257
|
}
|
|
255
258
|
/**
|
|
@@ -629,28 +632,13 @@ export function registrationRows(harness) {
|
|
|
629
632
|
* (`src/tap.rs`). Every synthesized hook's `command` field carries it verbatim. */
|
|
630
633
|
const TAP_COMMAND = "temper tap";
|
|
631
634
|
/**
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
635
|
-
* `event` is the `hooks.<Event>` key the tap registers under, and the `matcher` scopes
|
|
636
|
-
* the fire to the telemetry-relevant subset — each an external fact
|
|
637
|
-
* (code.claude.com/docs/en/hooks, retrieved 2026-07-17):
|
|
638
|
-
*
|
|
639
|
-
* - `InstructionsLoaded` fires on a rule/memory load; its matcher filters the load
|
|
640
|
-
* reason, and `path_glob_match` is the lazy per-path load the coverage tap reads.
|
|
641
|
-
* - `SkillInvoked` is a skill invocation, surfaced under `PostToolUse` with the tool-name
|
|
642
|
-
* matcher `Skill` — the tap's own read of a skill call.
|
|
643
|
-
* - `UserPromptExpansion` fires on a command expansion; its matcher filters the command
|
|
644
|
-
* name, `.*` capturing every one.
|
|
645
|
-
* - `ToolUse` fires after any tool call; its matcher filters the tool name, `.*`
|
|
646
|
-
* capturing every one.
|
|
635
|
+
* Builds a collision-safe dedup key for a tap hook (event, matcher) pair.
|
|
636
|
+
* Two distinct pairs cannot produce the same key (e.g., ("Foo", "BarBaz") ≠ ("FooBar", "Baz")).
|
|
637
|
+
* @internal
|
|
647
638
|
*/
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
UserPromptExpansion: { event: "UserPromptExpansion", matcher: ".*" },
|
|
652
|
-
ToolUse: { event: "PostToolUse", matcher: ".*" },
|
|
653
|
-
};
|
|
639
|
+
export function buildTapHookDedupeKey(event, matcher) {
|
|
640
|
+
return JSON.stringify([event, matcher]);
|
|
641
|
+
}
|
|
654
642
|
/**
|
|
655
643
|
* The synthesized tap-hook `registration` rows — one deduped `hooks.<Event>`
|
|
656
644
|
* registration per (lifecycle event, matcher) any telemetry verifier names. Scans the
|
|
@@ -671,7 +659,7 @@ export function tapHookRows(harness) {
|
|
|
671
659
|
for (const name of requirement.verifier.events) {
|
|
672
660
|
const mapping = TELEMETRY_EVENT_HOOKS[name];
|
|
673
661
|
if (mapping !== undefined)
|
|
674
|
-
deduped.set(
|
|
662
|
+
deduped.set(buildTapHookDedupeKey(mapping.event, mapping.matcher), mapping);
|
|
675
663
|
}
|
|
676
664
|
};
|
|
677
665
|
for (const requirement of Object.values(harness.require))
|
|
@@ -694,12 +682,6 @@ export function tapHookRows(harness) {
|
|
|
694
682
|
],
|
|
695
683
|
}));
|
|
696
684
|
}
|
|
697
|
-
/**
|
|
698
|
-
* The manifest Claude Code's harness-level settings reside in — the file the assembly's
|
|
699
|
-
* residual settings keys fold into as opaque residue, the same manifest the `hook` kind's
|
|
700
|
-
* registrations surface inside (code.claude.com/docs/en/settings, retrieved 2026-07-10).
|
|
701
|
-
*/
|
|
702
|
-
const SETTINGS_MANIFEST = "settings.json";
|
|
703
685
|
/**
|
|
704
686
|
* The `settings` rows — the assembly's harness-level residual settings keys, each folded
|
|
705
687
|
* into the settings.json manifest's opaque residue at emit. Key-sorted so double emit is
|
|
@@ -757,7 +739,7 @@ export function declaredAtLocusKinds(harness) {
|
|
|
757
739
|
return new Set(atLocusKindsInPlay(kindsInPlay(harness)).map((facts) => facts.name));
|
|
758
740
|
}
|
|
759
741
|
/** The full {@link MentionScope} the program resolves a mention against — its addresses and its deferral kinds. */
|
|
760
|
-
|
|
742
|
+
function mentionScope(harness) {
|
|
761
743
|
return { mentionable: declaredAddresses(harness), deferrableKinds: declaredAtLocusKinds(harness) };
|
|
762
744
|
}
|
|
763
745
|
/**
|
|
@@ -793,7 +775,7 @@ export function compileDeclarations(harness, placements, extents) {
|
|
|
793
775
|
};
|
|
794
776
|
}
|
|
795
777
|
/** The SDK's pinned engine/interchange version — the JSON pipe rides it in lockstep. */
|
|
796
|
-
|
|
778
|
+
const SEAM_VERSION = 2;
|
|
797
779
|
/**
|
|
798
780
|
* Serialize the seam payload to the internal versioned JSON pipe — `encodeSeam`
|
|
799
781
|
* stamps `version`, so the caller supplies the rest of the {@link Payload}.
|
package/dist/src/emit.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Harness } from "./assembly.js";
|
|
12
12
|
import type { Member } from "./kind.js";
|
|
13
|
-
import type { Declarations
|
|
13
|
+
import type { Declarations } from "./declarations.js";
|
|
14
14
|
import type { PayloadMember } from "./generated/index.js";
|
|
15
15
|
export type { PayloadMember } from "./generated/index.js";
|
|
16
16
|
/** What a mention may resolve against at emit. */
|
|
@@ -30,27 +30,6 @@ export interface ResolveOptions {
|
|
|
30
30
|
*/
|
|
31
31
|
readonly members?: ReadonlyMap<string, Member>;
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Every composed embedded value's placed edge fields, keyed by the value's
|
|
35
|
-
* {@link placementKey} — what `emit` hands {@link compileDeclarations} so each
|
|
36
|
-
* `nested_member` row carries its own format's placement record. Iterates exactly the
|
|
37
|
-
* values `nestedMemberRows` does, so every edge-bearing row it builds has an observation.
|
|
38
|
-
*/
|
|
39
|
-
export declare function edgePlacements(harness: Harness, options: ResolveOptions): Map<string, string[]>;
|
|
40
|
-
/**
|
|
41
|
-
* Every composed embedded value's rendered extent — the line and character count of the
|
|
42
|
-
* block `emit` projected for it — keyed by its {@link placementKey}, what `emit` hands
|
|
43
|
-
* {@link compileDeclarations} so each `nested_member` row carries the span an `extent`
|
|
44
|
-
* clause budgets. Iterates exactly the values {@link edgePlacements} does, rendering each
|
|
45
|
-
* through the same {@link renderMemberBlock} the body projection uses (a hook is pure, so
|
|
46
|
-
* the measured render and the projected one cannot disagree), never a second renderer.
|
|
47
|
-
*
|
|
48
|
-
* A value the SDK composes is always rendered here, so it always captures a span; a value
|
|
49
|
-
* no format rendered — an embedded member read off a layout host's source — is lowered by
|
|
50
|
-
* the engine, not this pass, and reaches its row with no span (the `placed_edges`
|
|
51
|
-
* distinction between an observed empty and an unobserved absence).
|
|
52
|
-
*/
|
|
53
|
-
export declare function renderedExtents(harness: Harness, options: ResolveOptions): Map<string, RenderedExtent>;
|
|
54
33
|
/**
|
|
55
34
|
* One fields-only registration member erased for the manifest write face: its key
|
|
56
35
|
* (a hook's lifecycle event, an MCP server's name), the collection address it keys
|
package/dist/src/emit.js
CHANGED
|
@@ -348,7 +348,7 @@ function placedEdges(host, value, options) {
|
|
|
348
348
|
* `nested_member` row carries its own format's placement record. Iterates exactly the
|
|
349
349
|
* values `nestedMemberRows` does, so every edge-bearing row it builds has an observation.
|
|
350
350
|
*/
|
|
351
|
-
|
|
351
|
+
function edgePlacements(harness, options) {
|
|
352
352
|
const placements = new Map();
|
|
353
353
|
for (const member of harness.members) {
|
|
354
354
|
if (member.prose?.kind !== "blocks")
|
|
@@ -389,7 +389,7 @@ function renderedLineCount(block) {
|
|
|
389
389
|
* the engine, not this pass, and reaches its row with no span (the `placed_edges`
|
|
390
390
|
* distinction between an observed empty and an unobserved absence).
|
|
391
391
|
*/
|
|
392
|
-
|
|
392
|
+
function renderedExtents(harness, options) {
|
|
393
393
|
const extents = new Map();
|
|
394
394
|
for (const member of harness.members) {
|
|
395
395
|
if (member.prose?.kind !== "blocks")
|
|
@@ -79,4 +79,13 @@ export type KindFactRow = {
|
|
|
79
79
|
* file-locus kind, so an ordinary row stays byte-identical.
|
|
80
80
|
*/
|
|
81
81
|
collection_address?: CollectionAddressRow;
|
|
82
|
+
/**
|
|
83
|
+
* Advisory authoring counsel for the kind as a whole — teaching at authoring time via
|
|
84
|
+
* `schema` hover or `explain`, carrying no predicate or severity (decision 0045).
|
|
85
|
+
*/
|
|
86
|
+
guidance?: string;
|
|
87
|
+
/**
|
|
88
|
+
* External-fact source backing the guidance — a doc URL plus retrieved date.
|
|
89
|
+
*/
|
|
90
|
+
cite?: string;
|
|
82
91
|
};
|
package/dist/src/kind.d.ts
CHANGED
|
@@ -210,6 +210,12 @@ export interface KindFacts {
|
|
|
210
210
|
/** Fact 7, template — one {@link Template} per inner layer of nested members the kind
|
|
211
211
|
* hosts; absent for a kind that nests nothing. */
|
|
212
212
|
readonly templates?: readonly Template[];
|
|
213
|
+
/** Advisory authoring counsel for the kind as a whole — teaching at authoring time via
|
|
214
|
+
* `schema` hover or `explain`, carrying no predicate or severity (decision 0045). */
|
|
215
|
+
readonly guidance?: string;
|
|
216
|
+
/** External-fact source backing the guidance — a doc URL plus retrieved date,
|
|
217
|
+
* carried as data. */
|
|
218
|
+
readonly cite?: string;
|
|
213
219
|
}
|
|
214
220
|
/**
|
|
215
221
|
* One authored member — a typed value in the library. Kind identity travels by
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dtmd/temper",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "The temper authoring face — the six-noun model as typed modules: harness(), kind<T>(), clause values, needs, and file()/text/blocks(). Emit compiles to the declaration rows the engine reads, a byte-faithful projection, and the lock.",
|
|
5
5
|
"license": "(MIT OR Apache-2.0)",
|
|
6
6
|
"repository": {
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"temper": "bin/temper.js"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
|
-
"@dtmd/temper-linux-x64": "0.0.
|
|
56
|
-
"@dtmd/temper-win32-x64": "0.0.
|
|
55
|
+
"@dtmd/temper-linux-x64": "0.0.12",
|
|
56
|
+
"@dtmd/temper-win32-x64": "0.0.12"
|
|
57
57
|
}
|
|
58
58
|
}
|