@dtmd/temper 0.0.7 → 0.0.8
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 +84 -53
- package/bin/temper.js +0 -0
- package/dist/src/assembly.d.ts +15 -1
- package/dist/src/assembly.js +2 -1
- package/dist/src/builtins.d.ts +682 -66
- package/dist/src/builtins.js +664 -92
- package/dist/src/claude-code.d.ts +2 -2
- package/dist/src/claude-code.js +1 -1
- package/dist/src/contract.d.ts +180 -29
- package/dist/src/contract.js +128 -15
- package/dist/src/declarations.d.ts +72 -5
- package/dist/src/declarations.js +389 -107
- package/dist/src/dial.d.ts +75 -0
- package/dist/src/dial.js +82 -0
- package/dist/src/emit.d.ts +35 -1
- package/dist/src/emit.js +369 -63
- package/dist/src/generated/AssemblyFactRow.d.ts +2 -2
- package/dist/src/generated/BoundRow.d.ts +2 -2
- package/dist/src/generated/ClauseRow.d.ts +73 -3
- package/dist/src/generated/CollectionAddressRow.d.ts +4 -0
- package/dist/src/generated/EmbeddedMember.d.ts +3 -3
- package/dist/src/generated/FeatureValue.d.ts +2 -2
- package/dist/src/generated/Features.d.ts +52 -3
- package/dist/src/generated/KindFactRow.d.ts +24 -7
- package/dist/src/generated/MentionRow.d.ts +5 -3
- package/dist/src/generated/NestedMemberRow.d.ts +32 -0
- package/dist/src/generated/PayloadMember.d.ts +6 -0
- package/dist/src/generated/RequirementRow.d.ts +4 -2
- package/dist/src/generated/SatisfiesRow.d.ts +2 -1
- package/dist/src/generated/Shape.d.ts +15 -0
- package/dist/src/generated/Shape.js +2 -0
- package/dist/src/generated/TemplateRow.d.ts +24 -0
- package/dist/src/generated/TemplateRow.js +2 -0
- package/dist/src/generated/ValueType.d.ts +11 -2
- package/dist/src/generated/Verifier.d.ts +20 -0
- package/dist/src/generated/Verifier.js +2 -0
- package/dist/src/generated/index.d.ts +3 -0
- package/dist/src/index.d.ts +8 -8
- package/dist/src/index.js +3 -3
- package/dist/src/kind.d.ts +135 -29
- package/dist/src/kind.js +35 -8
- package/dist/src/prose.d.ts +81 -25
- package/dist/src/prose.js +91 -21
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,55 +1,86 @@
|
|
|
1
|
-
# temper
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
# @dtmd/temper
|
|
2
|
+
|
|
3
|
+
_A type system for the documents that program agents._
|
|
4
|
+
|
|
5
|
+
One package, two faces: the `temper` CLI (a prebuilt binary that needs no
|
|
6
|
+
runtime once it is on disk) and the typed SDK for authoring a Claude Code
|
|
7
|
+
harness as a program. The full story, the CLI reference, and the spec corpus
|
|
8
|
+
live in the [repository](https://github.com/duct-tape-and-markdown/temper).
|
|
9
|
+
|
|
10
|
+
## Check a harness
|
|
11
|
+
|
|
12
|
+
Point it at any repo with a `.claude/`. No config, no project file, nothing
|
|
13
|
+
installed:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npx @dtmd/temper check --harness .
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
It validates every skill, rule, and agent against the documented Anthropic
|
|
20
|
+
schemas and best practices, then reports what is malformed, what Claude Code
|
|
21
|
+
silently ignores, and what a requirement you declared would strand. Every
|
|
22
|
+
finding arrives with its guidance attached.
|
|
23
|
+
|
|
24
|
+
## Wire the gate into a project
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
npx @dtmd/temper install
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`install` opens with a report of what it finds in your harness, then asks one
|
|
31
|
+
question: represent it as a temper program? Answering no wires the advisory
|
|
32
|
+
session-start report alone, one settings entry. Answering yes converts each
|
|
33
|
+
discovered artifact into a typed member module, your prose byte-for-byte
|
|
34
|
+
intact, and runs the first emit.
|
|
35
|
+
|
|
36
|
+
## Author the harness as a program
|
|
37
|
+
|
|
38
|
+
A harness is a small typed program: members are typed values, composition is
|
|
39
|
+
ordinary imports, and requirements are declared next to the members that fill
|
|
40
|
+
them:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { emit, harness } from "@dtmd/temper";
|
|
44
|
+
import { memory_CLAUDE } from "./memory/CLAUDE.ts";
|
|
45
|
+
import { rule_collaboration } from "./rules/collaboration.ts";
|
|
46
|
+
import { skill_captureFriction } from "./skills/capture-friction.ts";
|
|
47
|
+
|
|
48
|
+
const program = harness({
|
|
49
|
+
require: {
|
|
50
|
+
"friction-capture-procedure": {
|
|
51
|
+
prose: "an agent that hits harness friction needs a procedure for filing the capture",
|
|
52
|
+
required: true,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
members: [memory_CLAUDE, rule_collaboration, skill_captureFriction],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
process.stdout.write(emit(program).seam);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`temper emit` compiles the program into the projected `.claude/**` files and
|
|
62
|
+
a lock, byte-for-byte reproducible; it verifies itself by emitting twice.
|
|
63
|
+
`temper check` gates against the lock, so it can answer what fills each
|
|
64
|
+
requirement and what would strand it. A hand edit to a generated file
|
|
65
|
+
surfaces as drift routed to its authored source, never merged around. The SDK
|
|
66
|
+
implements no semantics: every type erases at the seam, and the engine
|
|
9
67
|
consumes only declared data, offline, no Node.
|
|
10
68
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
One deterministic pass over the harness, double-emit verified
|
|
31
|
-
(`specs/model/pipeline.md`, "Emit"):
|
|
32
|
-
|
|
33
|
-
- **Declaration rows** — the erased program (kind facts, clauses, requirements,
|
|
34
|
-
assembly facts) on the internal versioned JSON pipe and in the lock's
|
|
35
|
-
`[declaration]` families, byte-matching the Rust lock shape (`src/drift.rs`) —
|
|
36
|
-
the byte-parity lockstep two writers keep until single-writer lands.
|
|
37
|
-
- **A byte-faithful projection** — each `rule` / `skill` / `memory` member
|
|
38
|
-
compiled whole to its `.claude/**` locus; install's placement lines round-trip.
|
|
39
|
-
- **The lock** — rollup provenance/emit fingerprints plus the declaration rows.
|
|
40
|
-
|
|
41
|
-
Emit is **total** (members are the only source), **refuses** before it writes on
|
|
42
|
-
a broken source (a dangling `satisfies`, an unfilled `required`, an unresolved
|
|
43
|
-
mention), and is **byte-reproducible**. `writeEmit` lands the lock and the
|
|
44
|
-
projection on disk; the JSON pipe is in-flight, not a committed artifact.
|
|
45
|
-
|
|
46
|
-
## Stated bounds — each a named follow-on, never silently faked
|
|
47
|
-
|
|
48
|
-
- **The permission union is carried as data** — the fold into the settings
|
|
49
|
-
artifact lands with the hook/MCP kinds it folds many-to-one.
|
|
50
|
-
|
|
51
|
-
## Tests
|
|
52
|
-
|
|
53
|
-
`pnpm --dir sdk test` — `tsc` (the keystroke wall) then `node --test`, including
|
|
54
|
-
projection byte-parity and lock fingerprints against real Rust output, and the
|
|
55
|
-
declaration-row byte shape against the Rust `[declaration]` families.
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
- [CLI reference](https://github.com/duct-tape-and-markdown/temper/blob/main/docs/cli.md),
|
|
72
|
+
the seven verbs
|
|
73
|
+
- [How it works](https://github.com/duct-tape-and-markdown/temper/blob/main/docs/how-it-works.md),
|
|
74
|
+
the model in plain words
|
|
75
|
+
- [Why it exists](https://github.com/duct-tape-and-markdown/temper/blob/main/specs/intent.md)
|
|
76
|
+
|
|
77
|
+
## Platforms
|
|
78
|
+
|
|
79
|
+
Prebuilt binaries ship for Linux and Windows (x64), macOS next. On other
|
|
80
|
+
platforms, build from source with a Rust 1.96+ toolchain (`cargo install
|
|
81
|
+
--path .` from a clone of the repository).
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
Dual-licensed under **MIT OR Apache-2.0**. You may use `temper` under the
|
|
86
|
+
terms of either.
|
package/bin/temper.js
CHANGED
|
File without changes
|
package/dist/src/assembly.d.ts
CHANGED
|
@@ -17,6 +17,17 @@ export interface ExpectBinding {
|
|
|
17
17
|
readonly kind: KindDefinition<never>;
|
|
18
18
|
readonly clauses: readonly Clause[];
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* One `admit` declaration — the adopting corpus naming, for one `host` kind, the
|
|
22
|
+
* embedded kinds its composed body admits. An embedded kind declares no host, so
|
|
23
|
+
* admission is the corpus's call, not the child's: a shipped kind's composed body
|
|
24
|
+
* admits corpus-declared types by this declaration alone. Keyed by kind **value**
|
|
25
|
+
* the way {@link ExpectBinding} keys `expect`; absent, a host admits nothing.
|
|
26
|
+
*/
|
|
27
|
+
export interface Admission {
|
|
28
|
+
readonly host: KindDefinition<never>;
|
|
29
|
+
readonly admits: readonly KindDefinition<never>[];
|
|
30
|
+
}
|
|
20
31
|
/**
|
|
21
32
|
* The declared enforcement-mode vocabulary — how firmly the `PreToolUse` guard
|
|
22
33
|
* binds a tool call, split by where the finding goes.
|
|
@@ -32,6 +43,8 @@ export interface Harness {
|
|
|
32
43
|
readonly members: readonly Member[];
|
|
33
44
|
/** Universal clause bindings, keyed by kind value. */
|
|
34
45
|
readonly expect: readonly ExpectBinding[];
|
|
46
|
+
/** The embedded kinds each host kind's composed body admits, keyed by kind value. */
|
|
47
|
+
readonly admit: readonly Admission[];
|
|
35
48
|
/** Existential obligations the harness must contain a fill for, keyed by name. */
|
|
36
49
|
readonly require: Readonly<Record<string, Requirement>>;
|
|
37
50
|
/** The residual harness-level settings with no member home (a shrinking list). */
|
|
@@ -44,7 +57,7 @@ export interface Harness {
|
|
|
44
57
|
readonly mode: EnforcementMode;
|
|
45
58
|
}
|
|
46
59
|
/**
|
|
47
|
-
* Compose the harness from its
|
|
60
|
+
* Compose the harness from its six fields — ordinary code, Turing-completeness
|
|
48
61
|
* quarantined at authoring time. Absent
|
|
49
62
|
* fields default empty (`mode` defaults `warn`); the member list is the
|
|
50
63
|
* only required part.
|
|
@@ -52,6 +65,7 @@ export interface Harness {
|
|
|
52
65
|
export declare function harness(init: {
|
|
53
66
|
members: readonly Member[];
|
|
54
67
|
expect?: readonly ExpectBinding[];
|
|
68
|
+
admit?: readonly Admission[];
|
|
55
69
|
require?: Readonly<Record<string, Requirement>>;
|
|
56
70
|
settings?: Readonly<Record<string, unknown>>;
|
|
57
71
|
mode?: EnforcementMode;
|
package/dist/src/assembly.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* composing partial harnesses is ordinary code.
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
|
-
* Compose the harness from its
|
|
10
|
+
* Compose the harness from its six fields — ordinary code, Turing-completeness
|
|
11
11
|
* quarantined at authoring time. Absent
|
|
12
12
|
* fields default empty (`mode` defaults `warn`); the member list is the
|
|
13
13
|
* only required part.
|
|
@@ -16,6 +16,7 @@ export function harness(init) {
|
|
|
16
16
|
return {
|
|
17
17
|
members: init.members,
|
|
18
18
|
expect: init.expect ?? [],
|
|
19
|
+
admit: init.admit ?? [],
|
|
19
20
|
require: init.require ?? {},
|
|
20
21
|
settings: init.settings ?? {},
|
|
21
22
|
mode: init.mode ?? "warn",
|