yam-flow 2.8.4 → 2.8.5
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/AGENTS.md +4 -0
- package/CHANGELOG.md +17 -0
- package/COMMANDS.md +4 -0
- package/dist/bin/yam.js +24 -5
- package/dist/lib/security-integration.js +10 -1
- package/dist/lib/test-check.d.ts +156 -0
- package/dist/lib/test-check.js +558 -0
- package/package.json +5 -2
- package/references/final-report.md +4 -0
- package/references/test-check.md +192 -0
- package/skills/deep/SKILL.md +4 -0
- package/skills/mission/SKILL.md +4 -0
- package/skills/quick/SKILL.md +4 -0
- package/skills/ueye/SKILL.md +4 -0
- package/src/bin/yam.ts +19 -5
- package/src/lib/security-integration.ts +9 -1
- package/src/lib/test-check.ts +348 -0
- package/templates/test-check-policy.json +53 -0
- package/yam.manifest.json +1 -1
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Test check completion gate
|
|
2
|
+
|
|
3
|
+
Test check validates changed work before a completion claim, even without a commit
|
|
4
|
+
or push request. It is separate from report formatting and Security check. It does
|
|
5
|
+
not certify every possible input or prove a live deployment from a fixture.
|
|
6
|
+
|
|
7
|
+
## Contract
|
|
8
|
+
|
|
9
|
+
1. At work start, identify the exact baseline commit and expected behavior. Review
|
|
10
|
+
the project-owned policy before executing its commands. Commands run as the
|
|
11
|
+
caller without a shell; they are authorized project code, not a security sandbox.
|
|
12
|
+
2. Configure `testing/policy.json` (shared) or `.yam/testing/policy.json` (private).
|
|
13
|
+
`yam template test-check` prints a starter that cannot pass without an adapter.
|
|
14
|
+
3. Each changed source file must match a surface's exact path or `directory/**`.
|
|
15
|
+
Declare risk, targets and required scenarios. Built-in risk floors cannot be
|
|
16
|
+
reduced by deleting checks. API/DB/auth/UI require integration or E2E evidence.
|
|
17
|
+
4. At implementation end, `plan` checks impact and required scenarios; `run` executes
|
|
18
|
+
adapters and records exit codes/output hashes. Empty changes, zero tests, zero
|
|
19
|
+
assertions, skips, failing results and missing observations block. One identical
|
|
20
|
+
command executes once per run, even when it reports several scenarios.
|
|
21
|
+
5. `check` revalidates the policy, receipt, note, entire source snapshot, environment
|
|
22
|
+
identity and required scenario inventory. A relevant edit invalidates the result.
|
|
23
|
+
6. Completion requires PASS. An unavailable environment is BLOCKED, with a truthful
|
|
24
|
+
incomplete handoff permitted; it must not be described as completed verification.
|
|
25
|
+
|
|
26
|
+
Risk floors:
|
|
27
|
+
|
|
28
|
+
| Risk | Required scenarios |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| docs | inspection |
|
|
31
|
+
| logic | success, invalid, boundary |
|
|
32
|
+
| api | success, invalid, contract |
|
|
33
|
+
| db | success, denied, invalid, readback, rollback, migration_upgrade, migration_fresh |
|
|
34
|
+
| auth | success, denied, cross_scope, revoked |
|
|
35
|
+
| ui | success, error |
|
|
36
|
+
| release | artifact, integrity |
|
|
37
|
+
|
|
38
|
+
Path heuristics are conservative supplementary detection, not a complete dependency
|
|
39
|
+
or semantic graph. SQL functions/procedures/policies/triggers found in the old and
|
|
40
|
+
new SQL file must have explicit targets, e.g. `function:public.receiving`. Quoted
|
|
41
|
+
identifiers and dynamic SQL currently block for manual review; overloaded signatures,
|
|
42
|
+
indirect effects and application-specific dependencies require explicit project tests.
|
|
43
|
+
Do not label a function passing merely because a broad file-level test passed.
|
|
44
|
+
|
|
45
|
+
## Commands and activation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
mkdir -p testing
|
|
49
|
+
yam template test-check > testing/policy.json
|
|
50
|
+
# Edit policy and implement the referenced adapter; capture BASE before editing.
|
|
51
|
+
yam test-check plan --base "$BASE" --json
|
|
52
|
+
yam test-check run --base "$BASE" --json
|
|
53
|
+
yam test-check check --json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`BASE` must be an exact existing commit ID. A base equal to the candidate with no
|
|
57
|
+
changes cannot authorize completion. Generated/private `.yam`, dist, build, coverage,
|
|
58
|
+
node_modules, host agent configs and tarball/log files are excluded from source
|
|
59
|
+
snapshots; runtime dependency/configuration identities belong in environment evidence.
|
|
60
|
+
Source symlinks/submodules are unsupported and block, rather than silently omitted.
|
|
61
|
+
|
|
62
|
+
For a configured project, the existing opt-in `study-note` prompt/Stop hook also
|
|
63
|
+
runs Test check validation. Enable through `yam hook enable study-note --project .`
|
|
64
|
+
(or use an existing global study-note hook). Prompt captures changed-turn scope;
|
|
65
|
+
Stop checks the receipt only, never launches long tests. Unlike the report-format
|
|
66
|
+
one-correction rule, Test check remains blocked on repeated Stop calls. A response
|
|
67
|
+
containing the marker `Test check: BLOCKED` on its own status line may finish as an incomplete-status
|
|
68
|
+
handoff. This marker grants no machine gate approval. No-change/read-only turns
|
|
69
|
+
skip the completion check. Without a configured policy/hook the route instruction
|
|
70
|
+
is guidance, not host enforcement; missing host discovery must be reported.
|
|
71
|
+
|
|
72
|
+
Before commit use `check --stage commit`: the index must match the tested working
|
|
73
|
+
snapshot. Before push use `check --stage push --source "$SOURCE"` for every outgoing
|
|
74
|
+
commit; SOURCE must be an exact commit ID and match the tested snapshot. `check --base <expected starting commit>` rejects a receipt from a different baseline;
|
|
75
|
+
Security check supplies the actual CI base automatically. Stage ci
|
|
76
|
+
or deploy additionally requires an administrator-reviewed `--policy-digest`.
|
|
77
|
+
Missing CI/deploy pins are rejected before any project test command executes.
|
|
78
|
+
`run` supports the same stage/source requirements. Deploy additionally requires
|
|
79
|
+
`--artifact <repository-local-file> --configuration <repository-local-file>`
|
|
80
|
+
and a deployment-stage receipt. Both files are measured before/after the tests
|
|
81
|
+
and remeasured on check; completion-only evidence cannot approve deployment.
|
|
82
|
+
Adapters receive YAM_TEST_ARTIFACT / YAM_TEST_CONFIGURATION and must test those
|
|
83
|
+
exact inputs rather than create a substitute package. Run stage checks before operations,
|
|
84
|
+
not concurrently with index/source changes. Existing Security check invokes this
|
|
85
|
+
validation automatically when a default project policy exists; CI/deploy callers
|
|
86
|
+
must supply `yam security check --test-policy-digest "$PIN"`. Existing custom project
|
|
87
|
+
runners must generate the Test check receipt first. Do not overwrite other hooks.
|
|
88
|
+
|
|
89
|
+
Pins bind reviewed bytes; they do not independently approve policy authorship.
|
|
90
|
+
Policy/scenario removal and changed test adapters require renewed engineering review
|
|
91
|
+
and CI-protected policy approval. CI must independently run the reviewed tests;
|
|
92
|
+
local hooks/Stop hooks can be bypassed or disabled. This feature does not configure
|
|
93
|
+
GitHub protection or change installed global skills/hooks by package installation.
|
|
94
|
+
|
|
95
|
+
## Adapter protocol
|
|
96
|
+
|
|
97
|
+
A command emits one JSON document on stdout (logs can go to stderr). Each selected
|
|
98
|
+
check must appear exactly once. Reports are data and are never executed.
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"schema": "yam.test-observation.v1",
|
|
103
|
+
"tests": [{
|
|
104
|
+
"id": "save-success",
|
|
105
|
+
"target": "function:public.receiving",
|
|
106
|
+
"scenario": "success",
|
|
107
|
+
"evidence": "integration",
|
|
108
|
+
"status": "passed",
|
|
109
|
+
"tests": 1,
|
|
110
|
+
"assertions": 4,
|
|
111
|
+
"failed": 0,
|
|
112
|
+
"skipped": 0,
|
|
113
|
+
"mocked": false,
|
|
114
|
+
"environment": {}
|
|
115
|
+
}]
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The empty environment above is illustrative and cannot pass DB validation. DB
|
|
120
|
+
checks require `environment` to point to a repository-local expected manifest,
|
|
121
|
+
preferably ignored `.yam/testing/environment.json`, containing:
|
|
122
|
+
|
|
123
|
+
- schema `yam.test-environment.v1`, engine and exact engine_version;
|
|
124
|
+
- source_digest from `yam test-check plan`;
|
|
125
|
+
- configuration_digest, roles_digest and fixtures_digest (`sha256:...`);
|
|
126
|
+
- migrations: the complete sorted candidate `migrations/` inventory, each with
|
|
127
|
+
file and SHA256. Existing baseline migrations must also be included.
|
|
128
|
+
|
|
129
|
+
The adapter queries the *actual* isolated environment and returns the same structured
|
|
130
|
+
fields only after comparing applied migration order/content, runtime/roles/settings
|
|
131
|
+
and synthetic fixture identity. Returning the expected file without measuring the
|
|
132
|
+
DB is not valid evidence. yam compares reports and candidate manifests; adapter
|
|
133
|
+
assertions and environment truth are still trusted project code, not independently
|
|
134
|
+
attested by the generic runner. Misreported `mocked:false` cannot be detected by a
|
|
135
|
+
JSON validator. Review and protect the adapters as rigorously as the application.
|
|
136
|
+
|
|
137
|
+
Use actual DB operations with synthetic records and representative roles. Success
|
|
138
|
+
means saved headers/items and separate readback match, not just HTTP 200. Verify
|
|
139
|
+
failure rollback, duplicate/retry behavior, revoked access and relevant triggers.
|
|
140
|
+
Do not use owner/service credentials to stand in for ordinary-user authorization.
|
|
141
|
+
Test in disposable environments. Transaction rollback does not undo email, external
|
|
142
|
+
files, webhooks or all sequence effects; verify external isolation and cleanup.
|
|
143
|
+
|
|
144
|
+
## Records, safety and limits
|
|
145
|
+
|
|
146
|
+
Each run appends an explained `-- Test check --` block to private
|
|
147
|
+
`.yam/testing/notes.md`, writes an immutable JSON under `runs/` and updates
|
|
148
|
+
`latest.json`. Note/receipt write failure blocks; concurrent persistence uses an
|
|
149
|
+
exclusive lock, rejects links/hardlinks and never removes someone else's lock.
|
|
150
|
+
Raw stdout/stderr, command arguments and environment values are not persisted;
|
|
151
|
+
only allowlisted facts and hashes are recorded. Do not put secrets in explanations
|
|
152
|
+
or command arguments. Use the project's existing least-privilege test environment.
|
|
153
|
+
|
|
154
|
+
A checksum is not a signature against a hostile same-user process. Timeout marks a
|
|
155
|
+
command failed; descendant-process cleanup is not attested by spawnSync. Native
|
|
156
|
+
JUnit/Playwright/Postgres result parsers, property/stateful/combination testing and
|
|
157
|
+
mutation testing are project adapters or future extensions, not built-in scanners.
|
|
158
|
+
The regression suite uses real Git/process/filesystem fixtures and simulated DB
|
|
159
|
+
observations; it does not claim to have tested any production RO database.
|
|
160
|
+
|
|
161
|
+
Implementation boundaries: existing verification-closure remains an immutable
|
|
162
|
+
operator-declared command receipt. Test check adds actual process execution and
|
|
163
|
+
scenario checks without promoting those older receipts into runtime proof.
|
|
164
|
+
|
|
165
|
+
## Hosted rollout
|
|
166
|
+
|
|
167
|
+
The yam repository workflow runs Test check before Security check and uploads its
|
|
168
|
+
sanitized notes/runs. Activation after review requires `YAM_TEST_POLICY_SHA256`
|
|
169
|
+
alongside the existing reviewed source/security-policy pins. This change does not
|
|
170
|
+
set repository variables, update global hooks, commit, push or publish. An absent
|
|
171
|
+
or outdated pin intentionally blocks hosted approval rather than silently using
|
|
172
|
+
candidate-computed trust. Local project source-review manifests must be refreshed
|
|
173
|
+
only after the executable changes have been reviewed.
|
|
174
|
+
|
|
175
|
+
## Optional real PostgreSQL simulation
|
|
176
|
+
|
|
177
|
+
From a source checkout, `npm run test-check-postgres-smoke` requires Docker access and an existing local
|
|
178
|
+
`postgres:17-alpine` image (override with YAM_TEST_PG_IMAGE). It never pulls an
|
|
179
|
+
image, publishes a port, mounts host data, or connects to a production database.
|
|
180
|
+
The disposable database reproduces SQLSTATE 42702 after successful function DDL,
|
|
181
|
+
then verifies fixed normal save/readback, access denial/revocation, invalid input,
|
|
182
|
+
rollback, retry, fresh/upgrade migrations, out-of-band function drift, and a
|
|
183
|
+
16-case role/brand/quantity matrix. The
|
|
184
|
+
adapter queries actual server/function/ACL/migration state rather than echoing an
|
|
185
|
+
expected manifest. Cleanup must confirm the owned container is absent.
|
|
186
|
+
This is real PostgreSQL with synthetic application data, not verification of any
|
|
187
|
+
production application's SQL or authorization rules. It stays opt-in, outside
|
|
188
|
+
ordinary verification so a missing Docker daemon never silently becomes a mock.
|
|
189
|
+
|
|
190
|
+
Invalid stage/base values are rejected before persistence. Malformed run options
|
|
191
|
+
leave a sanitized failed note. Git discovery failure does not disable a previously
|
|
192
|
+
configured Stop gate; quoted examples of the handoff marker cannot approve it.
|
package/skills/deep/SKILL.md
CHANGED
|
@@ -74,6 +74,10 @@ Stop condition:
|
|
|
74
74
|
- Stop earlier when the same blocker repeats, a required tool/auth/runtime is unavailable, or a user decision is needed.
|
|
75
75
|
- Do not keep retrying the same failure; classify the cause, give a recovery hint, and hand off.
|
|
76
76
|
|
|
77
|
+
## Test check before completion
|
|
78
|
+
|
|
79
|
+
Before claiming changed work complete, use `references/test-check.md`. With a configured project policy run `yam test-check run --base <exact starting commit> --json` and `yam test-check check --json`. Require mapped scenarios, actual project-runner evidence, matching source/environment and a persisted Test check note. Required missing/failed/skipped checks block approval; give an honest `Test check: BLOCKED` handoff when unable to verify. Recheck exact staged/outgoing/deployment targets before their operations. Do not substitute mock DB results, report validation or old operator-declared receipts. If project adapters/policy are missing, report the activation gap instead of claiming gated completion. Read-only advisory work needs no execution gate; tiny changes use fitting inspection checks.
|
|
80
|
+
|
|
77
81
|
## Commit, push and deployment security gate
|
|
78
82
|
|
|
79
83
|
Before performing a requested commit, push or deployment, follow `references/security-check.md`: validate stage-bound evidence with `yam security check`, require a successful persisted Security check note, and stop the operation when the gate blocks. If the project is not configured, report that blocker rather than claim security approval. Do not overwrite existing hooks or treat supplied evidence as an automatic vulnerability scan.
|
package/skills/mission/SKILL.md
CHANGED
|
@@ -121,6 +121,10 @@ Good mission prompts include:
|
|
|
121
121
|
|
|
122
122
|
If the user invokes `$mission` without an approved plan, ask for the plan or propose a compact plan first.
|
|
123
123
|
|
|
124
|
+
## Test check before completion
|
|
125
|
+
|
|
126
|
+
Before claiming changed work complete, use `references/test-check.md`. With a configured project policy run `yam test-check run --base <exact starting commit> --json` and `yam test-check check --json`. Require mapped scenarios, actual project-runner evidence, matching source/environment and a persisted Test check note. Required missing/failed/skipped checks block approval; give an honest `Test check: BLOCKED` handoff when unable to verify. Recheck exact staged/outgoing/deployment targets before their operations. Do not substitute mock DB results, report validation or old operator-declared receipts. If project adapters/policy are missing, report the activation gap instead of claiming gated completion. Read-only advisory work needs no execution gate; tiny changes use fitting inspection checks.
|
|
127
|
+
|
|
124
128
|
## Commit, push and deployment security gate
|
|
125
129
|
|
|
126
130
|
Before performing a requested commit, push or deployment, follow `references/security-check.md`: validate stage-bound evidence with `yam security check`, require a successful persisted Security check note, and stop the operation when the gate blocks. If the project is not configured, report that blocker rather than claim security approval. Do not overwrite existing hooks or treat supplied evidence as an automatic vulnerability scan.
|
package/skills/quick/SKILL.md
CHANGED
|
@@ -75,6 +75,10 @@ Use `references/study-note.md` when any code, config, docs, or project artifact
|
|
|
75
75
|
Use `references/final-report.md` to close with remaining tasks and fix-first items when useful.
|
|
76
76
|
Use `references/token-budget-reporter.md` when a run needs measured budget feedback.
|
|
77
77
|
|
|
78
|
+
## Test check before completion
|
|
79
|
+
|
|
80
|
+
Before claiming changed work complete, use `references/test-check.md`. With a configured project policy run `yam test-check run --base <exact starting commit> --json` and `yam test-check check --json`. Require mapped scenarios, actual project-runner evidence, matching source/environment and a persisted Test check note. Required missing/failed/skipped checks block approval; give an honest `Test check: BLOCKED` handoff when unable to verify. Recheck exact staged/outgoing/deployment targets before their operations. Do not substitute mock DB results, report validation or old operator-declared receipts. If project adapters/policy are missing, report the activation gap instead of claiming gated completion. Read-only advisory work needs no execution gate; tiny changes use fitting inspection checks.
|
|
81
|
+
|
|
78
82
|
## Commit, push and deployment security gate
|
|
79
83
|
|
|
80
84
|
Before performing a requested commit, push or deployment, follow `references/security-check.md`: validate stage-bound evidence with `yam security check`, require a successful persisted Security check note, and stop the operation when the gate blocks. If the project is not configured, report that blocker rather than claim security approval. Do not overwrite existing hooks or treat supplied evidence as an automatic vulnerability scan.
|
package/skills/ueye/SKILL.md
CHANGED
|
@@ -183,6 +183,10 @@ Always consider:
|
|
|
183
183
|
- Interaction affordance.
|
|
184
184
|
- Consistency with the project's visual language.
|
|
185
185
|
|
|
186
|
+
## Test check before completion
|
|
187
|
+
|
|
188
|
+
Before claiming changed work complete, use `references/test-check.md`. With a configured project policy run `yam test-check run --base <exact starting commit> --json` and `yam test-check check --json`. Require mapped scenarios, actual project-runner evidence, matching source/environment and a persisted Test check note. Required missing/failed/skipped checks block approval; give an honest `Test check: BLOCKED` handoff when unable to verify. Recheck exact staged/outgoing/deployment targets before their operations. Do not substitute mock DB results, report validation or old operator-declared receipts. If project adapters/policy are missing, report the activation gap instead of claiming gated completion. Read-only advisory work needs no execution gate; tiny changes use fitting inspection checks.
|
|
189
|
+
|
|
186
190
|
## Commit, push and deployment security gate
|
|
187
191
|
|
|
188
192
|
Before performing a requested commit, push or deployment, follow `references/security-check.md`: validate stage-bound evidence with `yam security check`, require a successful persisted Security check note, and stop the operation when the gate blocks. If the project is not configured, report that blocker rather than claim security approval. Do not overwrite existing hooks or treat supplied evidence as an automatic vulnerability scan.
|
package/src/bin/yam.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { runTestCheckCommand, testCheckStop, testCheckConfigured } from '../lib/test-check.js';
|
|
2
3
|
import { spawnSync } from 'node:child_process';
|
|
3
4
|
import { studyNoteTurnScope } from '../lib/study-note-scope.js';
|
|
4
5
|
import { selectHookNode, probeHookDiscovery, inspectHookObservation, recordHookObservation } from '../lib/hook-readiness.js';
|
|
@@ -228,6 +229,7 @@ Usage:
|
|
|
228
229
|
yam proof [dir|--from file] [--route route] [--truth status] [--command text] [--evidence text]
|
|
229
230
|
yam proof write [dir] [--format json|md] [--out file] [--route route] [--truth status] [--command text]
|
|
230
231
|
yam study-note check [dir] [--report file|--text text] [--json]
|
|
232
|
+
yam test-check <plan|run|check|status> [--base commit] [--json]
|
|
231
233
|
yam security <init|check|hooks|status> [--stage commit|push|ci|deploy] [--json]
|
|
232
234
|
yam next-step <report|verify> [--spec file|--receipt file] [--json]
|
|
233
235
|
yam loop report [--route route] [--intent text] [--stage id:status:note] [--evidence text] [--json]
|
|
@@ -254,7 +256,7 @@ Usage:
|
|
|
254
256
|
yam safety [text...]
|
|
255
257
|
yam memory <init|add|list|summary|resolve> [dir] [options]
|
|
256
258
|
yam hook <status|enable|disable|run> [lite|study-note] [--global|--project dir]
|
|
257
|
-
yam template <project|ueye|mission|proof|tuning|security|security-ci>
|
|
259
|
+
yam template <project|ueye|mission|proof|tuning|security|security-ci|test-check>
|
|
258
260
|
yam tune-log [dir]
|
|
259
261
|
yam install [--dry-run] [--json] [--replace-user-skill name]
|
|
260
262
|
yam uninstall
|
|
@@ -576,6 +578,7 @@ async function verify({ quiet = false } = {}) {
|
|
|
576
578
|
'markdown-management.md',
|
|
577
579
|
'study-note.md',
|
|
578
580
|
'security-check.md',
|
|
581
|
+
'test-check.md',
|
|
579
582
|
'final-report.md',
|
|
580
583
|
'token-budget-reporter.md',
|
|
581
584
|
'memory.md'
|
|
@@ -591,7 +594,7 @@ async function verify({ quiet = false } = {}) {
|
|
|
591
594
|
if (!hasHeading(projectTemplate, section)) issues.push(`project template missing section: ${section}`);
|
|
592
595
|
}
|
|
593
596
|
}
|
|
594
|
-
for (const template of ['ueye-review.md', 'ueye-comparison.md', 'mission-plan.md', 'runtime-proof.md', 'tuning-log.md', 'security-check-note.md', 'security-gate.yml']) {
|
|
597
|
+
for (const template of ['ueye-review.md', 'ueye-comparison.md', 'mission-plan.md', 'runtime-proof.md', 'tuning-log.md', 'security-check-note.md', 'security-gate.yml', 'test-check-policy.json']) {
|
|
595
598
|
if (!await exists(path.join(ROOT, 'templates', template))) issues.push(`missing template: ${template}`);
|
|
596
599
|
}
|
|
597
600
|
for (const module of ['trust-kernel.js', 'ueye-artifacts.js']) {
|
|
@@ -2524,6 +2527,8 @@ async function buildYamLiteContext({ cwd, prompt }) {
|
|
|
2524
2527
|
async function buildStudyNoteStopOutput(input: AnyRecord = {}, cwd = process.cwd()) {
|
|
2525
2528
|
const lastAssistantMessage = String(input?.last_assistant_message || input?.lastAssistantMessage || '');
|
|
2526
2529
|
const scope = studyNoteTurnScope(input, cwd);
|
|
2530
|
+
const testGate = testCheckStop(cwd, !scope.available || scope.files.length > 0, lastAssistantMessage);
|
|
2531
|
+
if (testGate) return testGate;
|
|
2527
2532
|
const result = await buildStudyNoteGuardResult(path.resolve(cwd), lastAssistantMessage, 'stop_hook_last_assistant_message', scope);
|
|
2528
2533
|
if (result.truth_status === 'partial' && !result.changed_file_detection.available) {
|
|
2529
2534
|
return {
|
|
@@ -2554,8 +2559,9 @@ async function buildStudyNoteStopOutput(input: AnyRecord = {}, cwd = process.cwd
|
|
|
2554
2559
|
|
|
2555
2560
|
async function buildStudyNoteTurnContext(input: AnyRecord, cwd: string) {
|
|
2556
2561
|
const scope = studyNoteTurnScope(input, cwd, true);
|
|
2562
|
+
const testReminder = testCheckConfigured(cwd) ? ' Test check active: before completion run yam test-check run --base <exact starting commit> --json and yam test-check check --json. Missing required tests/evidence block completion; report Test check: BLOCKED if unable to verify. This is separate from report formatting and Security check.' : '';
|
|
2557
2563
|
if (!scope.available) return 'yam Study Note: turn scope is unavailable; do not treat this as a clean project. Inspect changed artifacts manually; no strict block will be applied without a baseline.';
|
|
2558
|
-
return `yam Study Note turn baseline saved (hash-only). Mode: ${scope.mode}. Only changes since this prompt count; known generated logs, mission/security receipts and screenshots are excluded unless explicitly included. Include a concise Study Note followed by Next step when product artifacts change. ${scope.mode === 'strict' ? 'Risk work uses the detailed report contract and one correction pass.' : 'Ordinary work is advisory: a short explanation, verification/limits and remaining work (or none) suffice.'}`;
|
|
2564
|
+
return `yam Study Note turn baseline saved (hash-only). Mode: ${scope.mode}. Only changes since this prompt count; known generated logs, mission/security receipts and screenshots are excluded unless explicitly included. Include a concise Study Note followed by Next step when product artifacts change. ${scope.mode === 'strict' ? 'Risk work uses the detailed report contract and one correction pass.' : 'Ordinary work is advisory: a short explanation, verification/limits and remaining work (or none) suffice.'}${testReminder}`;
|
|
2559
2565
|
}
|
|
2560
2566
|
|
|
2561
2567
|
function yamLiteRouteHint(prompt = '') {
|
|
@@ -6149,11 +6155,12 @@ async function printTemplate(name = '') {
|
|
|
6149
6155
|
runtime: 'runtime-proof.md',
|
|
6150
6156
|
tuning: 'tuning-log.md',
|
|
6151
6157
|
security: 'security-check-note.md',
|
|
6152
|
-
'security-ci': 'security-gate.yml'
|
|
6158
|
+
'security-ci': 'security-gate.yml',
|
|
6159
|
+
'test-check': 'test-check-policy.json'
|
|
6153
6160
|
};
|
|
6154
6161
|
const file = map[key];
|
|
6155
6162
|
if (!file) {
|
|
6156
|
-
console.error('usage: yam template <project|ueye|ueye-comparison|mission|proof|tuning|security|security-ci>');
|
|
6163
|
+
console.error('usage: yam template <project|ueye|ueye-comparison|mission|proof|tuning|security|security-ci|test-check>');
|
|
6157
6164
|
process.exitCode = 1;
|
|
6158
6165
|
return;
|
|
6159
6166
|
}
|
|
@@ -6456,6 +6463,13 @@ function showRequestedHelp(args: string[]) {
|
|
|
6456
6463
|
async function main() {
|
|
6457
6464
|
const args = process.argv.slice(2);
|
|
6458
6465
|
const command = args[0] || 'help';
|
|
6466
|
+
if (command === 'test-check') {
|
|
6467
|
+
if (!args[1] || ['help', '--help', '-h'].includes(args[1])) {
|
|
6468
|
+
console.log('yam test-check run --base <exact commit> [--policy file --policy-digest sha256] [--json]\nyam test-check check [--stage complete|commit|push|ci|deploy --source <exact commit> --policy-digest sha256 --receipt file] [--json]\nyam test-check status\nyam test-check plan --base <exact commit> --json\nSee references/test-check.md for required scenarios, adapters and activation.'); return;
|
|
6469
|
+
}
|
|
6470
|
+
const result = runTestCheckCommand(args.slice(1));
|
|
6471
|
+
console.log(JSON.stringify(result, null, 2)); if (!result.ok) process.exitCode = 1; return;
|
|
6472
|
+
}
|
|
6459
6473
|
if (showRequestedHelp(args)) return;
|
|
6460
6474
|
if (command === 'help') return usage();
|
|
6461
6475
|
if (command === 'security') {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { checkTestCheck, testCheckConfigured } from './test-check.js';
|
|
1
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
3
|
import { execFileSync } from 'node:child_process';
|
|
3
4
|
import fs from 'node:fs/promises';
|
|
@@ -27,7 +28,7 @@ function parseArgs(args: string[]): Map<string, string> {
|
|
|
27
28
|
const out = new Map<string, string>();
|
|
28
29
|
for (let i = 0; i < args.length; i++) {
|
|
29
30
|
if (args[i] === '--json') continue;
|
|
30
|
-
if (!['--policy', '--policy-digest', '--evidence', '--note', '--stage', '--remote', '--destination', '--source', '--base', '--artifact', '--artifact-digest', '--configuration', '--configuration-digest', '--environment', '--cli'].includes(args[i]) || !args[i + 1] || args[i + 1].startsWith('--') || out.has(args[i])) throw new Error('invalid or duplicate security option');
|
|
31
|
+
if (!['--policy', '--policy-digest', '--evidence', '--note', '--stage', '--remote', '--destination', '--source', '--base', '--artifact', '--artifact-digest', '--configuration', '--configuration-digest', '--environment', '--cli', '--test-policy-digest'].includes(args[i]) || !args[i + 1] || args[i + 1].startsWith('--') || out.has(args[i])) throw new Error('invalid or duplicate security option');
|
|
31
32
|
out.set(args[i], args[++i]);
|
|
32
33
|
}
|
|
33
34
|
return out;
|
|
@@ -262,6 +263,13 @@ async function check(cwd: string, options: Map<string, string>, settings: Securi
|
|
|
262
263
|
result = validateSecurityCheck(input, binding as any);
|
|
263
264
|
gateErrors.push('security_input_or_binding_unavailable');
|
|
264
265
|
}
|
|
266
|
+
if (testCheckConfigured(cwd) || config.test_policy_digest) {
|
|
267
|
+
const pin = options.get('--test-policy-digest') || config.test_policy_digest;
|
|
268
|
+
const sources = stage === 'push' ? (binding.push_refs as any[] || []).map(ref => ref.local_oid)
|
|
269
|
+
: [binding.source_revision as string | undefined];
|
|
270
|
+
const targets = sources.length ? sources : [undefined];
|
|
271
|
+
if (targets.some(source => !checkTestCheck(cwd, { stage, source, pin, base: stage === 'ci' ? binding.base_revision as string : undefined, artifact: options.get('--artifact'), configuration: options.get('--configuration') }).ok)) gateErrors.push('test_check_blocked');
|
|
272
|
+
}
|
|
265
273
|
if (gateErrors.length) {
|
|
266
274
|
result.result = 'BLOCKED';
|
|
267
275
|
result.errors = [...new Set([...result.errors, ...gateErrors])];
|