@typedstandards/civic-typed-harness 0.4.0 → 0.4.1
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/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,97 @@
|
|
|
3
3
|
Factual record of what changed per published version. Section references are
|
|
4
4
|
to the Typed Standards specification unless noted otherwise.
|
|
5
5
|
|
|
6
|
+
## 0.4.1 — 2026-09-12
|
|
7
|
+
|
|
8
|
+
Patch: one existing export changes its output for one input shape, and no
|
|
9
|
+
export is added, removed or retyped. That is measured across the release
|
|
10
|
+
boundary rather than asserted — the published `0.4.0` and this build each
|
|
11
|
+
expose 49 runtime exports from the package root, none added, none removed,
|
|
12
|
+
none changing runtime type, and no declared top-level name in `dist/*.d.ts`
|
|
13
|
+
differing between them. The tarball carries the same 28 files, and 22 of the
|
|
14
|
+
24 under `dist/` are byte-identical to `0.4.0`; the two that are not are
|
|
15
|
+
`dist/rubric/adversarial-eval-core.js` and its `.d.ts`, the latter differing
|
|
16
|
+
by a doc comment alone.
|
|
17
|
+
|
|
18
|
+
**What this release claims about golden bytes, and what it does not.** Every
|
|
19
|
+
golden byte is unchanged. This time that sentence is not the evidence, and
|
|
20
|
+
saying so is the point: **no golden fixture reaches the export that changed.**
|
|
21
|
+
`buildEvaluationPrompt` is named in two test files, both under `src/rubric/`,
|
|
22
|
+
and in neither golden suite. `__fixtures__/website-golden.json` carries no
|
|
23
|
+
`queries` array at all; `__fixtures__/reference-golden.json` carries eight and
|
|
24
|
+
**zero** occurrences of the `failed` key that is this release's only new
|
|
25
|
+
branch. So the golden suites are green for this change the way they are green
|
|
26
|
+
for a change to a file they never import, and their green is not evidence
|
|
27
|
+
about it. This is the same narrowing
|
|
28
|
+
[civic-ai-tools#199](https://github.com/npstorey/civic-ai-tools/issues/199)
|
|
29
|
+
records for the graph builder, met from the other side.
|
|
30
|
+
|
|
31
|
+
What **is** evidence is a direct measurement of the changed export either side
|
|
32
|
+
of the release boundary: `buildEvaluationPrompt` imported from the published
|
|
33
|
+
`0.4.0` and from this build, run over the same package.
|
|
34
|
+
|
|
35
|
+
- A package in which **no entry records `failed: true`** renders
|
|
36
|
+
**byte-identical** on both — 492 bytes, `sha256 ed77c84e…` — over five entry
|
|
37
|
+
shapes: `resultRows: 12`, `resultRows: 0`, no `resultRows` at all,
|
|
38
|
+
`failed: false`, and a bare `failureKind` carrying no `failed`.
|
|
39
|
+
- The same package plus one entry recorded `failed: true` renders
|
|
40
|
+
**differently** (539 bytes against 607). That case is the reason the first
|
|
41
|
+
one is worth reporting: an instrument that answers "identical" whatever it is
|
|
42
|
+
fed has not measured anything, and this one is shown answering "different"
|
|
43
|
+
on the shape it must flag.
|
|
44
|
+
|
|
45
|
+
**The evaluator reads a rejected call as rejected**
|
|
46
|
+
([civic-ai-tools#203](https://github.com/npstorey/civic-ai-tools/issues/203),
|
|
47
|
+
Wave N11 P-H1). Behaviour change, confined to one input shape.
|
|
48
|
+
|
|
49
|
+
- **The line that changes.** A `queries[]` entry the producer recorded as
|
|
50
|
+
rejected rendered `→ ? rows` — the same line an entry whose row count was
|
|
51
|
+
simply never recorded produces. A rejection and an unrecorded count were one
|
|
52
|
+
line to the evaluator, and the rubric asks that evaluator to cross-check the
|
|
53
|
+
answer's figures against the data the tool calls returned, so the conflation
|
|
54
|
+
invited it to read data that was never returned as merely uncounted. Its
|
|
55
|
+
score becomes a signed attestation. The entry now reads `→ REJECTED by the
|
|
56
|
+
source — no data was returned, and no row count is claimed`.
|
|
57
|
+
- **`failed: true` is the whole assertion.** `failureKind` is declared on the
|
|
58
|
+
shape and **deliberately not rendered**: it is producer-controlled text, and
|
|
59
|
+
the turn built here is read by a model whose score is signed, so the
|
|
60
|
+
rejection is stated in this module's own fixed words, interpolating nothing
|
|
61
|
+
the producer wrote and claiming no row count.
|
|
62
|
+
- **Absence stays absence.** An entry that records no outcome renders exactly
|
|
63
|
+
as it did before the fields existed. `failed: false` is not a rejection, and
|
|
64
|
+
a `failureKind` with no `failed` is not a rejection — the posture
|
|
65
|
+
`ToolCallSummary.failed` already takes in `capture/data-sources.ts`.
|
|
66
|
+
- **No dependency moves.** The two keys are read off a locally-declared shape
|
|
67
|
+
rather than imported, following that same file: produce-core `0.3.0`, which
|
|
68
|
+
the lockfile resolves, names neither key. No manifest change, no lockfile
|
|
69
|
+
bump, no new dependency.
|
|
70
|
+
|
|
71
|
+
**`RUBRIC_VERSION_SHA256` does not move, and the claim around it is corrected
|
|
72
|
+
rather than left standing**
|
|
73
|
+
([civic-ai-tools#207](https://github.com/npstorey/civic-ai-tools/issues/207)).
|
|
74
|
+
The hash is `sha256Hex(EVALUATION_RUBRIC)` — the rubric text alone. It does not
|
|
75
|
+
cover `buildEvaluationPrompt`, the template that assembles that rubric with the
|
|
76
|
+
package's tool calls, data sources and model into the turn the evaluator
|
|
77
|
+
actually reads. So this release changes what an evaluator is shown without
|
|
78
|
+
changing the value an attestation pins as `methodology.promptSetVersion`: two
|
|
79
|
+
evaluations either side of it carry the same value, measured here as
|
|
80
|
+
`b62b193c992fd430cc82dff9a80a057bbe0b2b656fbdace450ca1a5d99fffa02` on both the
|
|
81
|
+
published `0.4.0` and this build.
|
|
82
|
+
|
|
83
|
+
- **The overclaim is retired in the same change.** ADR-0015 §3, Q26's
|
|
84
|
+
resolution note and the two module comments said the value pinned the whole
|
|
85
|
+
prompt set that produced the scores. They now say it pins the rubric
|
|
86
|
+
*wording*, and that the prompt template is outside the hash. The phrase they
|
|
87
|
+
used for the wider claim appears nowhere in the tree at this release.
|
|
88
|
+
- **The gap is filed, not resolved.** #207 records what the hash covers, what
|
|
89
|
+
it does not, and the two spec-level options — widen the hash, or add a second
|
|
90
|
+
field — with no recommendation. Which one is right is a specification
|
|
91
|
+
decision, not a package's.
|
|
92
|
+
|
|
93
|
+
A consumer sees none of this until its own lockfile moves: `^0.4.0` admits
|
|
94
|
+
`0.4.1`, so the manifest range need not change and the refresh is the whole of
|
|
95
|
+
the upgrade.
|
|
96
|
+
|
|
6
97
|
## 0.4.0 — 2026-09-04
|
|
7
98
|
|
|
8
99
|
Minor: two optional input fields are added and no existing export is removed
|
|
@@ -6,7 +6,10 @@ export declare const EVALUATION_CRITERIA: readonly ["dataSourceIdentification",
|
|
|
6
6
|
export declare const EVALUATION_RUBRIC = "You are an independent evaluator assessing an AI-generated civic data analysis.\n\nYou will receive:\n1. The original prompt (question asked)\n2. The tool calls made (MCP queries to Socrata open data portals)\n3. The AI's final output/analysis\n\nEvaluate the analysis against these 6 criteria, scoring each 1-10:\n\na) **Data Source Identification** (1-10): Does the output correctly identify the data source(s) and time period? Are dataset IDs, portal domains, and date ranges accurate?\n\nb) **Quantitative Claim Support** (1-10): Are the quantitative claims (numbers, percentages, rankings) supported by the data returned in the tool calls? Cross-check key figures against the raw data.\n\nc) **Confounders and Bias** (1-10): Does the analysis acknowledge obvious confounders, selection biases, or framing issues? Are there lurking variables or cherry-picked timeframes?\n\nd) **Geographic Scope** (1-10): Is the geographic scope appropriate for the question? Does the analysis avoid over-generalizing from one jurisdiction?\n\ne) **Limitations Noted** (1-10): Are limitations and caveats noted? Does the analysis flag data quality issues, missing fields, or incomplete coverage?\n\nf) **Contradictory Conclusion** (1-10): Could the same data reasonably support a contradictory conclusion? Does the analysis consider alternative interpretations?\n\nRespond in this exact JSON format (no markdown fences, just raw JSON):\n{\n \"dataSourceIdentification\": { \"score\": <1-10>, \"comment\": \"<1-2 sentences>\" },\n \"quantitativeClaimSupport\": { \"score\": <1-10>, \"comment\": \"<1-2 sentences>\" },\n \"confoundersAndBias\": { \"score\": <1-10>, \"comment\": \"<1-2 sentences>\" },\n \"geographicScope\": { \"score\": <1-10>, \"comment\": \"<1-2 sentences>\" },\n \"limitationsNoted\": { \"score\": <1-10>, \"comment\": \"<1-2 sentences>\" },\n \"contradictoryConclusion\": { \"score\": <1-10>, \"comment\": \"<1-2 sentences>\" },\n \"overallScore\": <average of all 6 scores, one decimal>,\n \"assessment\": \"<2-4 sentence overall assessment>\"\n}";
|
|
7
7
|
/** The methodology's `promptSetVersion`: SHA-256 of the rubric text, computed
|
|
8
8
|
* once at module load. Any wording change to the rubric produces a new
|
|
9
|
-
* version, so an attestation pins the
|
|
9
|
+
* version, so an attestation pins the rubric WORDING that scored it — and
|
|
10
|
+
* that wording only. The prompt template around it (`buildEvaluationPrompt`)
|
|
11
|
+
* is outside this hash, so one value does not identify one set of evaluator
|
|
12
|
+
* inputs (civic-ai-tools#207). */
|
|
10
13
|
export declare const RUBRIC_VERSION_SHA256: string;
|
|
11
14
|
/** Build the user-turn evaluation content from a package's signed fields.
|
|
12
15
|
* Takes `RecordPackage` — produce-core 0.3.0's settlement-era name for the
|
|
@@ -5,8 +5,14 @@
|
|
|
5
5
|
// brief §1. The model runner and DB/blob emission (`adversarial-eval.ts`)
|
|
6
6
|
// stay app-side — this module never performs I/O.
|
|
7
7
|
//
|
|
8
|
-
// ⚠ RUBRIC_VERSION_SHA256 is a Q26-pinned version hash
|
|
9
|
-
//
|
|
8
|
+
// ⚠ RUBRIC_VERSION_SHA256 is a Q26-pinned version hash over THE RUBRIC TEXT
|
|
9
|
+
// ALONE (`sha256Hex(EVALUATION_RUBRIC)`). It does NOT cover
|
|
10
|
+
// `buildEvaluationPrompt` below — the template that assembles the rubric with
|
|
11
|
+
// the package's tool calls, data sources and model into the turn the evaluator
|
|
12
|
+
// actually reads. So two evaluations either side of a change to that template
|
|
13
|
+
// carry the SAME `methodology.promptSetVersion` while the evaluator saw
|
|
14
|
+
// different inputs; civic-ai-tools#207 files that gap for the specification to
|
|
15
|
+
// settle, and this module does not resolve it. The rubric text below is
|
|
10
16
|
// byte-exact with the reference implementation (the relocation changes no
|
|
11
17
|
// hashes), and the test suite asserts the literal digest. Any wording change
|
|
12
18
|
// to EVALUATION_RUBRIC is a NEW rubric version — never edit the text without
|
|
@@ -57,8 +63,24 @@ Respond in this exact JSON format (no markdown fences, just raw JSON):
|
|
|
57
63
|
}`;
|
|
58
64
|
/** The methodology's `promptSetVersion`: SHA-256 of the rubric text, computed
|
|
59
65
|
* once at module load. Any wording change to the rubric produces a new
|
|
60
|
-
* version, so an attestation pins the
|
|
66
|
+
* version, so an attestation pins the rubric WORDING that scored it — and
|
|
67
|
+
* that wording only. The prompt template around it (`buildEvaluationPrompt`)
|
|
68
|
+
* is outside this hash, so one value does not identify one set of evaluator
|
|
69
|
+
* inputs (civic-ai-tools#207). */
|
|
61
70
|
export const RUBRIC_VERSION_SHA256 = sha256Hex(EVALUATION_RUBRIC);
|
|
71
|
+
/** Did the producer record this entry as REJECTED by the source? Only a
|
|
72
|
+
* literal `failed: true` is a rejection (see `RecordedCallOutcome`). */
|
|
73
|
+
function wasRecordedRejected(query) {
|
|
74
|
+
return query.failed === true;
|
|
75
|
+
}
|
|
76
|
+
/** What the evaluator is told about a call the source rejected. A FIXED
|
|
77
|
+
* string: it interpolates nothing the producer wrote, and it claims no row
|
|
78
|
+
* count — there were no rows to count, which is neither "zero rows" nor "an
|
|
79
|
+
* unknown number of rows". The rubric asks the evaluator to cross-check
|
|
80
|
+
* figures against the data returned in the tool calls, so a rejected call
|
|
81
|
+
* reading `→ ? rows` invited it to treat absent data as merely unrecorded
|
|
82
|
+
* (civic-ai-tools#203). */
|
|
83
|
+
const REJECTED_CALL_RENDERING = 'REJECTED by the source — no data was returned, and no row count is claimed';
|
|
62
84
|
/** Build the user-turn evaluation content from a package's signed fields.
|
|
63
85
|
* Takes `RecordPackage` — produce-core 0.3.0's settlement-era name for the
|
|
64
86
|
* same object (spec Appendix J, migration class alias-and-deprecate). The
|
|
@@ -70,7 +92,10 @@ export function buildEvaluationPrompt(pkg) {
|
|
|
70
92
|
const argStr = Object.entries(q.arguments)
|
|
71
93
|
.map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
72
94
|
.join(', ');
|
|
73
|
-
|
|
95
|
+
const outcome = wasRecordedRejected(q)
|
|
96
|
+
? REJECTED_CALL_RENDERING
|
|
97
|
+
: `${q.resultRows ?? '?'} rows`;
|
|
98
|
+
return ` ${i + 1}. ${q.tool}(${argStr}) → ${outcome}`;
|
|
74
99
|
})
|
|
75
100
|
.join('\n');
|
|
76
101
|
const dataSources = pkg.dataSources
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typedstandards/civic-typed-harness",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Civic-domain harness for Typed Standards evidence packages — the DOMAIN layer of the ADR-0021 format/domain line: civic PROV-O vocabulary and provenance builder, datHere envelope-policy derivations, and the capture machinery (trace builder, skill-metadata extraction, data-source population, adversarial rubric core). Derives; @typedstandards/produce-core assembles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Nathan Storey",
|