harness-everything 0.28.0 → 0.30.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +47 -0
- package/PRIVACY.md +9 -0
- package/benchmarks/fixtures/system-one-holdout-reviews.json +18 -18
- package/benchmarks/fixtures/system-one-holdout.json +9 -9
- package/benchmarks/fixtures/system-one-intent-holdout-draft.json +2228 -0
- package/benchmarks/fixtures/system-one-intent-holdout.json +16509 -0
- package/benchmarks/fixtures/system-one-intent-reviews.json +2723 -0
- package/benchmarks/results/system-one/harness-routing-v1-cpu-2026-09-24/README.md +75 -0
- package/benchmarks/results/system-one/harness-routing-v1-cpu-2026-09-24/report.json +10832 -0
- package/benchmarks/results/system-one/harness-routing-v1-ngram-2026-09-24/README.md +72 -0
- package/benchmarks/results/system-one/harness-routing-v1-ngram-2026-09-24/report.json +10817 -0
- package/benchmarks/results/system-one/harness-routing-v3-ngram-2026-09-24/README.md +63 -0
- package/benchmarks/results/system-one/harness-routing-v3-ngram-2026-09-24/report.json +10817 -0
- package/benchmarks/results/system-one/intent-ngram-v1-2026-09-24/README.md +64 -0
- package/benchmarks/results/system-one/intent-ngram-v1-2026-09-24/report.json +15177 -0
- package/benchmarks/results/system-one/labeler-holdout-check-2026-09-24/report.json +1104 -0
- package/benchmarks/results/system-one/labeler-holdout-check-codex-2026-09-24/report.json +1104 -0
- package/benchmarks/results/system-one/labeler-holdout-check-codex-tier3-2026-09-24/report.json +1104 -0
- package/benchmarks/results/system-one/labeler-holdout-check-intent-2026-09-24/report.json +2976 -0
- package/benchmarks/results/system-one/labeler-holdout-check-intent-scores-haiku-2026-09-24/report-005-steps.json +6125 -0
- package/benchmarks/results/system-one/labeler-holdout-check-intent-scores-haiku-2026-09-24/report-haiku-sonnet-escalation.json +6344 -0
- package/benchmarks/results/system-one/labeler-holdout-check-intent-scores-haiku-2026-09-24/report-scaled-margin-escalation.json +6206 -0
- package/benchmarks/results/system-one/labeler-holdout-check-intent-scores-haiku-2026-09-24/report.json +6103 -0
- package/benchmarks/results/system-one/laya-ft-2026-09-25/README.md +83 -0
- package/benchmarks/results/system-one/laya-ft-2026-09-25/report.json +71 -0
- package/benchmarks/results/system-one/laya-ft-2026-09-25/shadow-report.json +44 -0
- package/benchmarks/results/system-one/laya-zs-2026-09-25/README.md +68 -0
- package/benchmarks/results/system-one/laya-zs-2026-09-25/report.json +173 -0
- package/ci/mechanism-34-observations.test.js +550 -0
- package/ci/mechanism-system-one-collect.test.js +16 -0
- package/ci/mechanism-system-one-evaluation.test.js +17 -0
- package/ci/mechanism-system-one-intent.test.js +406 -0
- package/ci/mechanism-system-one-label.test.js +27 -0
- package/ci/mechanism-system-one-laya.test.js +45 -0
- package/ci/mechanism-system-one-ngram.test.js +161 -0
- package/ci/mechanism-system-one-relevance.test.js +112 -0
- package/ci/mechanism-system-one-resident.test.js +16 -0
- package/ci/mechanism-system-one-train.test.js +12 -0
- package/ci/system-one-laya-calibrate-test.py +65 -0
- package/ci/system-one-laya-export-test.py +155 -0
- package/ci/system-one-laya-label-test.py +201 -0
- package/ci/system-one-laya-perintent-test.py +60 -0
- package/ci/system-one-laya-provider-test.py +115 -0
- package/ci/system-one-laya-train-test.py +93 -0
- package/ci/system-one-ngram-parity.py +19 -0
- package/ci/system-one-train-test.py +6 -0
- package/docs/routing.md +25 -0
- package/docs/system-one-corpus.md +31 -3
- package/docs/system-one-intent-gates.md +102 -0
- package/docs/system-one-intent.md +173 -0
- package/docs/system-one-laya-training.md +38 -0
- package/docs/system-one-observations.md +206 -0
- package/docs/system-one-routing.md +102 -5
- package/docs/system-one-suggestion-gates.md +292 -0
- package/docs/system-one-training.md +69 -7
- package/harness-everything/SKILL.md +1 -1
- package/harness-everything/scripts/kernel-router.js +10 -0
- package/harness-everything/scripts/system-one/catalogs.js +35 -0
- package/harness-everything/scripts/system-one/contract.js +45 -1
- package/harness-everything/scripts/system-one/evaluate.js +118 -21
- package/harness-everything/scripts/system-one/intent.js +22 -0
- package/harness-everything/scripts/system-one/laya_adapter.py +141 -0
- package/harness-everything/scripts/system-one/ngram.js +84 -0
- package/harness-everything/scripts/system-one/provider.js +24 -7
- package/harness-everything/scripts/system-one/resident.js +8 -3
- package/harness-everything/scripts/system-one/router.js +1 -1
- package/hooks/hooks.json +40 -0
- package/hooks/scripts/codex-user-prompt.js +39 -0
- package/hooks/scripts/lib/observations.js +581 -0
- package/hooks/scripts/observation-hook.js +25 -0
- package/opencode-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
- package/plugins/harness-everything/hooks/hooks.json +35 -2
- package/plugins/harness-everything/hooks/scripts/codex-user-prompt.js +39 -0
- package/plugins/harness-everything/hooks/scripts/lib/observations.js +581 -0
- package/plugins/harness-everything/hooks/scripts/observation-hook.js +25 -0
- package/plugins/harness-everything/plugin.json +1 -1
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +1 -1
- package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router.js +10 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/catalogs.js +35 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/contract.js +45 -1
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/evaluate.js +118 -21
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/intent.js +22 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/laya_adapter.py +141 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/ngram.js +84 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/provider.js +24 -7
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/resident.js +8 -3
- package/plugins/harness-everything/skills/harness-everything/scripts/system-one/router.js +1 -1
- package/sbom.cdx.json +7 -7
- package/scripts/evaluate-system-one.js +32 -13
- package/scripts/system-one-calibrate-laya.py +165 -0
- package/scripts/system-one-calibrate.js +42 -13
- package/scripts/system-one-collect.js +7 -3
- package/scripts/system-one-compare-laya.py +156 -0
- package/scripts/system-one-corpus.js +22 -15
- package/scripts/system-one-eval-laya.js +112 -0
- package/scripts/system-one-export-laya.py +197 -0
- package/scripts/system-one-label-laya.py +243 -0
- package/scripts/system-one-label.js +192 -37
- package/scripts/system-one-observations-export.js +106 -0
- package/scripts/system-one-observations-review.js +86 -0
- package/scripts/system-one-perintent-laya.py +134 -0
- package/scripts/system-one-train-laya.py +344 -0
- package/scripts/system-one-train-ngram.py +181 -0
- package/scripts/system-one-train.py +14 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# System One intent promotion gates (relevance-native)
|
|
2
|
+
|
|
3
|
+
Status: **superseded** by [system-one-suggestion-gates.md](system-one-suggestion-gates.md).
|
|
4
|
+
This table remains the contract for the runs made under it (for example
|
|
5
|
+
`benchmarks/results/system-one/laya-ft-2026-09-25/`); those results are
|
|
6
|
+
never re-scored under the new gates.
|
|
7
|
+
|
|
8
|
+
Originally decided in
|
|
9
|
+
[#233](https://github.com/dyphn1/Harness-everything/issues/233) (accept
|
|
10
|
+
relevance-native direction, keep production migration gated); evidence in
|
|
11
|
+
[#255](https://github.com/dyphn1/Harness-everything/issues/255). Thresholds
|
|
12
|
+
below are proposals: they take effect only after owner review, and the final
|
|
13
|
+
holdout runs **once** against the reviewed numbers. No threshold, gate, or
|
|
14
|
+
wording change may use the frozen holdout as feedback.
|
|
15
|
+
|
|
16
|
+
This replaces the single-winner intent gates (acceptedPrecision ≥ 0.85 at
|
|
17
|
+
coverage ≥ 0.8), which a 57%-precision / 66%-recall multi-label system
|
|
18
|
+
cannot clear by construction: owner prompts carry about 2.5 secondaries on
|
|
19
|
+
average, so a single-winner contract caps coverage near 6% no matter how
|
|
20
|
+
good the ranking is.
|
|
21
|
+
|
|
22
|
+
## Ground truth
|
|
23
|
+
|
|
24
|
+
- **Training/validation truth.** Teacher relevance scores binarized at the
|
|
25
|
+
owner secondary band: intent is positive iff score ≥ 0.4
|
|
26
|
+
([system-one-intent.md](system-one-intent.md#relevance-scores)).
|
|
27
|
+
- **Holdout truth.** Owner-reviewed `{gold, secondary}` per case. A predicted
|
|
28
|
+
set is compared as sets; graded agreement still applies where the report
|
|
29
|
+
cites it, but promotion gates use the binary metrics below.
|
|
30
|
+
|
|
31
|
+
## Threshold flow (frozen)
|
|
32
|
+
|
|
33
|
+
1. Train on train rows only.
|
|
34
|
+
2. Fit one threshold per intent (max-F1) on validation, 2-fold CV reported.
|
|
35
|
+
3. Freeze thresholds, code, and this document.
|
|
36
|
+
4. Score the frozen holdout exactly once (two runs for repeatability).
|
|
37
|
+
5. Gate on the table below. A fail is a fail; re-tuning restarts at step 2
|
|
38
|
+
with a documented reason, never at step 4.
|
|
39
|
+
|
|
40
|
+
## Metrics
|
|
41
|
+
|
|
42
|
+
- **micro precision / recall / F1** over all (case, intent) pairs.
|
|
43
|
+
- **macro F1**: mean of per-intent F1.
|
|
44
|
+
- **per-intent precision / recall / support** (support = holdout positives).
|
|
45
|
+
- **predicted cardinality**: mean fires per prompt vs gold mean.
|
|
46
|
+
- **abstain rate**: prompts with no intent fired.
|
|
47
|
+
- **exact-set-match**: all 12 decisions correct (reported, not gated).
|
|
48
|
+
- **weak-intent precision**: minimum precision over intents with support.
|
|
49
|
+
- **family consistency**: model vs gold (same definition as the old gates).
|
|
50
|
+
- **repeatability**: byte-identical decisions across two runs.
|
|
51
|
+
- **latency**: warm p50/p95 per decision batch.
|
|
52
|
+
- **policy evidence**: structural controls untouched (floor, fallback,
|
|
53
|
+
abstain path, rollback availability).
|
|
54
|
+
|
|
55
|
+
## Proposed gates
|
|
56
|
+
|
|
57
|
+
Anchors: per-intent train-majority predicts nothing (micro-F1 0), so gates
|
|
58
|
+
are absolute. Reference measurement is the fine-tuned multilingual model on
|
|
59
|
+
validation teacher proxy (micro-F1 CV 0.60, fires 2.0 vs truth 1.8); holdout
|
|
60
|
+
gold is stricter, so thresholds sit below it.
|
|
61
|
+
|
|
62
|
+
| Metric | Gate | Rationale |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| micro-F1 | ≥ 0.55 | CV 0.60 minus holdout strictness margin |
|
|
65
|
+
| macro-F1 | ≥ 0.50 | reference ≈ 0.61 |
|
|
66
|
+
| per-intent F1 (support ≥ 10) | ≥ 0.30 | keeps refactor-class weak spots visible, not fatal |
|
|
67
|
+
| weak-intent precision | ≥ 0.30 | tripwire for silent degradation |
|
|
68
|
+
| mean fires | within gold mean ± 1.0 | blocks spray (4+) and collapse (<1) |
|
|
69
|
+
| abstain rate | ≤ 0.20 | reference 0.09 |
|
|
70
|
+
| family consistency (model) | ≥ gold | same bar as the old gates |
|
|
71
|
+
| repeatability | == 1 | deterministic inference required |
|
|
72
|
+
| warm p95 | ≤ 250 ms | environment-tolerant bar (see latency note) |
|
|
73
|
+
| structural controls | unchanged + rollback path live | migration stays shadow-compatible |
|
|
74
|
+
|
|
75
|
+
`rolloutReady` is true only when every gate passes. `policyEvidence` and
|
|
76
|
+
`liveHostEvidence` remain false until independently produced; they are
|
|
77
|
+
reported, not bypassed.
|
|
78
|
+
|
|
79
|
+
## Latency note
|
|
80
|
+
|
|
81
|
+
The old single-winner gate used warm p95 ≤ 100 ms. That bar flakes on
|
|
82
|
+
developer hardware for model-backed transports: the fine-tuned multilingual
|
|
83
|
+
model measured p50 135 ms / p95 179 ms on a Mac mini M4 over 444 warm
|
|
84
|
+
samples, and thermal throttling, GPU contention, or memory pressure can push
|
|
85
|
+
any single run past 100 ms without a code change. The 250 ms bar still rules
|
|
86
|
+
out pathological transports (per-request model reloads at 7–10 s, cold CPU
|
|
87
|
+
fallbacks in seconds) while tolerating host variance. For reference, the
|
|
88
|
+
MLX port of the same model class measures 7–13 ms; transport choice, not
|
|
89
|
+
the gate, is where that gap belongs. Latency evidence always ships with the
|
|
90
|
+
host record (cpu/os/node/python); a gate pass on one host is not a claim
|
|
91
|
+
about another.
|
|
92
|
+
|
|
93
|
+
## Non-goals and invariants
|
|
94
|
+
|
|
95
|
+
- The single-winner path (contract.decide as shipped, n-gram provider,
|
|
96
|
+
lexical fallback) stays live as rollback until promotion completes.
|
|
97
|
+
- Tier structural floor, explicit workflow constraints, action/security
|
|
98
|
+
approval, and scope/memory ownership stay outside learned scoring.
|
|
99
|
+
- Taxonomy is frozen: 12 intents in catalog order plus abstain. Wording
|
|
100
|
+
versions are recorded per artifact but never change categories.
|
|
101
|
+
- Private prompts never enter the public repository; public evidence holds
|
|
102
|
+
aggregates, hashes, and per-intent metrics only.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# System One intent stage: catalog and labeling
|
|
2
|
+
|
|
3
|
+
This document defines the second stage of [System One](system-one-routing.md#staged-classification):
|
|
4
|
+
the **intent** of a prompt, meaning the kind of work it asks for (issue
|
|
5
|
+
[#233](https://github.com/dyphn1/Harness-everything/issues/233)). The tier stage is
|
|
6
|
+
defined in [system-one-corpus.md](system-one-corpus.md) and is unchanged. The intent
|
|
7
|
+
stage reuses the tier pipeline in [system-one-training.md](system-one-training.md) with
|
|
8
|
+
its own catalog, labels, holdout and gates.
|
|
9
|
+
|
|
10
|
+
## Intent labels
|
|
11
|
+
|
|
12
|
+
An intent label answers one question: **what kinds of work does this prompt ask the
|
|
13
|
+
assistant to do, judged from the prompt and its session context?** The catalog is the
|
|
14
|
+
repository owner's (confirmed 2026-09-24, with `edit` added the same day) and is fixed.
|
|
15
|
+
Its order is the scorer's option order.
|
|
16
|
+
|
|
17
|
+
A label has two parts:
|
|
18
|
+
|
|
19
|
+
- **Primary.** Exactly one intent, or `null`. This is the work that produces the main
|
|
20
|
+
deliverable.
|
|
21
|
+
- **Secondary.** Zero or more other intents that the request also needs. Changing a
|
|
22
|
+
default port, for example, is primary `edit` with secondary `test` and `docs` when
|
|
23
|
+
tests and docs mention the port. Secondary never contains the primary intent or
|
|
24
|
+
`null`, and it is empty when the primary is `null`.
|
|
25
|
+
|
|
26
|
+
| Gold | Use when the prompt asks the assistant to | Examples of shape |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `explain` | Answer a question or explain how something works, without deciding anything or changing files | "what does this flag do?", "why is this test slow?" (explanation only), "今天這段 code 在做什麼" |
|
|
29
|
+
| `discuss` | Weigh options, give an opinion, or settle a decision for work in progress | "should we keep the old name?", "1. agree 2. use hash", "你覺得哪個方案好" |
|
|
30
|
+
| `git` | Perform Git or GitHub housekeeping: commit, push, branch, merge, rebase, cherry-pick, tag, open or merge a PR, post a comment | "commit and push", "開 PR", "commit the sub-repos, then the main repo" |
|
|
31
|
+
| `fix` | Repair behavior that is wrong: a bug, a crash, a failing or flaky test, a build or CI failure, a dependency conflict | "the CLI panics here, fix it", "CI times out, find the cause and fix it" |
|
|
32
|
+
| `edit` | Change an existing value, setting, text or behavior on request, when it is neither a bug nor new behavior | "change the default port from 8080 to 3000", "把 timeout 改成 30 秒", "rename the button label to Save" |
|
|
33
|
+
| `feature` | Add new behavior: a command, an option, a format, an endpoint, a script, a migration | "add a --verbose flag", "support YAML input", "寫一個資料遷移腳本" |
|
|
34
|
+
| `refactor` | Restructure or unify existing code without new behavior: rename, move, extract, replace a pattern everywhere, upgrade a dependency | "rename component to module everywhere", "replace console.log with the logger", "把常數搬出去" |
|
|
35
|
+
| `review` | Evaluate an existing artifact against a standard: a PR, a diff, a design, a document, test coverage, a benchmark result | "review this PR", "檢查測試是不是只有 happy path", "audit the skill descriptions" |
|
|
36
|
+
| `test` | Run tests or builds, or write tests as the main deliverable | "run npm test", "add tests for the parser" |
|
|
37
|
+
| `docs` | Write or edit documentation as the main deliverable: README, guides, comments, changelogs, a memory note | "update the install guide", "改成全英文文件" |
|
|
38
|
+
| `plan` | Produce a plan, specification, roadmap, ADR or breakdown before implementation | "plan phase 4", "拆分實作階段", "write an ADR for the new cache" |
|
|
39
|
+
| `investigate` | Find facts or a cause and report back, without being asked to change anything | "find every repo still using the old logger", "查一下為什麼變慢,先不要改" |
|
|
40
|
+
| `null` | Nothing actionable: a bare continuation, a vague reaction, pasted status with no request, or a request outside software work | "go", "嗯", "今天股價多少" |
|
|
41
|
+
|
|
42
|
+
Rules:
|
|
43
|
+
|
|
44
|
+
1. **One primary intent, then the rest as secondary.** The primary is the work that
|
|
45
|
+
produces the main deliverable. "Fix the bug and add a regression test" is primary
|
|
46
|
+
`fix`, secondary `test`. "Investigate and fix" is primary `fix`, secondary
|
|
47
|
+
`investigate`. "Implement the feature, then commit" is primary `feature`, secondary
|
|
48
|
+
`git`. Add a secondary intent only when the request asks for it or clearly needs it,
|
|
49
|
+
not for every step an assistant might take.
|
|
50
|
+
2. **Change beats inquiry.** When the prompt asks for a change, label the change, not
|
|
51
|
+
the reading that precedes it. `investigate` and `explain` are for prompts that only
|
|
52
|
+
ask for information.
|
|
53
|
+
3. **`investigate` against `explain`.** `investigate` needs searching or running
|
|
54
|
+
something to find facts; `explain` can be answered from what is already known or
|
|
55
|
+
shown.
|
|
56
|
+
4. **`review` against `investigate`.** `review` judges a given artifact against a
|
|
57
|
+
standard; `investigate` looks for a cause or for facts that are not yet known.
|
|
58
|
+
5. **`fix`, `edit`, `feature` and `refactor`.** Wrong behavior made right is `fix`.
|
|
59
|
+
A requested change to a value, setting, text or existing behavior that was not wrong
|
|
60
|
+
is `edit`. New behavior is `feature`. The same behavior in a new structure is
|
|
61
|
+
`refactor`.
|
|
62
|
+
6. **Short replies follow the work in progress**, as in the tier rules. A reply that
|
|
63
|
+
asks to change an output takes the intent of that change ("not this format, use the
|
|
64
|
+
table" in a docs session is `docs`). A reply that settles decisions is `discuss`.
|
|
65
|
+
7. **Intent is independent of tier.** A repository-wide `refactor` is `tier3` and a
|
|
66
|
+
one-line `refactor` is `tier2`; both are `refactor`. Never infer intent from a tier
|
|
67
|
+
label or tier from an intent label.
|
|
68
|
+
8. **Never derive gold from the lexical router or any model output.** A reviewer may
|
|
69
|
+
read a proposed intent, but the recorded gold is the reviewer's decision.
|
|
70
|
+
|
|
71
|
+
### Relevance scores
|
|
72
|
+
|
|
73
|
+
A scored label rates every intent of the catalog, except `null`, from 0 to 1 in steps of
|
|
74
|
+
0.05. The owner set this scale on 2026-09-24 (it replaces a four-level draft of the same
|
|
75
|
+
day). System One only suggests skills, so a scored label is meant to rank every candidate,
|
|
76
|
+
not to pick one.
|
|
77
|
+
|
|
78
|
+
| Score | Band |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| 0.6 or more | Primary relevance: the prompt asks for this work as a main deliverable |
|
|
81
|
+
| 0.4 to 0.55 | Secondary relevance: the request also needs this work |
|
|
82
|
+
| 0.2 to 0.35 | Related: useful context or a likely follow-up that the prompt does not ask for |
|
|
83
|
+
| 0.05 to 0.15 | Faint: a remote link to the prompt |
|
|
84
|
+
| 0 | Unrelated |
|
|
85
|
+
|
|
86
|
+
Rules:
|
|
87
|
+
|
|
88
|
+
1. **Score every intent on its own.** This replaces "add a secondary intent only when the
|
|
89
|
+
request asks for it" above for scored labels: every intent gets a considered score.
|
|
90
|
+
The scores are not a budget shared by the intents.
|
|
91
|
+
2. **No ties.** Two intents never share a score other than 0, so the scores rank the
|
|
92
|
+
whole catalog.
|
|
93
|
+
3. **At most eight zeros.** At least four intents score above 0.
|
|
94
|
+
4. **Name one primary.** It is the intent with the highest score, and it scores 0.6 or
|
|
95
|
+
more. Rule 1 above decides which work produces the main deliverable.
|
|
96
|
+
5. **`null` means nothing actionable.** With a `null` primary, no intent scores more
|
|
97
|
+
than 0.2.
|
|
98
|
+
6. **Bands give the label.** The secondary intents are every other intent that scores
|
|
99
|
+
0.4 or more, highest first. Related intents are kept only as scores.
|
|
100
|
+
|
|
101
|
+
## Holdout
|
|
102
|
+
|
|
103
|
+
The intent holdout reuses the prompts of the tier holdout
|
|
104
|
+
(`benchmarks/fixtures/system-one-holdout.json`). Their families are already
|
|
105
|
+
holdout-only, so no training prompt can leak into them. Each case gets an intent gold
|
|
106
|
+
through the same owner review as the tier holdout. An intent review decision also
|
|
107
|
+
records `secondary`, the list of secondary intents. `accept` and `relabel` refer to the
|
|
108
|
+
primary intent only. The review records live in
|
|
109
|
+
`benchmarks/fixtures/system-one-intent-reviews.json`, and the evaluation corpus is
|
|
110
|
+
`benchmarks/fixtures/system-one-intent-holdout.json`. The `reviewedHoldout` gate is the
|
|
111
|
+
same: at least 200 reviewed cases and at least 50 per language. The report also gives
|
|
112
|
+
the count per intent, because a class with only a few holdout cases cannot be measured.
|
|
113
|
+
|
|
114
|
+
**Scope.** The intent stage runs only on actionable prompts. When the tier stage
|
|
115
|
+
abstains (`unclassified`), no intent is asked. In the first review the owner rejected
|
|
116
|
+
all 25 non-actionable prompts, which left 190 cases, so the holdout gains
|
|
117
|
+
**supplementary intent-only families** (`synthetic:authored`). Those families favor
|
|
118
|
+
the thinnest intents (`test`, `plan`, `discuss`, `review`, `edit`). They are appended
|
|
119
|
+
to the intent draft, reviewed the same way, and added to the training-leakage filter
|
|
120
|
+
like every holdout prompt.
|
|
121
|
+
|
|
122
|
+
## Scoring
|
|
123
|
+
|
|
124
|
+
System One gives a probability for every intent. The highest is the predicted
|
|
125
|
+
primary, and every other intent at or above a calibrated threshold is a predicted
|
|
126
|
+
secondary. The skills stage consumes the primary intent together with the accepted
|
|
127
|
+
secondary intents.
|
|
128
|
+
|
|
129
|
+
Two intent labels are compared by **graded agreement**. Each side is a primary `p`
|
|
130
|
+
plus a secondary set `S`, and its full set is `{p} ∪ S`. The owner set these grades:
|
|
131
|
+
|
|
132
|
+
| Case | Score |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| Same primary | 1.0 |
|
|
135
|
+
| Different primaries, and each primary is in the other side's full set (only the order differs) | 0.6 |
|
|
136
|
+
| Different primaries, and only one primary is in the other side's full set; or the order differs but the secondary counts differ by 3 or more | 0.3 |
|
|
137
|
+
| Neither primary is in the other side's full set | 0 |
|
|
138
|
+
|
|
139
|
+
Both sides agreeing on intent but differing in order or in the number of steps means
|
|
140
|
+
the same goal with a different breakdown, not a different goal. Graded agreement is
|
|
141
|
+
reported next to exact primary agreement, never instead of it. The same grades apply
|
|
142
|
+
to the labeler check and to accepted predictions of a model.
|
|
143
|
+
|
|
144
|
+
**Family consistency.** A family groups variants and translations of one scenario.
|
|
145
|
+
The report gives the share of families whose members share one primary intent, for the
|
|
146
|
+
owner's gold and for the predictions. This makes a language-dependent intent visible
|
|
147
|
+
without treating every variant as a translation.
|
|
148
|
+
|
|
149
|
+
## Training data
|
|
150
|
+
|
|
151
|
+
The collected prompts are labeled a second time, for intent. The labeler returns a
|
|
152
|
+
primary and a secondary list for each prompt. Intent labels are stored beside the tier
|
|
153
|
+
labels, never in place of them. Owner spot-checks for intent show session context, like
|
|
154
|
+
the tier spot-checks. The labeler check against the intent holdout must reach a graded
|
|
155
|
+
agreement of 80% before training data is labeled.
|
|
156
|
+
|
|
157
|
+
**Scored labels.** The second intent labeling, requested by the owner on 2026-09-24,
|
|
158
|
+
asks for [relevance scores](#relevance-scores) instead of a primary and a short list.
|
|
159
|
+
The labeler returns a primary and a score for every intent. Scored labels are stored in
|
|
160
|
+
`labels-intent-scores.jsonl`, beside the earlier intent labels. Each row keeps the
|
|
161
|
+
primary as `gold`, the secondary intents derived from the bands and all the scores. The
|
|
162
|
+
labeler check grades the derived primary and secondary intents against the holdout, as
|
|
163
|
+
above. Its report also gives the mean number of secondary and related intents per
|
|
164
|
+
prompt, next to the owner's mean number of secondary intents.
|
|
165
|
+
|
|
166
|
+
## Gates
|
|
167
|
+
|
|
168
|
+
The intent stage uses the rollout gates of
|
|
169
|
+
[system-one-routing.md](system-one-routing.md#rollout-gates): accepted precision at least
|
|
170
|
+
85% (graded agreement over accepted predictions, with exact primary precision
|
|
171
|
+
reported beside it), coverage at least 80%, repeatability, warm p95 at most 100 ms and
|
|
172
|
+
verified provenance. There is no lexical intent router, so the macro-F1 baseline is the
|
|
173
|
+
majority-class predictor on the holdout.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# System One Laya weak-intent training contract
|
|
2
|
+
|
|
3
|
+
This document defines the training-data semantics used by the #255 weak-intent experiment.
|
|
4
|
+
|
|
5
|
+
## Intent-level oversampling
|
|
6
|
+
|
|
7
|
+
`system-one-export-laya.py --oversample intent:factor` is an **intent-item** intervention.
|
|
8
|
+
|
|
9
|
+
For a prompt whose teacher score for the selected intent is at least `0.4`:
|
|
10
|
+
|
|
11
|
+
- only that `promptId + intent` training item is repeated to the requested factor;
|
|
12
|
+
- sibling intents from the same prompt are emitted once;
|
|
13
|
+
- prompts below the positive threshold are not repeated;
|
|
14
|
+
- the manifest records the requested oversample map.
|
|
15
|
+
|
|
16
|
+
Example: `--oversample refactor:3` emits three copies of the positive `refactor` item, but still emits one copy each of `review`, `explain`, and every other sibling intent.
|
|
17
|
+
|
|
18
|
+
This distinction is required so a weak-intent intervention does not silently reweight neighboring intents.
|
|
19
|
+
|
|
20
|
+
## Calibration isolation
|
|
21
|
+
|
|
22
|
+
The trainer calibration split is **prompt-group disjoint**.
|
|
23
|
+
|
|
24
|
+
- All items sharing one `promptId` must stay on the same side of the train/calibration boundary.
|
|
25
|
+
- Calibration uses one copy of each `promptId + intent` identity.
|
|
26
|
+
- Oversampled duplicates are retained only for prompt groups assigned to training.
|
|
27
|
+
- Oversampling therefore cannot create an exact duplicate in both training and calibration, and it cannot overweight temperature fitting.
|
|
28
|
+
- Items without `promptId` retain the legacy per-item deterministic split behavior for unit-level callers.
|
|
29
|
+
|
|
30
|
+
The calibration selection remains deterministic for a fixed seed and continues to respect the configured fraction and `CALIB_MAX` target over the de-duplicated base identities.
|
|
31
|
+
|
|
32
|
+
## Loss weights
|
|
33
|
+
|
|
34
|
+
`system-one-train-laya.py --intent-weights '{"refactor": 2.0}'` applies a per-sample multiplier to both RL and CE losses for the named intent. Unlisted intents remain at weight `1.0`. Weights must be finite and greater than zero.
|
|
35
|
+
|
|
36
|
+
## Evidence rule
|
|
37
|
+
|
|
38
|
+
Results produced before these isolation rules were enforced must not be used as causal evidence for neighbor-intent regressions without re-running the experiment. In particular, prompt-level duplication and train/calibration duplicate leakage confound interpretation of an intent-specific intervention.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# System One observations: collecting routing data from real sessions
|
|
2
|
+
|
|
3
|
+
Status: **accepted**, 2026-09-27. Owner decisions are recorded below.
|
|
4
|
+
Implementation: `hooks/scripts/observation-hook.js`,
|
|
5
|
+
`hooks/scripts/lib/observations.js`, `scripts/system-one-observations-export.js`
|
|
6
|
+
and `scripts/system-one-observations-review.js`; tests in
|
|
7
|
+
`ci/mechanism-34-observations.test.js`. Issue
|
|
8
|
+
[#233](https://github.com/dyphn1/Harness-everything/issues/233).
|
|
9
|
+
|
|
10
|
+
## Why
|
|
11
|
+
|
|
12
|
+
Two data problems limit the System One scorers
|
|
13
|
+
([system-one-suggestion-gates.md](system-one-suggestion-gates.md)):
|
|
14
|
+
|
|
15
|
+
1. There are too few valid, text-decidable examples.
|
|
16
|
+
2. Teacher labels from an offline LLM are thin, and were often assigned with
|
|
17
|
+
session context the small model never sees.
|
|
18
|
+
|
|
19
|
+
Every Harness turn already produces better material. The host LLM sees the
|
|
20
|
+
whole conversation, states its view in the Harness Status, and then acts.
|
|
21
|
+
Recording the prompt, that view, and what the agent actually did, turn by
|
|
22
|
+
turn, gives labeled data that grows with daily use. The data covers
|
|
23
|
+
validity, intent, tier, workflow and skills.
|
|
24
|
+
|
|
25
|
+
## Owner decisions (2026-09-27)
|
|
26
|
+
|
|
27
|
+
- The host LLM adds one machine-readable label line to its final message
|
|
28
|
+
each turn. The token cost is accepted.
|
|
29
|
+
- Collection is **on by default**, with no environment variable needed to
|
|
30
|
+
enable it. `HARNESS_OBSERVATIONS=off` turns it off; this opt-out exists
|
|
31
|
+
because the plugin ships to other users.
|
|
32
|
+
- Hosts: **Claude Code** and **Codex** first.
|
|
33
|
+
- This document is the specification; implementation follows
|
|
34
|
+
docs → RED → GREEN.
|
|
35
|
+
|
|
36
|
+
## One observation per turn
|
|
37
|
+
|
|
38
|
+
A turn runs from `UserPromptSubmit` to `Stop`. Its record:
|
|
39
|
+
|
|
40
|
+
| Field | Source | Notes |
|
|
41
|
+
| --- | --- | --- |
|
|
42
|
+
| `id`, `sessionId`, `turn`, `host`, `observedAt` | hooks | `id` = hash of session id + turn |
|
|
43
|
+
| `prompt` | `UserPromptSubmit` | stored in the private text store only (see Storage) |
|
|
44
|
+
| `previous` | the last assistant message before the prompt | truncated to 2 KB; text store only |
|
|
45
|
+
| `router` | kernel-router output | lexical tier, strategy, suggested skills; System One shadow scores when present |
|
|
46
|
+
| `behavior` | `PostToolUse`, `PostToolUseFailure` | counts and categories, never arguments: files written, distinct repositories written, files created, commands by class (git, gh, test, build, package, shell), skills loaded or read, subagents started. Failed attempts are counted separately (`toolFailures`, `failedWrites`, `failedSkillLoads`) and never count as a write or a load |
|
|
47
|
+
| `workflow` | `workflow-run.json` / `workflow-disposition` | selected and confirmed strategy |
|
|
48
|
+
| `selfReport` | label line in the final message | see below; `null` if missing or invalid |
|
|
49
|
+
| `derived` | exporter | labels computed from the fields above |
|
|
50
|
+
|
|
51
|
+
### Label line
|
|
52
|
+
|
|
53
|
+
At the end of the final message of each turn the agent writes one line,
|
|
54
|
+
which is invisible in rendered Markdown:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
<!-- harness-label {"v":1,"validity":"actionable","contextDependent":false,"tier":"tier2","intents":["fix","test"],"workflow":"iterative-single","skills":["tdd"]} -->
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
| Key | Values |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `validity` | `actionable` or `invalid` (continuation, feedback on earlier work, pointer to earlier content, paste or chatter) |
|
|
63
|
+
| `contextDependent` | `true` when the prompt text alone would not have been enough to know the task |
|
|
64
|
+
| `tier` | `tier1` (no file change), `tier2` (bounded file change: code, config or docs), `tier3` (feature, refactor, redefinition, cross-component) or `null` (only for `invalid`), under tier rules v2 |
|
|
65
|
+
| `intents` | up to 3 of the 12 intent ids, strongest first |
|
|
66
|
+
| `workflow` | a router strategy id or `null` |
|
|
67
|
+
| `skills` | skill ids actually used this turn |
|
|
68
|
+
|
|
69
|
+
The line states the agent's own judgement **after** the work, not a copy of
|
|
70
|
+
the router's suggestion. A line that does not parse, or has an invalid
|
|
71
|
+
validity, tier or workflow, is recorded as `selfReport: null` with a reason
|
|
72
|
+
code; it never blocks the turn. Two slips seen in live runs are tolerated
|
|
73
|
+
rather than losing the whole label: unknown intent ids are dropped and kept
|
|
74
|
+
in `unknownIntents`, and a final label line missing its closing `-->` is
|
|
75
|
+
accepted when it ends the message.
|
|
76
|
+
|
|
77
|
+
## Labels and how much to trust them
|
|
78
|
+
|
|
79
|
+
The label is the host LLM's own judgement. It saw the whole conversation and
|
|
80
|
+
did the work, so no fixed rule replaces it (owner decision, 2026-09-27: no
|
|
81
|
+
file-count threshold for tier).
|
|
82
|
+
|
|
83
|
+
| Label | Source | Override |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| validity, contextDependent | self-report | owner review |
|
|
86
|
+
| intents | self-report | — |
|
|
87
|
+
| tier | self-report (tier rules v2) | owner review |
|
|
88
|
+
| workflow | self-report, else the confirmed strategy | — |
|
|
89
|
+
| skills | skills actually loaded or read, else the self-report | — |
|
|
90
|
+
|
|
91
|
+
Behavior counters (files, repositories, command classes, skills,
|
|
92
|
+
subagents) are kept as **evidence**, never as a label rule. They serve two
|
|
93
|
+
purposes:
|
|
94
|
+
|
|
95
|
+
- **Contradictions.** Some records contradict themselves. A `tier1` label
|
|
96
|
+
after files were written contradicts the tier1 definition (no code
|
|
97
|
+
change). These records go to the owner's review page.
|
|
98
|
+
- **Future features.** The counters can train or check later models
|
|
99
|
+
without re-reading transcripts.
|
|
100
|
+
|
|
101
|
+
**Owner review.** Missing labels, contradictions, and turns where the
|
|
102
|
+
router's tier and the self-reported tier differ go to a blind review page.
|
|
103
|
+
The owner decides validity, context dependence and tier; each decision
|
|
104
|
+
overrides the self-report, an explicit `false` included, and also labels a
|
|
105
|
+
turn that has no self-report.
|
|
106
|
+
|
|
107
|
+
**Bias controls.** The agent sees the router's suggestion before it
|
|
108
|
+
answers, so it may copy it. Router output and self-report are both stored.
|
|
109
|
+
Each export reports how often they agree, over turns where the router chose
|
|
110
|
+
a tier (`unclassified` is not a tier); a rate close to 1 over many turns is a
|
|
111
|
+
warning sign. The review page samples the turns where they differ.
|
|
112
|
+
|
|
113
|
+
## Storage, index and privacy
|
|
114
|
+
|
|
115
|
+
- **Location**: `~/.agents/harness-everything/system-one/observations/`,
|
|
116
|
+
outside every workspace. It is never written under `memories/repo`, which
|
|
117
|
+
can be committed.
|
|
118
|
+
- **Text store**: `text/<sha256>.json` holds `prompt` and `previous`, with
|
|
119
|
+
the collector's redaction applied (email addresses and home paths).
|
|
120
|
+
- **Index**: `observations-index.json` uses the `index_memory.js` record
|
|
121
|
+
shape: `schemaVersion: 1` and `records[]`. Each record has `id`,
|
|
122
|
+
`status`, `validUntil`, `contentSha256`, `scope`, `writer.sessionId` and
|
|
123
|
+
`source: "observation"`, plus the non-text fields above. `scope.taskTerms`
|
|
124
|
+
hold normalized terms, so `retrieveMemoryRecords`-style lookups can find
|
|
125
|
+
similar past turns.
|
|
126
|
+
- **Retention**: `validUntil` is 180 days after `observedAt`. An expired
|
|
127
|
+
record keeps its labels and counts, but its text is deleted. Expiry is
|
|
128
|
+
enforced on read as well: the exporter and the review page skip the text
|
|
129
|
+
of any record past `validUntil`, whether or not a later turn has swept it.
|
|
130
|
+
A text blob is content-addressed, so it is deleted only when no active
|
|
131
|
+
record references it. Session state that holds text (the previous-message
|
|
132
|
+
tail and an unfinished turn's prompt) follows the same 180 days, counted
|
|
133
|
+
from when the text was captured. Finishing or recovering an old turn never
|
|
134
|
+
renews that deadline: its record's `validUntil` comes from the capture
|
|
135
|
+
time, and a turn whose text has already expired is recorded with its
|
|
136
|
+
labels and counts but no text.
|
|
137
|
+
- **Concurrency**: tool hooks may run in parallel. Each tool event is written
|
|
138
|
+
as its own immutable file, and `Stop` adds them up, so no event is lost to
|
|
139
|
+
a concurrent read-modify-write.
|
|
140
|
+
- **Telemetry stays content-free.** The telemetry channel keeps its
|
|
141
|
+
`FORBIDDEN_KEYS` rule. Observations are a separate, local-only channel and
|
|
142
|
+
are never uploaded by Harness.
|
|
143
|
+
- `PRIVACY.md` is updated to state that prompts and the previous assistant
|
|
144
|
+
message are stored locally by default, where they are stored, how long
|
|
145
|
+
they are kept, and how to turn this off.
|
|
146
|
+
|
|
147
|
+
## Hosts
|
|
148
|
+
|
|
149
|
+
- **Claude Code**: plugin hooks `UserPromptSubmit`, `PostToolUse` and
|
|
150
|
+
`Stop`. The final message is read from the Stop payload or from the
|
|
151
|
+
transcript the payload points to.
|
|
152
|
+
- **Codex**: the same hooks. Verified live on codex-cli 0.157.1
|
|
153
|
+
(2026-09-28):
|
|
154
|
+
- Codex adds `UserPromptSubmit` context to the model only from JSON
|
|
155
|
+
`hookSpecificOutput.additionalContext`. With the router's plain stdout
|
|
156
|
+
the model never saw the routing contract or the label instruction, so
|
|
157
|
+
it wrote no label; the same text as JSON reached the model and all five
|
|
158
|
+
test turns carried a label. The Codex manifest therefore runs the router
|
|
159
|
+
through `hooks/scripts/codex-user-prompt.js`, which wraps its output.
|
|
160
|
+
- Plugin-bundled hooks do not run on this version (`plugin_hooks` is
|
|
161
|
+
`removed`); the explicit fallback `harness codex-hooks install` is
|
|
162
|
+
needed, and Codex runs the hooks only after they are trusted in
|
|
163
|
+
`/hooks`.
|
|
164
|
+
- The final message comes from the rollout's `task_complete` event.
|
|
165
|
+
- The final message must belong to the current turn. A transcript scan
|
|
166
|
+
stops at the start of the current turn (Codex `task_started` or a user
|
|
167
|
+
message; a Claude user prompt) and a Codex `task_complete` must carry the
|
|
168
|
+
current `turn_id` when both are known. With no final message for the
|
|
169
|
+
current turn, `selfReport` is `null` with `final-message-unavailable`; the
|
|
170
|
+
previous turn's label is never reused.
|
|
171
|
+
- Failure follows each host's convention: the `PostToolUseFailure` event
|
|
172
|
+
(Claude Code), or an error flag or non-zero exit code in the tool response
|
|
173
|
+
(Codex).
|
|
174
|
+
- A missing field records `null` with a reason code. Collection must never
|
|
175
|
+
block, slow down, or fail a turn; each hook has a short time budget.
|
|
176
|
+
|
|
177
|
+
## Export
|
|
178
|
+
|
|
179
|
+
`scripts/system-one-observations-export.js` writes to the private data
|
|
180
|
+
repository:
|
|
181
|
+
|
|
182
|
+
- `prompts-observed.jsonl`: `{id, family, source: "observation", split, text}`
|
|
183
|
+
- `labels-observed.jsonl`: `{id, validity, contextDependent, tier, tierSource, intents, workflow, skills}`
|
|
184
|
+
|
|
185
|
+
`family` groups near-duplicate prompts. The split is by time: the newest 15%
|
|
186
|
+
is validation. The existing holdouts stay frozen and separate. Observed data
|
|
187
|
+
may later seed a new holdout, but only after owner review.
|
|
188
|
+
|
|
189
|
+
## Phases
|
|
190
|
+
|
|
191
|
+
1. **Contract.** Define the label-line format in `AGENTS.md` rule 11 and in
|
|
192
|
+
the Harness Status docs. The parser and validator come with tests.
|
|
193
|
+
2. **Collector.** Hook-side recording for Claude Code: the turn record,
|
|
194
|
+
behavior counters, the text store, the index and the opt-out. Tests cover
|
|
195
|
+
redaction, the time budget, fail-open behavior and index shape.
|
|
196
|
+
3. **Codex.** Verify the payload fields, then add the adapter and its tests.
|
|
197
|
+
4. **Exporter.** Derived labels, the family grouping, the time split, and
|
|
198
|
+
bias reports.
|
|
199
|
+
5. **Review page.** A blind review of disagreements; decisions feed back as
|
|
200
|
+
owner overrides.
|
|
201
|
+
|
|
202
|
+
## Non-goals
|
|
203
|
+
|
|
204
|
+
- Nothing is uploaded and there is no remote collection.
|
|
205
|
+
- The label line never gates or changes routing.
|
|
206
|
+
- Observed data does not replace the owner-reviewed holdouts.
|
|
@@ -42,10 +42,16 @@ The manifest is version 1 with `python` (executable), `checkpoint` (absolute
|
|
|
42
42
|
`.safetensors` path), `weightsSha256`, `configSha256` (matching `.json` sidecar),
|
|
43
43
|
`modelId`, `revision`, `domain`, and optional `timeoutMs` (1–10000, default 2000).
|
|
44
44
|
All fields are required except the timeout; unknown fields are rejected. An
|
|
45
|
-
optional `acceptance` object holds
|
|
46
|
-
`minMargin` (0–0.9).
|
|
45
|
+
optional `acceptance` object holds `minConfidence` (0.5–0.99) and
|
|
46
|
+
`minMargin` (0–0.9). It may also hold `secondaryThreshold` (0.05–0.5), the
|
|
47
|
+
probability at which another intent counts as a secondary intent; that key is
|
|
48
|
+
valid only for an intent checkpoint ([system-one-intent.md](system-one-intent.md#scoring)).
|
|
49
|
+
These are the thresholds calibrated on validation for this
|
|
47
50
|
checkpoint. A scored result carries them, and the router and the evaluator pass
|
|
48
|
-
|
|
51
|
+
the first two to `decide`. Without the field the Phase 0 defaults apply. For an
|
|
52
|
+
intent corpus the evaluator also reports graded accepted precision, exact accepted
|
|
53
|
+
precision and family consistency. The `acceptedPrecision` gate uses the graded
|
|
54
|
+
value. Hashes
|
|
49
55
|
must be lowercase SHA-256. Revision and domain are artifact-owner declarations,
|
|
50
56
|
not independently verified quality claims. The known `cua-ai/cua-s1-forms` ID
|
|
51
57
|
must use domain `forms-v1`. No pickle format or remote URL is accepted.
|
|
@@ -103,6 +109,52 @@ responses are checked by Phase 0. Transport fixtures prove IPC and failure
|
|
|
103
109
|
handling only. Real checkpoint inference and measured CPU latency remain a
|
|
104
110
|
separate gate, with explicit unavailable evidence if dependencies are absent.
|
|
105
111
|
|
|
112
|
+
## N-gram provider (Phase 4)
|
|
113
|
+
|
|
114
|
+
`transport: "ngram"` scores in the Node process itself. It needs no Python, no
|
|
115
|
+
torch, no resident server and no subprocess. It exists because a byte-level
|
|
116
|
+
transformer trained from scratch learned little beyond class priors on the
|
|
117
|
+
owner's data. A linear model over character n-grams learned more from the same
|
|
118
|
+
labels at about 1 MB. See
|
|
119
|
+
[harness-routing-v1-cpu-2026-09-24](../benchmarks/results/system-one/harness-routing-v1-cpu-2026-09-24/README.md).
|
|
120
|
+
|
|
121
|
+
**Artifact.** The manifest `checkpoint` is an absolute path to `<name>.bin`, and
|
|
122
|
+
`weightsSha256` is that file's hash. A `<name>.json` sidecar beside it has the
|
|
123
|
+
hash `configSha256`. `python` is not required for this transport. The sidecar
|
|
124
|
+
holds exactly:
|
|
125
|
+
|
|
126
|
+
| Field | Value |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| `format` | `harness-ngram` |
|
|
129
|
+
| `formatVersion` | `1` |
|
|
130
|
+
| `dim` | Feature buckets, a power of two between 2^10 and 2^20 |
|
|
131
|
+
| `nmax` | Longest n-gram, 1–4 |
|
|
132
|
+
| `hash` | `fnv1a32` |
|
|
133
|
+
| `catalog` | The option IDs in catalog order |
|
|
134
|
+
| `bias` | One number per option |
|
|
135
|
+
| `metadata` | An object with training provenance |
|
|
136
|
+
|
|
137
|
+
`.bin` holds `dim × catalog.length` little-endian float32 weights in row-major
|
|
138
|
+
order (feature, then option), so its size must equal `dim × options × 4` bytes.
|
|
139
|
+
Both files are hash-checked before use. Any mismatch in hash, shape or field
|
|
140
|
+
returns `provider-config` and never scores.
|
|
141
|
+
|
|
142
|
+
**Features.** Featurization is identical in the trainer and the provider, and a
|
|
143
|
+
cross-language test proves it.
|
|
144
|
+
|
|
145
|
+
1. Lowercase the text and join its whitespace-separated parts with one space.
|
|
146
|
+
2. For each n from 1 to `nmax`, take every n-gram of Unicode code points that is
|
|
147
|
+
not only spaces. Add it to bucket `fnv1a32("<n>:<gram>" as UTF-8) mod dim`.
|
|
148
|
+
3. Add one length feature, bucket `fnv1a32("len:<k>") mod dim`, where
|
|
149
|
+
`k = min(8, floor(log2(utf8Bytes + 1)))`.
|
|
150
|
+
4. Weight each bucket as `log(1 + count)` and L2-normalize the vector.
|
|
151
|
+
|
|
152
|
+
**Scoring.** The probabilities are `softmax(x·W + bias)` in catalog order. The
|
|
153
|
+
request's option IDs must equal `catalog`, or the result is `provider-config`.
|
|
154
|
+
The response has the Phase 0 shape, and the manifest `acceptance` thresholds
|
|
155
|
+
apply as for any transport. The Phase 0 context limit (64 KiB) is the only
|
|
156
|
+
length limit.
|
|
157
|
+
|
|
106
158
|
## Resident provider (Phase 4 prerequisite)
|
|
107
159
|
|
|
108
160
|
The one-shot bridge pays Python start, `import torch` and checkpoint load on every
|
|
@@ -262,6 +314,15 @@ The latter evidence is not supplied by this offline runner, so it always reports
|
|
|
262
314
|
those gates pending. With the one-shot adapter, all latency is cold and the warm
|
|
263
315
|
gate also remains pending. Exporting a report never changes router defaults.
|
|
264
316
|
|
|
317
|
+
For the `ngram` transport, samples are recorded with `coldStart: false`, because
|
|
318
|
+
scoring happens in process. The evaluator loads and verifies the artifact once
|
|
319
|
+
before any timed sample, so that load is not part of the warm latency. The
|
|
320
|
+
source check does not run the Python `cua_s1` probe, which this transport does
|
|
321
|
+
not use. It records `{status: "recorded", transport: "ngram", artifactVerified}`,
|
|
322
|
+
where `artifactVerified` is true only when both artifact files load and match
|
|
323
|
+
their SHA-256 values. For this transport, the `sourceProvenance` gate passes
|
|
324
|
+
when `artifactVerified` is true.
|
|
325
|
+
|
|
265
326
|
## Model suitability
|
|
266
327
|
|
|
267
328
|
The [CUA-S1-FORMS model card](https://huggingface.co/cua-ai/cua-s1-forms)
|
|
@@ -286,11 +347,47 @@ unversioned download during a prompt hook.
|
|
|
286
347
|
Phase 4 training data, labeling, calibration and release are defined in
|
|
287
348
|
[system-one-training.md](system-one-training.md).
|
|
288
349
|
|
|
350
|
+
## Staged classification
|
|
351
|
+
|
|
352
|
+
System One answers three narrow questions in sequence instead of one broad
|
|
353
|
+
question. Each stage is its own fixed catalog, scorer request and holdout, so a
|
|
354
|
+
small model only has to separate a few options at a time.
|
|
355
|
+
|
|
356
|
+
1. **Tier**: `tier1`, `tier2`, `tier3` or `unclassified`, following
|
|
357
|
+
[system-one-corpus.md](system-one-corpus.md).
|
|
358
|
+
2. **Intent**: the kind of work the prompt asks for, drawn from the owner's
|
|
359
|
+
fixed catalog in [system-one-intent.md](system-one-intent.md): `explain`,
|
|
360
|
+
`discuss`, `git`, `fix`, `edit`, `feature`, `refactor`, `review`, `test`,
|
|
361
|
+
`docs`, `plan`, `investigate` or `unclassified`. A prompt has one primary
|
|
362
|
+
intent and may have secondary intents.
|
|
363
|
+
3. **Skills**: which canonical skills fit the prompt, scored against skill
|
|
364
|
+
descriptions. Only skills above the stage's calibrated threshold are
|
|
365
|
+
suggested, and they are suggestions, never required reads.
|
|
366
|
+
|
|
367
|
+
Each stage has its own gates, and a stage ships only when it passes them.
|
|
368
|
+
The relevance-native plan in
|
|
369
|
+
[system-one-suggestion-gates.md](system-one-suggestion-gates.md#readout-per-stage)
|
|
370
|
+
adds a validity stage first and runs intent before tier, because tier3 is
|
|
371
|
+
composed from the intent scores. Tier was trained first because the
|
|
372
|
+
reviewed holdout exists for it. Later stages reuse the
|
|
373
|
+
same collector, labeler, trainer and evaluator with a different catalog.
|
|
374
|
+
Suggestions are advisory: explicit workflow requests, action gates, memory
|
|
375
|
+
ownership, the Rule of 3 and deterministic policy always take precedence.
|
|
376
|
+
|
|
289
377
|
## Rollout gates
|
|
290
378
|
|
|
379
|
+
Model-quality gates for relevance-native candidates are defined in
|
|
380
|
+
[system-one-suggestion-gates.md](system-one-suggestion-gates.md), which
|
|
381
|
+
supersedes the precision/coverage/latency targets below. The holdout size,
|
|
382
|
+
provenance, repeatability and advisory rules below still apply.
|
|
383
|
+
|
|
291
384
|
Phase 4 requires a separately reviewed, family-disjoint holdout of at least 200
|
|
292
|
-
cases, at least 50 each in English and Traditional Chinese.
|
|
293
|
-
|
|
385
|
+
cases, at least 50 each in English and Traditional Chinese. System One output is
|
|
386
|
+
advisory: it informs the agent and suggests skills. It never grants or removes
|
|
387
|
+
policy. The owner therefore set the target at accepted precision ≥85% (the
|
|
388
|
+
80–90% band), coverage ≥80%, and macro-F1 at least the lexical baseline. A
|
|
389
|
+
probabilistic scorer small enough to ship inside a skills plugin (a few MB, not
|
|
390
|
+
hundreds) is not expected to reach 98%.
|
|
294
391
|
Policy invariants must remain intact in every case; repeat decisions twice with
|
|
295
392
|
100% agreement. Record checkpoint/source hashes, CPU, OS, runtime, thread count,
|
|
296
393
|
cold latency and warm p95 (target ≤100ms). Synthetic fixtures and mock providers
|