setspec 0.3.0__tar.gz → 0.4.0__tar.gz
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.
- {setspec-0.3.0 → setspec-0.4.0}/CHANGELOG.md +38 -0
- {setspec-0.3.0 → setspec-0.4.0}/PKG-INFO +1 -1
- setspec-0.4.0/docs/prompts-adoption-checklist.md +86 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/__about__.py +1 -1
- setspec-0.4.0/src/setspec/goldens/prompt.manifest/1.0/full.json +19 -0
- setspec-0.4.0/src/setspec/goldens/prompt.manifest/1.0/minimal.json +14 -0
- setspec-0.4.0/src/setspec/goldens/prompt.record/1.0/full.json +54 -0
- setspec-0.4.0/src/setspec/goldens/prompt.record/1.0/minimal.json +10 -0
- setspec-0.4.0/src/setspec/prompts.py +940 -0
- setspec-0.4.0/src/setspec/schemas/prompt.manifest/1.0.json +37 -0
- setspec-0.4.0/src/setspec/schemas/prompt.record/1.0.json +70 -0
- setspec-0.4.0/tests/unit/test_prompts.py +350 -0
- {setspec-0.3.0 → setspec-0.4.0}/.editorconfig +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/.github/workflows/ci.yml +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/.github/workflows/release.yml +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/.gitignore +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/.importlinter +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/.pre-commit-config.yaml +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/CONTRIBUTING.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/LICENSE +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/PHASE4_ISSUES.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/README.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/SECURITY.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/docs/README.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/docs/packages/setspec/development-plan.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/docs/packages/setspec/spec.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/docs/schemas.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/pyproject.toml +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/requirements/README.md +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/requirements/ci.lock +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/requirements/release.in +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/requirements/release.lock +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/__init__.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/artifacts.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/base.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/benchmark/v1.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/capability/v1.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/envelope.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/error/v1.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/errors.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/event/v1.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goal/v1.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.calibration_report/1.0/full.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.calibration_report/1.0/gate_failed.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.calibration_report/1.0/minimal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.evidence_bundle/1.0/full.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.evidence_bundle/1.0/minimal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.evidence_bundle/1.0/unsupported.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.goal_pack/1.0/full.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.goal_pack/1.0/minimal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.goal_pack/1.0/starter_unforked.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.result/1.0/full.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.result/1.0/minimal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.result/1.0/unsupported.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.run_summary/1.0/full.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.run_summary/1.0/minimal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/benchmark.run_summary/1.0/unsupported.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/capability.evidence/1.0/full.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/capability.evidence/1.0/goal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/capability.evidence/1.0/minimal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/capability.evidence/1.0/unsupported.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/machine.profile/1.0/full.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/machine.profile/1.0/minimal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/machine.profile/1.0/unsupported.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/model.identity/1.0/full.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/model.identity/1.0/minimal.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/goldens/model.identity/1.0/unsupported.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/machine/v1.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/metrics.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/model/v1.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/provenance.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/py.typed +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/schemas/benchmark.calibration_report/1.0.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/schemas/benchmark.evidence_bundle/1.0.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/schemas/benchmark.goal_pack/1.0.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/schemas/benchmark.result/1.0.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/schemas/benchmark.run_summary/1.0.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/schemas/capability.evidence/1.0.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/schemas/machine.profile/1.0.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/schemas/model.identity/1.0.json +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/serialization.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/src/setspec/vocabulary.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/conftest.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/contract/test_cross_version.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/contract/test_goldens.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/contract/test_schema_snapshots.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/contract/test_version_negotiation.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_base.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_envelope.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_errors.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_events.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_metrics.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_payloads_benchmark.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_payloads_capability.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_payloads_goal.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_serialization.py +0 -0
- {setspec-0.3.0 → setspec-0.4.0}/tests/unit/test_vocabulary.py +0 -0
|
@@ -7,6 +7,44 @@ packaging and release standards §3.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0] — 2026-08-29
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`setspec.prompts`** (Phase 5): prompt records and prompt packs, moved from
|
|
15
|
+
`freeweight.services.prompts` — `PromptRecord`, `PromptLibrary`, `load_record()`, `load_pack()`,
|
|
16
|
+
`build_manifest()`/`write_manifest()`, and the pack's three hashes
|
|
17
|
+
(`prompt_record_hash`/`prompt_subset_hash`/`pack_hash`, ADR-0028). Rendering runs through a
|
|
18
|
+
sandboxed, loader-less Jinja2 `Environment` with `StrictUndefined` (prompt-management-standards
|
|
19
|
+
§2.1): a referenced-but-unsupplied variable is an error, a template cannot reach the filesystem,
|
|
20
|
+
and dunder attribute access is refused. `load_pack()`'s `root` parameter is required — the
|
|
21
|
+
package carries no opinion about an application's pack layout; an application wanting a default
|
|
22
|
+
location supplies its own thin wrapper (FreeWeight's `freeweight.services.prompts.load_pack`
|
|
23
|
+
keeps its old default this way).
|
|
24
|
+
|
|
25
|
+
FreeWeight's own prompt pack adopts this module in the same change (pulling its P12 forward):
|
|
26
|
+
`freeweight.services.prompts` is now a re-export shim over `setspec.prompts`, verified to
|
|
27
|
+
produce a byte-identical `pack_hash` and per-record hash for every shipped prompt before and
|
|
28
|
+
after the move, with FreeWeight's own gate green afterwards. Two applications reading the same
|
|
29
|
+
pack format from two processes is the scenario ADR-0028's hashes exist for; the FreeWeight move
|
|
30
|
+
is the first proof of it.
|
|
31
|
+
|
|
32
|
+
- **JSON Schema for `prompt.record` and `prompt.manifest`**, committed as package data under
|
|
33
|
+
`setspec/schemas/prompt.record/1.0.json` and `setspec/schemas/prompt.manifest/1.0.json`, with
|
|
34
|
+
golden examples under `setspec/goldens/prompt.{record,manifest}/1.0/{full,minimal}.json`. Both
|
|
35
|
+
are hand-authored rather than generated: `PromptRecord` is a plain dataclass, not a pydantic
|
|
36
|
+
envelope payload — a prompt record is a pack file on disk, never wrapped in a `SchemaEnvelope` —
|
|
37
|
+
so neither schema is registered in `PUBLISHED_SCHEMAS`/reachable through `json_schema_for()`,
|
|
38
|
+
and the goldens are illustrative examples rather than inputs to the envelope contract-test
|
|
39
|
+
matrix in `tests/contract/test_goldens.py`. Every golden round-trips through the real
|
|
40
|
+
`load_pack()` loader (not just schema validation) and its `pack_sha256` is the module's own
|
|
41
|
+
computed hash, not a hand-typed value.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- Bumped to 0.4.0 for the `setspec.prompts` addition (packaging standards §3: additive,
|
|
46
|
+
non-breaking).
|
|
47
|
+
|
|
10
48
|
## [0.3.0] — 2026-08-28
|
|
11
49
|
|
|
12
50
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: setspec
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Every versioned data contract that crosses an application boundary: benchmark results, capability evidence, event/error envelopes, prompt records.
|
|
5
5
|
Project-URL: Homepage, https://github.com/JPKell/SetSpec
|
|
6
6
|
Project-URL: Documentation, https://github.com/JPKell/SetSpec/tree/main/docs
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# `setspec.prompts` Adoption Checklist
|
|
2
|
+
|
|
3
|
+
For an application that owns a prompt pack today (its own `PromptRecord`/`load_pack`-shaped code,
|
|
4
|
+
or an equivalent) and wants to move onto `setspec.prompts` instead of maintaining a second copy of
|
|
5
|
+
prompt-record loading, hashing and rendering. Written against the first adopter, FreeWeight P12
|
|
6
|
+
(§5 below is that migration, completed); the steps are what the *next* adopter — IdeaPress or
|
|
7
|
+
LoadCoach, whichever writes its first prompt pack second — should follow.
|
|
8
|
+
|
|
9
|
+
## 1. What to delete outright
|
|
10
|
+
|
|
11
|
+
Anything that duplicates, byte-for-byte in behaviour, what `setspec.prompts` now provides:
|
|
12
|
+
`PromptRecord`/`VariableSpec`/`RenderedPrompt`/`PromptReference`/`PromptLibrary`, `load_record()`,
|
|
13
|
+
`load_pack()`, `build_manifest()`/`write_manifest()`, `prompt_record_hash()`/`prompt_subset_hash()`/
|
|
14
|
+
`pack_hash()`, and the sandboxed `StrictUndefined` Jinja2 environment. If your pack format matches
|
|
15
|
+
prompt-management-standards §2.1–§3 (schema_version/prompt_id/version/template/purpose/metadata,
|
|
16
|
+
a manifest with pack_id/pack_version/prompts/pack_sha256), there should be nothing left to keep.
|
|
17
|
+
|
|
18
|
+
## 2. The one thing every adopter supplies itself: pack location
|
|
19
|
+
|
|
20
|
+
`load_pack(root: Path, *, override_root: Path | None = None)` takes `root` as a required
|
|
21
|
+
positional argument — the package has no opinion about where an application's pack lives on disk,
|
|
22
|
+
and no default. If your call sites currently call a zero-argument `load_pack()`, write a one-line
|
|
23
|
+
wrapper in your own package that supplies your pack's fixed location and forwards everything else:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from setspec.prompts import load_pack as _setspec_load_pack, PromptLibrary
|
|
28
|
+
|
|
29
|
+
PACK_ROOT = Path(__file__).resolve().parent.parent / "prompts"
|
|
30
|
+
|
|
31
|
+
def load_pack(root: Path = PACK_ROOT, *, override_root: Path | None = None) -> PromptLibrary:
|
|
32
|
+
return _setspec_load_pack(root, override_root=override_root)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Do this even if every current call site could be edited to pass `root` explicitly — a re-export
|
|
36
|
+
shim at your old import path means the migration touches one file instead of every call site, and
|
|
37
|
+
is the difference between a multi-file diff and a four-file one (§5).
|
|
38
|
+
|
|
39
|
+
## 3. Behaviour to re-verify, not assume
|
|
40
|
+
|
|
41
|
+
* **Hashing is over `canonical_json`, not file bytes.** If you ever hashed a record file's raw
|
|
42
|
+
bytes, that is not the same value `prompt_record_hash()` produces; re-indenting a file must not
|
|
43
|
+
change its hash, and canonical-JSON hashing already guarantees that here.
|
|
44
|
+
* **Declared-and-unused is a load-time error, same as undeclared-and-used.** A variable in the
|
|
45
|
+
record's `variables` block that the template never references fails validation — not just the
|
|
46
|
+
reverse. Audit existing records for this before the first `load_pack()` call in CI.
|
|
47
|
+
See [`goldens/prompt.record/1.0/full.json`](../src/setspec/goldens/prompt.record/1.0/full.json)
|
|
48
|
+
for a record where every declared variable — including a non-string one with `min`/`max` — is
|
|
49
|
+
used in the template.
|
|
50
|
+
* **The Jinja2 environment has no loader.** `{% include %}` / `{% extends %}` fail at render time
|
|
51
|
+
(`PromptRenderError`), not load time — a template that used either against your old environment
|
|
52
|
+
needs rewriting, not just re-pointing.
|
|
53
|
+
* **`pack_hash()` is provenance, never a fingerprint input** (ADR-0028 §1). If your evidence
|
|
54
|
+
payloads folded a pack-wide hash into a capability fingerprint, stop — only
|
|
55
|
+
`prompt_subset_hash()` over the *specific prompts a benchmark declares* belongs there.
|
|
56
|
+
|
|
57
|
+
## 4. Tests that must still pass, unchanged
|
|
58
|
+
|
|
59
|
+
Whatever exercises your prompt pack today — rendering determinism, unknown-variable rejection,
|
|
60
|
+
sandboxing (no filesystem reach, no dunder attribute access from a template) — should still pass
|
|
61
|
+
against `setspec.prompts` with no change to the test's assertions, only to its imports. A test that
|
|
62
|
+
needed a new assertion to pass found a real behaviour difference; treat that as a bug to resolve,
|
|
63
|
+
not a test to relax, before shipping the migration.
|
|
64
|
+
|
|
65
|
+
## 5. Verification: FreeWeight P12 (completed)
|
|
66
|
+
|
|
67
|
+
FreeWeight adopted `setspec.prompts` in the same change that added it to `setspec` (Phase 5 pulled
|
|
68
|
+
FreeWeight's own P12 forward, rather than leaving `setspec.prompts` unused until a later phase).
|
|
69
|
+
The proof this checklist rests on:
|
|
70
|
+
|
|
71
|
+
1. **Before**: captured the pack hash and every individual record hash from FreeWeight's original,
|
|
72
|
+
pre-migration `freeweight.services.prompts` — `pack_hash: sha256:b1b0ffd0a5941fee5e0013d2a826732ea02a285b229bdc006ebd6dd25ff4ceb4`
|
|
73
|
+
plus 18 individual record hashes spanning `benchmarks.agent.goal` through `goals.judge.rubric`.
|
|
74
|
+
2. **After, direct**: loaded the same pack through `setspec.prompts.load_pack()` directly and
|
|
75
|
+
recomputed every hash — identical.
|
|
76
|
+
3. **After, through the shim**: rewrote `freeweight/services/prompts.py` as a thin re-export over
|
|
77
|
+
`setspec.prompts` (§2's pattern, `PACK_ROOT` default preserved) and recomputed through
|
|
78
|
+
FreeWeight's own public import path — identical again.
|
|
79
|
+
4. **Full gate, unchanged**: FreeWeight's complete pre-PR gate (ruff, mypy strict over 265 files,
|
|
80
|
+
import-linter, pytest) passed with no test assertions changed — 2297 passed, 28 skipped, 21
|
|
81
|
+
deselected (performance). The only non-shim source edit was 3 import statements in
|
|
82
|
+
`tests/security/test_goal_pack_import.py`, which reached into the module's private
|
|
83
|
+
`_environment()` directly for a sandboxing assertion; every other call site needed no change.
|
|
84
|
+
|
|
85
|
+
Final diff: 4 files changed. The next adopter should expect a diff of similar shape — one shim
|
|
86
|
+
file, a dependency bump, and an edit only where a test reached past the public API.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pack_id": "freeweight.core",
|
|
3
|
+
"pack_version": "1.4.0",
|
|
4
|
+
"schema_version": "1.0",
|
|
5
|
+
"generated_at": "2026-08-21T00:00:00Z",
|
|
6
|
+
"prompts": [
|
|
7
|
+
{
|
|
8
|
+
"prompt_id": "stages.draft.article",
|
|
9
|
+
"version": "2.1.0",
|
|
10
|
+
"sha256": "sha256:2316b1ae73d0298e17a78677e2da9fd5f0b664ae09cc3dd7625f26921a9630c5"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"prompt_id": "stages.notify.digest",
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"sha256": "sha256:21829b05324468ff96ddb14ea45d4ca3a3409c4d0928f1475089aa0467c276a0"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"pack_sha256": "sha256:39e13d67c588be76c08d82073e8de6953c73974740d1ceedf1d66394d5e4efef"
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pack_id": "ideapress.core",
|
|
3
|
+
"pack_version": "1.0.0",
|
|
4
|
+
"schema_version": "1.0",
|
|
5
|
+
"generated_at": "1970-01-01T00:00:00Z",
|
|
6
|
+
"prompts": [
|
|
7
|
+
{
|
|
8
|
+
"prompt_id": "stages.notify.digest",
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"sha256": "sha256:21829b05324468ff96ddb14ea45d4ca3a3409c4d0928f1475089aa0467c276a0"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"pack_sha256": "sha256:2f0a1d2047e54d2dac5da63af4ee49a5e50c6bf931af9fe105374f73c89f6e7f"
|
|
14
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1.0",
|
|
3
|
+
"prompt_id": "stages.draft.article",
|
|
4
|
+
"version": "2.1.0",
|
|
5
|
+
"purpose": "Produce a first draft of one article section from a compiled requirement set.",
|
|
6
|
+
"system": "You are drafting one section of an article. Follow every hard requirement.",
|
|
7
|
+
"template": "SECTION: {{ section_title }}\n\nREQUIREMENTS\n{{ requirements_json }}\n\nCONTEXT\n{{ context }}\n\nWrite roughly {{ word_target }} words.",
|
|
8
|
+
"variables": {
|
|
9
|
+
"section_title": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"required": true,
|
|
12
|
+
"description": "Human-readable section title"
|
|
13
|
+
},
|
|
14
|
+
"requirements_json": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"required": true,
|
|
17
|
+
"description": "Canonical JSON of compiled requirements"
|
|
18
|
+
},
|
|
19
|
+
"context": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"required": false,
|
|
22
|
+
"default": "",
|
|
23
|
+
"description": "Bounded prior context"
|
|
24
|
+
},
|
|
25
|
+
"word_target": {
|
|
26
|
+
"type": "integer",
|
|
27
|
+
"required": false,
|
|
28
|
+
"default": 800,
|
|
29
|
+
"min": 100,
|
|
30
|
+
"max": 5000,
|
|
31
|
+
"description": "Target word count for the drafted section"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"task": "content.article_draft",
|
|
35
|
+
"capability": "creative_writing",
|
|
36
|
+
"response": {
|
|
37
|
+
"format": "text",
|
|
38
|
+
"json_schema_ref": null,
|
|
39
|
+
"expectations": ["No headings above H3", "No meta-commentary about being an AI"]
|
|
40
|
+
},
|
|
41
|
+
"model_requirements": {
|
|
42
|
+
"min_context_tokens": 8192,
|
|
43
|
+
"requires_capabilities": [],
|
|
44
|
+
"recommended_temperature": 0.7
|
|
45
|
+
},
|
|
46
|
+
"metadata": {
|
|
47
|
+
"author": "suite",
|
|
48
|
+
"created_at": "2026-08-21T00:00:00Z",
|
|
49
|
+
"changed_at": "2026-08-21T00:00:00Z",
|
|
50
|
+
"change_reason": "Tightened the requirement-compliance instruction after audit-pass regressions.",
|
|
51
|
+
"supersedes": "2.0.0",
|
|
52
|
+
"tags": ["content", "draft"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": "1.0",
|
|
3
|
+
"prompt_id": "stages.notify.digest",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"purpose": "Static prompt with no variables, exercising the record format's floor.",
|
|
6
|
+
"template": "Summarize today's queue in three bullet points.",
|
|
7
|
+
"metadata": {
|
|
8
|
+
"change_reason": "Initial version."
|
|
9
|
+
}
|
|
10
|
+
}
|