instar 1.2.68 → 1.2.69
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/commands/server.js +1 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +9 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/StandardsRegistryParser.d.ts +50 -0
- package/dist/core/StandardsRegistryParser.d.ts.map +1 -0
- package/dist/core/StandardsRegistryParser.js +120 -0
- package/dist/core/StandardsRegistryParser.js.map +1 -0
- package/dist/core/reviewers/standards-conformance.d.ts +49 -0
- package/dist/core/reviewers/standards-conformance.d.ts.map +1 -0
- package/dist/core/reviewers/standards-conformance.js +120 -0
- package/dist/core/reviewers/standards-conformance.js.map +1 -0
- package/dist/core/types.d.ts +10 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/server/AgentServer.d.ts +2 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +19 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +1 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/specReviewRoutes.d.ts +32 -0
- package/dist/server/specReviewRoutes.d.ts.map +1 -0
- package/dist/server/specReviewRoutes.js +120 -0
- package/dist/server/specReviewRoutes.js.map +1 -0
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +3 -3
- package/upgrades/1.2.69.md +73 -0
- package/upgrades/side-effects/standards-conformance-gate.md +87 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec-review HTTP routes — the standards-conformance gate surface.
|
|
3
|
+
*
|
|
4
|
+
* POST /spec/conformance-check — check a spec against the constitution → report
|
|
5
|
+
* GET /spec/conformance-metrics — observability funnel (runs, per-standard flags)
|
|
6
|
+
*
|
|
7
|
+
* Signal-only (spec §4): returns a report; never blocks. Operator/skill-callable;
|
|
8
|
+
* classified INTERNAL (build-time tool, not an agent-discoverable runtime capability).
|
|
9
|
+
*
|
|
10
|
+
* Spec: docs/specs/standards-conformance-gate.md §3, §5.
|
|
11
|
+
*/
|
|
12
|
+
import { Router } from 'express';
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import { loadStandardsRegistry, parseStandardsRegistry, runRegistryCanary } from '../core/StandardsRegistryParser.js';
|
|
16
|
+
import { StandardsConformanceReviewer } from '../core/reviewers/standards-conformance.js';
|
|
17
|
+
function emptyMetrics() {
|
|
18
|
+
return { runs: 0, degraded: 0, findings_total: 0, by_standard: {}, last_run_at: null };
|
|
19
|
+
}
|
|
20
|
+
function loadMetrics(file) {
|
|
21
|
+
try {
|
|
22
|
+
if (fs.existsSync(file)) {
|
|
23
|
+
const m = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
24
|
+
return { ...emptyMetrics(), ...m, by_standard: m.by_standard ?? {} };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch { /* corrupt → fresh */ }
|
|
28
|
+
return emptyMetrics();
|
|
29
|
+
}
|
|
30
|
+
function saveMetrics(file, m) {
|
|
31
|
+
try {
|
|
32
|
+
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
33
|
+
fs.writeFileSync(tmp, JSON.stringify(m, null, 2));
|
|
34
|
+
fs.renameSync(tmp, file);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
console.error(`[specReviewRoutes] metrics save failed: ${err}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function createSpecReviewRoutes(deps) {
|
|
41
|
+
const router = Router();
|
|
42
|
+
const enabled = deps.enabled !== false;
|
|
43
|
+
const metricsFile = path.join(deps.stateDir, 'spec-conformance-metrics.json');
|
|
44
|
+
const reviewer = new StandardsConformanceReviewer(deps.intelligence, { model: deps.model });
|
|
45
|
+
if (!enabled) {
|
|
46
|
+
router.use('/spec', (_req, res) => res.status(503).json({ error: 'spec conformance gate disabled' }));
|
|
47
|
+
return router;
|
|
48
|
+
}
|
|
49
|
+
/** Resolve a caller-supplied specPath safely within specsDir (block traversal). */
|
|
50
|
+
function resolveSpecPath(specPath) {
|
|
51
|
+
const resolved = path.resolve(deps.specsDir, specPath);
|
|
52
|
+
const base = path.resolve(deps.specsDir);
|
|
53
|
+
if (resolved !== base && !resolved.startsWith(base + path.sep))
|
|
54
|
+
return null;
|
|
55
|
+
return resolved;
|
|
56
|
+
}
|
|
57
|
+
router.post('/spec/conformance-check', async (req, res) => {
|
|
58
|
+
let markdown;
|
|
59
|
+
if (typeof req.body?.markdown === 'string' && req.body.markdown.trim()) {
|
|
60
|
+
markdown = req.body.markdown;
|
|
61
|
+
}
|
|
62
|
+
else if (typeof req.body?.specPath === 'string' && req.body.specPath.trim()) {
|
|
63
|
+
const p = resolveSpecPath(req.body.specPath);
|
|
64
|
+
if (!p)
|
|
65
|
+
return res.status(400).json({ error: 'specPath escapes specsDir' });
|
|
66
|
+
if (!fs.existsSync(p))
|
|
67
|
+
return res.status(404).json({ error: 'spec not found' });
|
|
68
|
+
try {
|
|
69
|
+
markdown = fs.readFileSync(p, 'utf-8');
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
return res.status(500).json({ error: `read failed: ${err.message}` });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return res.status(400).json({ error: 'provide markdown or specPath' });
|
|
77
|
+
}
|
|
78
|
+
if (typeof markdown !== 'string' || !markdown.trim()) {
|
|
79
|
+
return res.status(400).json({ error: 'empty spec content' });
|
|
80
|
+
}
|
|
81
|
+
// Load + canary the constitution; a drifted/partial registry must not silently
|
|
82
|
+
// produce a misleadingly-clean report.
|
|
83
|
+
let articles;
|
|
84
|
+
try {
|
|
85
|
+
articles = loadStandardsRegistry(deps.registryPath);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
return res.status(503).json({ error: `constitution unreadable: ${err.message}` });
|
|
89
|
+
}
|
|
90
|
+
const canary = runRegistryCanary(articles);
|
|
91
|
+
const report = await reviewer.review(markdown, articles);
|
|
92
|
+
// Record metrics (best-effort).
|
|
93
|
+
try {
|
|
94
|
+
const m = loadMetrics(metricsFile);
|
|
95
|
+
m.runs += 1;
|
|
96
|
+
if (report.degraded)
|
|
97
|
+
m.degraded += 1;
|
|
98
|
+
m.findings_total += report.findings.length;
|
|
99
|
+
for (const f of report.findings)
|
|
100
|
+
m.by_standard[f.standard] = (m.by_standard[f.standard] ?? 0) + 1;
|
|
101
|
+
m.last_run_at = report.checkedAt;
|
|
102
|
+
saveMetrics(metricsFile, m);
|
|
103
|
+
}
|
|
104
|
+
catch { /* metering best-effort */ }
|
|
105
|
+
res.json({ report, registryCanary: canary });
|
|
106
|
+
});
|
|
107
|
+
router.get('/spec/conformance-metrics', (_req, res) => {
|
|
108
|
+
res.json({ metrics: loadMetrics(metricsFile) });
|
|
109
|
+
});
|
|
110
|
+
return router;
|
|
111
|
+
}
|
|
112
|
+
/** Exposed for the CLI (no HTTP): run a conformance check on raw markdown. */
|
|
113
|
+
export async function runConformanceCheck(markdown, registryMarkdown, intelligence, model) {
|
|
114
|
+
const articles = parseStandardsRegistry(registryMarkdown);
|
|
115
|
+
const canary = runRegistryCanary(articles);
|
|
116
|
+
const reviewer = new StandardsConformanceReviewer(intelligence, { model });
|
|
117
|
+
const report = await reviewer.review(markdown, articles);
|
|
118
|
+
return { report, registryCanary: canary };
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=specReviewRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specReviewRoutes.js","sourceRoot":"","sources":["../../src/server/specReviewRoutes.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-05-
|
|
5
|
-
"instarVersion": "1.2.
|
|
4
|
+
"generatedAt": "2026-05-25T03:15:08.421Z",
|
|
5
|
+
"instarVersion": "1.2.69",
|
|
6
6
|
"entryCount": 191,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -1440,7 +1440,7 @@
|
|
|
1440
1440
|
"type": "subsystem",
|
|
1441
1441
|
"domain": "server",
|
|
1442
1442
|
"sourcePath": "src/server/AgentServer.ts",
|
|
1443
|
-
"contentHash": "
|
|
1443
|
+
"contentHash": "038365abc27a181166c64817b88b92dd4cd4fdcf33d9444040da91ba9f821f5b",
|
|
1444
1444
|
"since": "2025-01-01"
|
|
1445
1445
|
},
|
|
1446
1446
|
"subsystem:session-manager": {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Upgrade Guide — the review gate now reads the constitution
|
|
2
|
+
|
|
3
|
+
<!-- bump: minor -->
|
|
4
|
+
<!-- minor = new features, new APIs, new capabilities (backwards-compatible) -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
**The constitution stops being a doc nobody checks.**
|
|
9
|
+
|
|
10
|
+
The living constitution (`docs/STANDARDS-REGISTRY.md`) has been on main for a
|
|
11
|
+
while, but nothing actually *read* it when a new spec was written — the
|
|
12
|
+
"check this against the standards" step was a prompt the reviewer had to remember,
|
|
13
|
+
and on some hosts the tool that runs it isn't even installed. So a spec could
|
|
14
|
+
break a standard and slip through: the North Star draft quietly violated **No
|
|
15
|
+
Manual Work**, the review missed it, and only Justin caught it. The rulebook
|
|
16
|
+
existed with no inspector — the exact "shipped but asleep" trap the rulebook was
|
|
17
|
+
written to fight, turned on itself.
|
|
18
|
+
|
|
19
|
+
This builds the inspector:
|
|
20
|
+
|
|
21
|
+
- **A registry parser** reads the constitution into structured articles, with a
|
|
22
|
+
**canary** so a formatting change can't silently hide half the rulebook (it
|
|
23
|
+
asserts a sane article count and that anchor articles parse).
|
|
24
|
+
- **A conformance reviewer** checks a draft spec against every article and returns
|
|
25
|
+
a rule-by-rule report ("this part might break No-Manual-Work, here's why"). It
|
|
26
|
+
runs on the subscription LLM path (never a raw API client), is degrade-safe (a
|
|
27
|
+
down provider yields an empty report, never blocks spec work), and is
|
|
28
|
+
prompt-injection-hardened (the spec is treated as untrusted data).
|
|
29
|
+
- **It SIGNALS, never blocks.** The report advises; the human + the existing
|
|
30
|
+
approval gate decide. Blocking authority is a deliberate later step, gated on
|
|
31
|
+
measured precision.
|
|
32
|
+
- **Observability**: `GET /spec/conformance-metrics` shows runs and which standards
|
|
33
|
+
get flagged most — the heat map of where our drafts drift, which itself feeds
|
|
34
|
+
evolution.
|
|
35
|
+
|
|
36
|
+
Default-on (`specReview.conformance.enabled`); 503-stubs cleanly where the
|
|
37
|
+
constitution isn't present.
|
|
38
|
+
|
|
39
|
+
**Evidence**: 20 new tests across all three tiers (10 unit, 6 integration, 4 e2e)
|
|
40
|
+
— 117 related (discoverability/config/route) tests green; `tsc` + lint clean
|
|
41
|
+
(including the no-raw-LLM-HTTP guard). The Tier-3 e2e reproduces the motivating
|
|
42
|
+
incident in miniature: a spec whose design requires manual work is fed to the gate
|
|
43
|
+
and flagged against **No Manual Work**, while a conforming spec is not (no false
|
|
44
|
+
positive). The parser is verified against the real on-disk constitution (22
|
|
45
|
+
articles, canary green).
|
|
46
|
+
|
|
47
|
+
Spec: `docs/specs/standards-conformance-gate.md` (approved; Claude-authored +
|
|
48
|
+
manual review — full multi-model convergence tooling absent on host, caveat
|
|
49
|
+
ratified explicitly). ELI16: `docs/specs/standards-conformance-gate.eli16.md`.
|
|
50
|
+
Side-effects: `upgrades/side-effects/standards-conformance-gate.md`.
|
|
51
|
+
|
|
52
|
+
## What to Tell Your User
|
|
53
|
+
|
|
54
|
+
- **The rulebook now checks the work**: "When I write a new plan, a checker now
|
|
55
|
+
reads our actual standards and flags anything that might break one — so a plan
|
|
56
|
+
can't quietly violate a rule and slip past. It advises; we still decide."
|
|
57
|
+
|
|
58
|
+
## Summary of New Capabilities
|
|
59
|
+
|
|
60
|
+
| Capability | How to Use |
|
|
61
|
+
|-----------|-----------|
|
|
62
|
+
| Spec standards-conformance check | `POST /spec/conformance-check` (`{markdown}` or `{specPath}`) → rule-by-rule report |
|
|
63
|
+
| Conformance observability | `GET /spec/conformance-metrics` → runs + per-standard flag counts |
|
|
64
|
+
| Constitution parser + canary | `StandardsRegistryParser` (drift-guarded) |
|
|
65
|
+
|
|
66
|
+
## Evidence
|
|
67
|
+
|
|
68
|
+
Not a bug fix — a new capability. Verified end-to-end (not unit-mocked) by the
|
|
69
|
+
Tier-3 e2e that reproduces the motivating incident: a manual-work-requiring spec
|
|
70
|
+
is flagged against No Manual Work, a conforming spec is not. The registry parser
|
|
71
|
+
is exercised against the real on-disk constitution (22 articles parsed, canary
|
|
72
|
+
green). Signal-only by construction (no `block` path exists). 137 tests green
|
|
73
|
+
across the feature + related suites; `tsc` + lint clean.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Side-effects review — standards-conformance gate
|
|
2
|
+
|
|
3
|
+
**Scope**: Make the living constitution enforceable — a code-backed reviewer that
|
|
4
|
+
reads `docs/STANDARDS-REGISTRY.md` and signals possible standard-violations in a
|
|
5
|
+
draft spec, turning the manual/prompt-driven conformance pass into structure. The
|
|
6
|
+
rung-3 normative slice; directly fixes `[[feedback_spec_review_against_standards]]`
|
|
7
|
+
(the North Star draft violated No-Manual-Work, review missed it, Justin caught it).
|
|
8
|
+
Spec: `docs/specs/standards-conformance-gate.md` (approved; Claude-authored +
|
|
9
|
+
manual review — see honest convergence note).
|
|
10
|
+
|
|
11
|
+
**Files touched**:
|
|
12
|
+
- `src/core/StandardsRegistryParser.ts` — NEW. Deterministic parse of the
|
|
13
|
+
constitution into `{family,name,rule,inPractice}[]` (tracks the five standards
|
|
14
|
+
`##` families so non-article `###` sections — Genesis etc. — are excluded);
|
|
15
|
+
`runRegistryCanary` (state-detector: ≥15 articles + anchor articles present).
|
|
16
|
+
- `src/core/reviewers/standards-conformance.ts` — NEW. `StandardsConformanceReviewer`:
|
|
17
|
+
injected `IntelligenceProvider` (subscription path), anti-injection prompt (spec
|
|
18
|
+
fenced as untrusted data), degrade-safe (no provider/throw/unparseable → empty
|
|
19
|
+
report), drops hallucinated standards not in the registry, `capable` tier.
|
|
20
|
+
- `src/server/specReviewRoutes.ts` — NEW. `POST /spec/conformance-check` (markdown
|
|
21
|
+
or specPath, traversal-guarded) → report + registry canary; `GET
|
|
22
|
+
/spec/conformance-metrics`; file-backed metrics (reloads on restart); 503-stub
|
|
23
|
+
when disabled. Exports `runConformanceCheck` for the (deferred) CLI.
|
|
24
|
+
- `src/server/AgentServer.ts` — mount the routes; new optional `intelligence` in
|
|
25
|
+
`AgentServerOptions`.
|
|
26
|
+
- `src/commands/server.ts` — pass `intelligence: sharedIntelligence` to AgentServer.
|
|
27
|
+
- `src/server/CapabilityIndex.ts` — `spec` → `INTERNAL_PREFIXES`.
|
|
28
|
+
- `src/config/ConfigDefaults.ts` + `src/core/types.ts` — `specReview.conformance.enabled`
|
|
29
|
+
default true (auto init+migration).
|
|
30
|
+
- `docs/specs/06-state-detector-registry.md` — registry-parser row.
|
|
31
|
+
- Tests: unit/integration/e2e for the gate; updated `capabilities-discoverability`
|
|
32
|
+
to scan `specReviewRoutes.ts` (so the `spec` INTERNAL prefix resolves).
|
|
33
|
+
|
|
34
|
+
**Under-block**: The gate SIGNALS only — it cannot block anything in v1 (no code
|
|
35
|
+
path grants it authority), so it cannot wrongly stop a spec. The registry canary
|
|
36
|
+
runs on every check; a drifted/partial registry surfaces in the response
|
|
37
|
+
(`registryCanary.ok=false`) rather than silently producing a clean report. The
|
|
38
|
+
traversal guard rejects specPath escaping specsDir.
|
|
39
|
+
|
|
40
|
+
**Over-block**: None possible — signal-only. A false-positive finding costs one
|
|
41
|
+
advisory line in a report the human reads, never a blocked commit.
|
|
42
|
+
|
|
43
|
+
**Level-of-abstraction fit**: The constitution stays the single source of truth
|
|
44
|
+
(the parser reads it; nothing duplicates the standards). The reviewer reuses the
|
|
45
|
+
established LLM-reviewer pattern (injected provider, anti-injection, fail-open)
|
|
46
|
+
rather than a bespoke LLM client. The route is a thin surface over parser +
|
|
47
|
+
reviewer. Signal-vs-authority is structural: the reviewer has no `block` path.
|
|
48
|
+
|
|
49
|
+
**Signal vs authority**: The whole feature is a signal producer. The human
|
|
50
|
+
ratification + the instar-dev `approved:true` gate retain all authority. Promotion
|
|
51
|
+
to a blocking/warn signal in the precommit gate is the tracked `scg-blocking-authority`
|
|
52
|
+
follow-up, gated on measured precision.
|
|
53
|
+
|
|
54
|
+
**Interactions**:
|
|
55
|
+
- Reads `docs/STANDARDS-REGISTRY.md` from `config.projectDir/docs`. For Echo (repo
|
|
56
|
+
checkout) it's present; a deployed agent without the repo docs gets a clean 503
|
|
57
|
+
("constitution unreadable") — correct (the gate is a build-time tool, inert where
|
|
58
|
+
there's no constitution).
|
|
59
|
+
- Adds one `capable`-tier LLM call per conformance check (per-spec, rare) through
|
|
60
|
+
`sharedIntelligence` — degrade-safe, never blocks spec work if the provider is down.
|
|
61
|
+
- New `intelligence` option on AgentServer is additive (optional); existing
|
|
62
|
+
construction unaffected.
|
|
63
|
+
- File-backed metrics at `stateDir/spec-conformance-metrics.json` (atomic
|
|
64
|
+
temp+rename); corrupt → fresh.
|
|
65
|
+
|
|
66
|
+
**External surfaces**:
|
|
67
|
+
- `POST /spec/conformance-check`, `GET /spec/conformance-metrics` (INTERNAL prefix).
|
|
68
|
+
- New config `specReview.conformance.enabled` (default true).
|
|
69
|
+
- New exported `runConformanceCheck` (for the deferred CLI).
|
|
70
|
+
|
|
71
|
+
**Deferred (tracked)**: `instar spec conformance` CLI (`scg-cli`) — thin wrapper
|
|
72
|
+
over `runConformanceCheck`; the route delivers the capability. Auto-blocking
|
|
73
|
+
authority (`scg-blocking-authority`). Richer markdown parser (`scg-richer-parser`).
|
|
74
|
+
|
|
75
|
+
**Rollback cost**: Low, strictly additive. Remove the routes + reviewer + parser;
|
|
76
|
+
the constitution returns to being read only by the manual `/spec-converge` pass
|
|
77
|
+
(today's state). No existing runtime path is modified.
|
|
78
|
+
|
|
79
|
+
**Migration parity**: New server-side code + routes + config default (init +
|
|
80
|
+
`migrateConfig` via ConfigDefaults) + INTERNAL prefix. The parser reads a
|
|
81
|
+
repo-shipped doc (no per-agent state). No hook/template/skill-file change.
|
|
82
|
+
|
|
83
|
+
**Convergence honesty**: Claude-authored + manual review only; full
|
|
84
|
+
`/spec-converge` + `/crossreview` multi-model tooling absent on host. Ratified by
|
|
85
|
+
Justin with that caveat explicit. CI + the known-violating-spec e2e are the
|
|
86
|
+
strongest current evidence; a fuller multi-model review remains advisable —
|
|
87
|
+
fittingly, this is the tool that would make that conformance pass structural.
|