harness-everything 0.19.0 → 0.20.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/.releaserc.json +1 -1
- package/AGENTS.md +3 -2
- package/CHANGELOG.md +9 -0
- package/README.md +14 -14
- package/RELEASING.md +10 -2
- package/ci/invariant-routing.test.js +42 -19
- package/ci/mechanism-2af-worktree-isolation.test.js +3 -3
- package/ci/mechanism-2ag-router-worktree-contract.test.js +1 -0
- package/ci/mechanism-2an-workflow-obligations.test.js +1 -0
- package/ci/mechanism-2ap-sbom.test.js +92 -0
- package/ci/mechanism-33-issues-205-207.test.js +2 -2
- package/ci/openai-plugin-package.test.js +6 -6
- package/ci/router-workflow-plan.test.js +12 -9
- package/ci/workflow-execution-contract.test.js +2 -2
- package/docs/architecture.md +15 -15
- package/docs/enforcement-locks.md +17 -15
- package/docs/philosophy.md +43 -8
- package/docs/routing.md +23 -16
- package/docs/workflow-runtime.md +20 -19
- package/environment-detection/SKILL.md +3 -1
- package/evals/harness-everything/tasks/positive-tier1.yaml +1 -1
- package/evals/harness-everything/tasks/positive-tier2.yaml +1 -1
- package/evals/harness-everything/tasks/positive-tier3.yaml +1 -1
- package/evals/using-git-worktrees/tasks/positive-trigger.yaml +1 -1
- package/find-skills/SKILL.md +20 -29
- package/git-commit/SKILL.md +4 -4
- package/harness-everything/SKILL.md +16 -17
- package/harness-everything/references/triage-and-tiers.md +17 -16
- package/harness-everything/scripts/kernel-router-core.js +26 -24
- package/harness-everything/scripts/kernel-router.js +8 -8
- package/harness-everything/scripts/router-contract-core.js +7 -7
- package/harness-everything/scripts/router-contract.js +1 -1
- package/hooks/scripts/atomic-commit-check.js +1 -1
- package/hooks/scripts/boundary-guard.js +2 -2
- package/hooks/scripts/depth-guard.js +5 -6
- package/hooks/scripts/subagent-scope-guard.js +2 -2
- package/hooks/scripts/workflow-gate.js +1 -1
- package/install-cognitive-os/SKILL.md +3 -3
- package/opencode-plugin/plugin.json +1 -1
- package/package.json +5 -2
- package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
- package/plugins/harness-everything/hooks/scripts/atomic-commit-check.js +1 -1
- package/plugins/harness-everything/hooks/scripts/boundary-guard.js +2 -2
- package/plugins/harness-everything/hooks/scripts/depth-guard.js +5 -6
- package/plugins/harness-everything/hooks/scripts/subagent-scope-guard.js +2 -2
- package/plugins/harness-everything/hooks/scripts/workflow-gate.js +1 -1
- package/plugins/harness-everything/plugin.json +1 -1
- package/plugins/harness-everything/scripts/lib/advisory-text.js +19 -17
- package/plugins/harness-everything/skills/environment-detection/SKILL.md +3 -1
- package/plugins/harness-everything/skills/find-skills/SKILL.md +20 -29
- package/plugins/harness-everything/skills/git-commit/SKILL.md +4 -4
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +16 -17
- package/plugins/harness-everything/skills/harness-everything/references/triage-and-tiers.md +17 -16
- package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router-core.js +26 -24
- package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router.js +8 -8
- package/plugins/harness-everything/skills/harness-everything/scripts/router-contract-core.js +7 -7
- package/plugins/harness-everything/skills/harness-everything/scripts/router-contract.js +1 -1
- package/plugins/harness-everything/skills/install-cognitive-os/SKILL.md +3 -3
- package/plugins/harness-everything/skills/rewrite-commits/SKILL.md +2 -2
- package/plugins/harness-everything/skills/to-tickets/SKILL.md +2 -2
- package/plugins/harness-everything/skills/using-git-worktrees/SKILL.md +6 -6
- package/rewrite-commits/SKILL.md +2 -2
- package/sbom.cdx.json +2110 -0
- package/scripts/generate-sbom.js +239 -0
- package/scripts/lib/advisory-text.js +19 -17
- package/to-tickets/SKILL.md +2 -2
- package/using-git-worktrees/SKILL.md +6 -6
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "harness-everything",
|
|
11
11
|
"source": "./",
|
|
12
12
|
"description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
|
|
13
|
-
"version": "0.
|
|
13
|
+
"version": "0.20.0",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Miya Daniel"
|
|
16
16
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harness-everything",
|
|
3
3
|
"description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.20.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Miya Daniel"
|
|
7
7
|
},
|
package/.releaserc.json
CHANGED
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"@semantic-release/exec",
|
|
65
65
|
{
|
|
66
66
|
"verifyReleaseCmd": "node scripts/sync-release-version.js --validate ${nextRelease.version}",
|
|
67
|
-
"prepareCmd": "node scripts/sync-release-version.js ${nextRelease.version} --base ${lastRelease.gitTag} && npm run plugin:sync && node scripts/sync-release-version.js --check ${nextRelease.version} --base ${lastRelease.gitTag} && npm run test:consistency && npm run test:plugin:openai && npm run test:plugin:submission"
|
|
67
|
+
"prepareCmd": "node scripts/sync-release-version.js ${nextRelease.version} --base ${lastRelease.gitTag} && npm run plugin:sync && node scripts/generate-sbom.js --output sbom.cdx.json --version ${nextRelease.version} && node scripts/generate-sbom.js --validate sbom.cdx.json --version ${nextRelease.version} && node scripts/sync-release-version.js --check ${nextRelease.version} --base ${lastRelease.gitTag} && npm run test:consistency && npm run test:plugin:openai && npm run test:plugin:submission"
|
|
68
68
|
}
|
|
69
69
|
],
|
|
70
70
|
[
|
package/AGENTS.md
CHANGED
|
@@ -40,9 +40,10 @@ The retained [OpenCode evidence](benchmarks/results/live-host/opencode-2026-09-1
|
|
|
40
40
|
7. **Runtime/workflow claims are generated facts.** `package.json`, `.nvmrc`, Dockerfile, and active workflows feed `scripts/repository-contract.js`; run `npm run docs:sync` after relevant changes.
|
|
41
41
|
8. **CHANGELOG.md keeps pending human-authored notes under `[Unreleased]`.** Semantic-release owns stable headings/tags/release notes.
|
|
42
42
|
9. **Conventional Commit type is release input.** Breaking→major; `feat`→minor; `fix`/`perf`/`refactor`/`build`/`revert`→patch; docs/test/ci/style/chore do not release by themselves.
|
|
43
|
-
10. **Selected workflow is
|
|
43
|
+
10. **Selected workflow is a semantic contract; tactics remain flexible.** Suggested skills MUST be read/evaluated before omission; applicable skill core contracts MUST be followed, while not-applicable requires a flow-grounded reason. Selected-topology required obligations MUST resolve. Missing host evidence may produce reminders, not a persistent Harness lock.
|
|
44
44
|
11. **User-visible Harness Status is mandatory for non-trivial work.** Render one readable Markdown block headed `### 🚦 Harness Status`, with bullet-aligned bold `Current`, `Read / Evidence`, `Next`, plus optional `Risk / Blocked`; use nested evidence bullets when useful. Emit it before substantive execution, after major phases, on direction changes, during long work at meaningful boundaries, and before final completion. The routing checkpoint is internal source state, not a second user-facing block. This semantic MUST does not create a hard lock.
|
|
45
|
-
12. **
|
|
45
|
+
12. **Tier-3/Fable isolation disposition is mandatory before broad mutation.** Use/reuse a verified linked Git worktree, or record an explicit degraded fallback when isolation is unavailable or the user explicitly chooses to stay in place. Ordinary isolation SHOULD be used when it materially reduces collision/risk. Failure to isolate is a visible semantic gap, not a Harness-owned deadlock. See [workflow-runtime.md](docs/workflow-runtime.md).
|
|
46
|
+
13. **Use contract strength deliberately.** MUST = required semantic obligation; SHOULD = expected default with an evidence-based exception; MAY = optional optimization. Do not use recommend/prefer/advisory/guidance to weaken a MUST. See [philosophy.md](docs/philosophy.md#contract-strength-must--should--may).
|
|
46
47
|
|
|
47
48
|
## Verification Before You Claim Done
|
|
48
49
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.20.0](https://github.com/dyphn1/Harness-everything/compare/v0.19.1...v0.20.0) (2026-09-21)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
* **release:** adopt cyclonedx 1.7 sbom ([39304e4](https://github.com/dyphn1/Harness-everything/commit/39304e4bfe8f94e969c72624301238c5f183a995))
|
|
10
|
+
* **release:** generate and publish CycloneDX SBOM with npm ([6d8ddd0](https://github.com/dyphn1/Harness-everything/commit/6d8ddd008b5cb1e893cbdad915be8fe063e85b84))
|
|
11
|
+
|
|
12
|
+
## [0.19.1](https://github.com/dyphn1/Harness-everything/compare/v0.19.0...v0.19.1) (2026-09-21)
|
|
13
|
+
|
|
5
14
|
## [0.19.0](https://github.com/dyphn1/Harness-everything/compare/v0.18.1...v0.19.0) (2026-09-21)
|
|
6
15
|
|
|
7
16
|
### Features
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ AI coding agents are highly capable, but they struggle with self-regulation, env
|
|
|
19
19
|
|
|
20
20
|
Harness acts as an automated system supervisor. It remains completely silent and out of the way, intervening only when execution boundaries are violated or failures are detected.
|
|
21
21
|
|
|
22
|
-
Harness deliberately follows a **minimal rails, maximum freedom** design:
|
|
22
|
+
Harness deliberately follows a **minimal rails, maximum freedom** design: semantic obligations are explicit, while runtime observation remains lightweight and mostly fail-open. It does not hard-stop work on iteration/revision/replan/worker counts. The one cognitive hard boundary is Rule of 3: three matching failures pause mutation for a zoom-out reflection. Router suggestions are conditional by applicability, not optional by default: the agent MUST read/evaluate each suggested skill; if applicable, its core contract MUST be followed, and if not applicable a flow-grounded reason MUST be retained. Implementation tactics remain flexible inside those obligations.
|
|
23
23
|
|
|
24
24
|
### Comparison: Prompt vs. Skill vs. Harness
|
|
25
25
|
|
|
@@ -48,7 +48,7 @@ The exact "Harness" behavior depends on the installation surface. Claude Code ha
|
|
|
48
48
|
|
|
49
49
|
Harness integrates directly into your workspace. There is no heavy daemon, no paid external APIs, and zero configuration required.
|
|
50
50
|
|
|
51
|
-
**Runtime:** Harness supports **Node.js 22+**. Node.js **24** is the primary
|
|
51
|
+
**Runtime:** Harness supports **Node.js 22+**. Node.js **24** is the primary development and CI runtime (`.nvmrc`). The generated current-state runtime/workflow summary is [docs/repository-contract.md](docs/repository-contract.md).
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
54
|
# Option A: Claude Code plugin (marketplace manifest included)
|
|
@@ -73,7 +73,7 @@ npx github:dyphn1/Harness-everything install
|
|
|
73
73
|
1. **Use the selected surface's real mechanism:** Claude Code hooks, the local OpenAI plugin lifecycle hooks, OpenCode's plugin API, or advisory instructions depending on what you installed.
|
|
74
74
|
2. **Preflight / session context where packaged:** Hook-capable surfaces can inject environment/session context automatically; advisory-only surfaces must not be described as if they do.
|
|
75
75
|
3. **Verification boundary:** Completion claims require objective evidence; whether that boundary is mechanically invoked or explicitly called depends on the host surface.
|
|
76
|
-
4. **Mandatory applicable workflow:**
|
|
76
|
+
4. **Mandatory applicable workflow:** MUST evaluate each suggested skill's complete `SKILL.md`; applicable core contracts MUST be followed, while not-applicable needs a flow-grounded reason. Selected-topology required obligations MUST resolve with objective evidence. Reasoning and implementation remain flexible; escape applies only to declared uncovered scope with evidence. Tier-3/Fable broad mutation MUST resolve isolation: verified linked worktree or explicit degraded fallback. See the [workflow runtime contract](docs/workflow-runtime.md). Harness does not impose one universal TODO/TDD/Fable sequence.
|
|
77
77
|
5. **Unified user-visible status:** For non-trivial software/project work, the agent MUST render one scannable Markdown `### 🚦 Harness Status` block with bold bullet labels for `Current`, `Read / Evidence`, `Next`, plus optional `Risk / Blocked`; multiple evidence items may use nested bullets. Use it at major phase/direction boundaries and before final completion. The routing checkpoint remains internal source state. This is a communication contract, not a hard runtime lock.
|
|
78
78
|
|
|
79
79
|
### What Gets Installed (and How to Remove It)
|
|
@@ -127,7 +127,7 @@ flowchart TD
|
|
|
127
127
|
```mermaid
|
|
128
128
|
flowchart TD
|
|
129
129
|
U([User Request]) --> K[Harness Kernel<br/>classify scope + establish invariants]
|
|
130
|
-
K --> T{Tier
|
|
130
|
+
K --> T{Tier classification}
|
|
131
131
|
T --> S{Suggested skills?}
|
|
132
132
|
S -->|Yes| R[Read each suggested SKILL.md<br/>evaluate flow + applicability]
|
|
133
133
|
S -->|No| A[Agent chooses smallest useful tactic / skill set]
|
|
@@ -147,7 +147,7 @@ flowchart TD
|
|
|
147
147
|
style Gate fill:#ffcdd2,stroke:#c62828,stroke-width:1px,color:#000000
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
The Tier changes the **
|
|
150
|
+
The Tier changes task shape and the set of **suggested skills**, not a universal required order. Tier 2 may suggest `tdd`, `todo-driven-workflow`, or `verification-loop`; Tier 3 may select Fable or multi-agent topologies. Every suggestion is **MUST-evaluate**: if its real flow is applicable, the core contract becomes **MUST-follow**; otherwise retain a flow-grounded not-applicable reason. Tactics inside the resulting contract remain model-controlled.
|
|
151
151
|
|
|
152
152
|
---
|
|
153
153
|
|
|
@@ -155,7 +155,7 @@ The Tier changes the **recommendations**, not the required order. Tier 2 may sug
|
|
|
155
155
|
|
|
156
156
|
Harness operates through six core cognitive concepts:
|
|
157
157
|
|
|
158
|
-
1. **Kernel Router (`kernel-router.js` + `tier-router.js`):** `tier-router.js` remains the classifier, dynamic-skill detector, and knowledge-guide matcher. `kernel-router.js` is the public runtime boundary: it preserves the classifier result,
|
|
158
|
+
1. **Kernel Router (`kernel-router.js` + `tier-router.js`):** `tier-router.js` remains the classifier, dynamic-skill detector, and knowledge-guide matcher. `kernel-router.js` is the public runtime boundary: it preserves the classifier result, injects baseline MUST invariants, and adds `evaluate-suggestions-before-skip` whenever domain skills are suggested. Suggestions MUST be evaluated from their real `SKILL.md` flow; an applicable skill's core contract MUST be followed, while not-applicable needs evidence. Selected-topology obligations are also semantic MUSTs, but the runtime generally observes/reminds rather than hard-blocking. This preserves agent autonomy over tactics without allowing confidence to erase the lifecycle. If nothing matches at all — including nothing already kept from the open skills ecosystem — `find-skills` checks `npx skills list` live and, if still nothing, searches `skills.sh`/`npx skills` with explicit approval before installation.
|
|
159
159
|
2. **Guard (`rule-of-3.js`):** The fail-safe circuit breaker. Tracks failure signatures across terminal runs on integration surfaces that package the required lifecycle hooks. If a test or command fails 3 times with the same signature, it locks mutating tools and forces a `zoom-out` reflection: re-verify every assumption with read-only tools, write a fact-checked report, then resume on a fresh diagnosis. A companion `Stop` hook (`stop-gate.js`) emits a non-blocking reminder when edits were never followed by successful verification on hosts where that hook is installed.
|
|
160
160
|
3. **Memory (`state-persist.js`):** Session transaction logging for stateful hook/plugin integrations. Static skills/instructions alone do not create WAL state.
|
|
161
161
|
4. **Reflection (`self-evolve`):** Long-term workspace immunization. Upon task completion, the agent reflects on the root cause of resolved issues, then judges whether the lesson is a simple rule or a reusable, complex pattern: simple rules are appended to local workspace rules (`RULES.md`); genuinely reusable patterns are instead packaged as a dynamic skill (via `skill-creator`'s Dynamic Skill Generation Contract) and registered in `manifest.json` so the Router picks it up in future sessions. Either path is validated by a hermetic self-regression suite before it's persisted.
|
|
@@ -172,10 +172,10 @@ The authoritative current matrix is [docs/platform-capabilities.md](docs/platfor
|
|
|
172
172
|
|
|
173
173
|
| AI Agent Tool / Surface | Integration Method | Local Target Location | Enforcement claim |
|
|
174
174
|
|---|---|---|---|
|
|
175
|
-
| **Claude Code** | Native lifecycle hooks (`PreToolUse`, `PostToolUse`, `SessionStart`, `UserPromptSubmit`, `Stop`) | `.claude/settings.json`, `.claude/skills/`, `.claude/agents/` |
|
|
175
|
+
| **Claude Code** | Native lifecycle hooks (`PreToolUse`, `PostToolUse`, `SessionStart`, `UserPromptSubmit`, `Stop`) | `.claude/settings.json`, `.claude/skills/`, `.claude/agents/` | Semantic workflow contracts are reminder-observed; Rule-of-3 reflection and explicit permission boundaries may block |
|
|
176
176
|
| **OpenCode** | Native plugin module ([`opencode-plugin/index.mjs`](opencode-plugin/index.mjs), install as `harness-enforcement.js`) | `.opencode/plugins/` | **Partial live-host evidence** — project-scope `.js` loading and edit/verification state on OpenCode 1.18.31 (macOS); current workflow/verification behavior is reminder-oriented, with only the third-failure reflection boundary blocking edits |
|
|
177
|
-
| **Codex — general installer path** | Skills + `AGENTS.md`
|
|
178
|
-
| **Codex / local OpenAI plugin** | `.codex-plugin` package with session, prompt, supported-tool, subagent, and stop hooks plus 26 canonical skills | `.agents/plugins/marketplace.json` → `plugins/harness-everything/` | **Mechanism-tested local
|
|
177
|
+
| **Codex — general installer path** | Skills + `AGENTS.md` instructions | `AGENTS.md` + repo-scoped `.agents/skills/` | **Instruction/advisory delivery only**; semantic MUST/SHOULD/MAY still applies, without a hard-enforcement claim |
|
|
178
|
+
| **Codex / local OpenAI plugin** | `.codex-plugin` package with session, prompt, supported-tool, subagent, and stop hooks plus 26 canonical skills | `.agents/plugins/marketplace.json` → `plugins/harness-everything/` | **Mechanism-tested local contract observation plus explicit permission/Rule-of-3 boundaries** for the packaged mappings; live host loading remains unverified |
|
|
179
179
|
| **Public OpenAI Skills-only plugin** | Public Skills-only bundle | Generated submission ZIP from `plugins/harness-everything/skills/` | **Skill/workflow behavior only**; no local `.codex-plugin` lifecycle hooks in the public artifact |
|
|
180
180
|
| **Cursor** | Native Project Rules + project skills | `.cursorrules` + `.cursor/skills/` | Advisory only |
|
|
181
181
|
| **GitHub Copilot agent surfaces** | Agent Skills + repository custom instructions | `.github/copilot-instructions.md` + `.github/skills/` | Agent Skills path is documented; no live Harness session or plugin install is verified |
|
|
@@ -246,9 +246,9 @@ This repo uses a flat layout (waza/agentskills.io convention). The table below m
|
|
|
246
246
|
| `skill-creator` | **Meta** | Create new skills from patterns |
|
|
247
247
|
| `skill-style` | **Meta** | Skill authoring style guide |
|
|
248
248
|
| `tdd` | **Skill (Tier 2)** | Test-driven development when executable behavior benefits from it |
|
|
249
|
-
| `to-spec` | **
|
|
250
|
-
| `to-tickets` | **
|
|
251
|
-
| `todo-driven-workflow` | **
|
|
249
|
+
| `to-spec` | **Optional (MAY, Tier 2/3)** | Publish specs from settled conversations |
|
|
250
|
+
| `to-tickets` | **Optional (MAY, Tier 2/3)** | Decompose settled specs into tracked tickets |
|
|
251
|
+
| `todo-driven-workflow` | **Optional Foundation (MAY)** | Progress tracking when explicit multi-step state helps |
|
|
252
252
|
| `using-git-worktrees` | **Skill (Tier 2)** | Git worktree concurrency patterns |
|
|
253
253
|
| `verification-loop` | **Skill (Tier 2)** | Select systematic verification evidence; kernel still requires evidence before completion |
|
|
254
254
|
| `verify-before-claim` | **Always-on discipline** | Fact-audit before asserting claims |
|
|
@@ -263,7 +263,7 @@ For a deep dive into individual modules and the underlying philosophy, explore o
|
|
|
263
263
|
|
|
264
264
|
* [Harness Philosophy](docs/philosophy.md): The core behavior-first, intervention-only design.
|
|
265
265
|
* [Harness Architecture](docs/architecture.md): Lifecycle hooks, security model, and data locality.
|
|
266
|
-
* [
|
|
266
|
+
* [Semantic Contracts and Safety Boundary Diagnostic Flows](docs/enforcement-locks.md): Distinguish MUST/SHOULD/MAY obligations from reminder mechanics and the two intentional blocking boundaries.
|
|
267
267
|
* [Platform Capability Matrix](docs/platform-capabilities.md): Canonical current enforcement/install/evidence boundary per surface.
|
|
268
268
|
* [Repository Runtime & Workflow Contract](docs/repository-contract.md): Generated Node/action/workflow/gate state used by consistency CI.
|
|
269
269
|
* [OpenAI / ChatGPT Plugin Packaging](docs/openai-plugin.md): Local Codex/OpenAI plugin packaging plus public Skills-only submission boundary.
|
|
@@ -273,7 +273,7 @@ For a deep dive into individual modules and the underlying philosophy, explore o
|
|
|
273
273
|
|
|
274
274
|
Fable model selection is documented in [fable-mode/references/model-matrix.md](fable-mode/references/model-matrix.md); the explicit entrypoints are `fable-haiku`, `fable-sonnet`, and `fable-opus`.
|
|
275
275
|
|
|
276
|
-
Maintainers
|
|
276
|
+
Maintainers **MUST** follow [RELEASING.md](RELEASING.md) for tag-driven npm releases and record observations in [docs/release-evidence.md](docs/release-evidence.md). Issue #20 is closed (2026-09-10); its coordination history lives in git.
|
|
277
277
|
|
|
278
278
|
---
|
|
279
279
|
|
package/RELEASING.md
CHANGED
|
@@ -38,9 +38,11 @@ A push to `main` runs the full reusable CI gate and then semantic-release. A man
|
|
|
38
38
|
4. Exit without publishing when there is no releasable commit.
|
|
39
39
|
5. Calculate the next stable SemVer.
|
|
40
40
|
6. Run `scripts/sync-release-version.js` to synchronize package, Claude, OpenAI/Codex, OpenCode, lockfile, and changed canonical skill version fields.
|
|
41
|
-
7. Regenerate and verify plugin packages.
|
|
41
|
+
7. Regenerate and verify plugin packages, then generate and validate the release-only `sbom.cdx.json` CycloneDX 1.7 file.
|
|
42
42
|
8. Update `CHANGELOG.md` and create `chore(release): X.Y.Z [skip ci]`.
|
|
43
|
-
9. Create tag `vX.Y.Z`, publish npm with provenance, and create the GitHub Release.
|
|
43
|
+
9. Create tag `vX.Y.Z`, publish npm with provenance (including the generated SBOM), and create the GitHub Release.
|
|
44
|
+
|
|
45
|
+
The SBOM is generated from the release `package.json`/`package-lock.json` as CycloneDX 1.7, the current 1.x format, to satisfy consumers and regulatory baselines requiring CycloneDX 1.6 or later. It is intentionally not committed to Git. npm packaging is tested to ensure `sbom.cdx.json` is included in the published tarball.
|
|
44
46
|
|
|
45
47
|
Release concurrency is serialized so two updates to `main` cannot publish competing versions.
|
|
46
48
|
|
|
@@ -69,6 +71,12 @@ node scripts/sync-release-version.js --validate 1.2.3
|
|
|
69
71
|
|
|
70
72
|
Prerelease/build suffixes such as `1.2.3-beta` or `1.2.3+meta` are rejected.
|
|
71
73
|
|
|
74
|
+
The release SBOM can be checked independently with:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npm run test:release:sbom
|
|
78
|
+
```
|
|
79
|
+
|
|
72
80
|
## Contributor requirements
|
|
73
81
|
|
|
74
82
|
The final commit that lands on `main` must use a Conventional Commit type because it is release input. With squash merging, the PR title becomes especially important. Use `feat`, `fix`, `perf`, `refactor`, `build`, or `revert` when a shipped change needs a release, and use non-releasing types for changes that should not publish.
|
|
@@ -4,18 +4,18 @@ const fs=require('fs'),path=require('path'),{spawnSync}=require('child_process')
|
|
|
4
4
|
const ROOT=path.resolve(__dirname,'..');let failed=0;
|
|
5
5
|
function check(c,m){if(c)console.log(' PASS '+m);else{console.error(' FAIL '+m);failed++;}}
|
|
6
6
|
function read(p){return fs.readFileSync(path.join(ROOT,p),'utf8');}
|
|
7
|
-
console.log('===
|
|
7
|
+
console.log('=== Semantic Contract-Strength Routing Contract ===');
|
|
8
8
|
const kernel=path.join(ROOT,'harness-everything/scripts/kernel-router.js');
|
|
9
9
|
const tier2=spawnSync(process.execPath,[kernel,'add a login endpoint with tests and update the implementation'],{cwd:ROOT,encoding:'utf8'});
|
|
10
10
|
check(tier2.status===0,'kernel router exits successfully');
|
|
11
11
|
check(/RECOMMENDED TIER:\s*Tier 2/i.test(tier2.stdout),'classifier result is preserved');
|
|
12
|
-
check(tier2.stdout.includes('"strategy":"iterative-single"'),'Tier 2 selects iterative-single
|
|
12
|
+
check(tier2.stdout.includes('"strategy":"iterative-single"'),'Tier 2 selects iterative-single workflow');
|
|
13
13
|
check(tier2.stdout.includes('loop-awareness:'),'iterative work exposes loop-awareness instead of a hard budget');
|
|
14
|
-
check(tier2.stdout.includes('
|
|
15
|
-
check(tier2.stdout.includes('ORCHESTRATION POLICY: Selected
|
|
16
|
-
check(tier2.stdout.includes('WORKFLOW
|
|
17
|
-
check(tier2.stdout.includes('
|
|
18
|
-
check(!tier2.stdout.includes('WORKFLOW
|
|
14
|
+
check(tier2.stdout.includes('WORKFLOW SKILLS (APPLICABILITY MUST BE RESOLVED)'),'skill applicability is explicitly mandatory');
|
|
15
|
+
check(tier2.stdout.includes('ORCHESTRATION POLICY: Selected-topology required obligations and applicable skill core contracts are semantic MUSTs'),'orchestration policy preserves semantic MUST obligations');
|
|
16
|
+
check(tier2.stdout.includes('WORKFLOW SEMANTIC CONTRACT (NON-BLOCKING OBSERVATION)'),'kernel separates semantic contract from non-blocking observation');
|
|
17
|
+
check(tier2.stdout.includes('Tier 3 / Fable broad mutation MUST resolve isolation'),'worktree isolation disposition is a semantic MUST');
|
|
18
|
+
check(!tier2.stdout.includes('SELECTED WORKFLOW IS GUIDANCE'),'old planning-guidance label is absent');
|
|
19
19
|
check(!tier2.stdout.includes('unavailable isolation means BLOCKED'),'old worktree hard-block wording is absent');
|
|
20
20
|
check(tier2.stdout.includes('evaluate-suggestions-before-skip'),'skill suggestions still require evaluation before omission');
|
|
21
21
|
check(tier2.stdout.includes('visible-status-updates'),'workflow plan carries mandatory user-visible status invariant');
|
|
@@ -31,46 +31,69 @@ check(tier2.stdout.includes('semantic communication MUST, not a hard execution l
|
|
|
31
31
|
const tier3=spawnSync(process.execPath,[kernel,'audit the entire repository architecture and coordinate multiple modules'],{cwd:ROOT,encoding:'utf8'});
|
|
32
32
|
check(tier3.status===0,'Tier 3 routing exits successfully');
|
|
33
33
|
check(/RECOMMENDED TIER:\s*Tier 3/i.test(tier3.stdout),'macro task remains Tier 3');
|
|
34
|
-
check(tier3.stdout.includes('using-git-worktrees'),'Tier 3 still
|
|
35
|
-
check(tier3.stdout.includes('
|
|
34
|
+
check(tier3.stdout.includes('using-git-worktrees'),'Tier 3 still routes the worktree skill');
|
|
35
|
+
check(tier3.stdout.includes('Tier 3 / Fable broad mutation MUST resolve isolation'),'Tier 3 requires an isolation disposition without a hard lock');
|
|
36
36
|
|
|
37
37
|
const hs=read('harness-everything/SKILL.md');
|
|
38
|
-
check(/
|
|
38
|
+
check(/required obligations are MUST; tactics MAY adapt/i.test(hs),'Harness skill separates required obligations from adaptable tactics');
|
|
39
39
|
check(/only Rule-of-3 reflection and explicit user\/host permission boundaries may block/i.test(hs),'Harness skill names the only intentional blocking boundaries');
|
|
40
|
-
check(/Surface status
|
|
40
|
+
check(/Surface status \(MUST\).*Harness Status/i.test(hs)&&/Read \/ Evidence/i.test(hs),'Harness skill requires the readable unified user-visible status');
|
|
41
41
|
check(read('plugins/harness-everything/skills/harness-everything/SKILL.md')===hs,'Harness skill mirror matches');
|
|
42
42
|
|
|
43
43
|
const wt=read('using-git-worktrees/SKILL.md');
|
|
44
|
-
check(/
|
|
44
|
+
check(/Tier 3 \/ Fable \(MUST resolve\)/i.test(wt)&&/explicit degraded fallback/i.test(wt),'worktree skill requires isolation disposition but permits degraded fallback');
|
|
45
45
|
check(!/Creation\/entry failure => `BLOCKED`/i.test(wt),'worktree creation failure is not a cognitive blocked state');
|
|
46
46
|
check(read('plugins/harness-everything/skills/using-git-worktrees/SKILL.md')===wt,'worktree skill mirror matches');
|
|
47
47
|
|
|
48
48
|
const triage=read('harness-everything/references/triage-and-tiers.md');
|
|
49
|
-
check(/
|
|
49
|
+
check(/Contract-first lifecycle/i.test(triage),'triage reference uses contract-first policy');
|
|
50
50
|
check(/User-visible status contract/i.test(triage)&&/Harness Status/i.test(triage)&&/MUST/i.test(triage),'triage defines the mandatory unified status contract');
|
|
51
51
|
check(read('plugins/harness-everything/skills/harness-everything/references/triage-and-tiers.md')===triage,'triage mirror matches');
|
|
52
52
|
|
|
53
|
-
for(const p of ['docs/routing.md','docs/architecture.md','docs/philosophy.md'
|
|
54
|
-
const t=read(p); check(/
|
|
53
|
+
for(const p of ['docs/routing.md','docs/architecture.md','docs/philosophy.md']){
|
|
54
|
+
const t=read(p); check(/MUST/i.test(t)&&/MAY/i.test(t),'current doc '+p+' preserves explicit semantic strength');
|
|
55
55
|
}
|
|
56
56
|
for(const p of ['docs/routing.md','docs/architecture.md','docs/workflow-runtime.md']){
|
|
57
57
|
const t=read(p); check(/Harness Status/i.test(t)&&/MUST/i.test(t),'current doc '+p+' defines mandatory user-visible status');
|
|
58
58
|
}
|
|
59
|
+
const philosophy=read('docs/philosophy.md');
|
|
60
|
+
check(/Contract Strength: MUST \/ SHOULD \/ MAY/i.test(philosophy),'philosophy defines canonical MUST/SHOULD/MAY strength');
|
|
61
|
+
for(const phrase of [
|
|
62
|
+
'Route before software/project execution',
|
|
63
|
+
'Read/evaluate every suggested skill before omission',
|
|
64
|
+
'Resolve selected-topology invariants/stages/checks/synthesis/verification',
|
|
65
|
+
'Discover relevant environment/host facts',
|
|
66
|
+
'Resolve Tier-3/Fable isolation before broad mutation',
|
|
67
|
+
'Numeric iteration/revision/replan/worker values',
|
|
68
|
+
'Durable memory writes'
|
|
69
|
+
]){
|
|
70
|
+
check(philosophy.includes(phrase),'contract-strength audit classifies '+phrase);
|
|
71
|
+
}
|
|
72
|
+
check(!/Applicable workflow is guidance:/i.test(philosophy),'old ambiguous philosophy wording is removed');
|
|
73
|
+
|
|
59
74
|
const advisory=read('scripts/lib/advisory-text.js');
|
|
60
|
-
check(/
|
|
75
|
+
check(/Selected-topology required obligations are MUSTs/i.test(advisory)&&/numeric.*MAY guide planning/i.test(advisory),'instruction-only installer preserves MUST/MAY semantics');
|
|
61
76
|
check(/USER-VISIBLE STATUS \(MUST\)/i.test(advisory)&&/### 🚦 Harness Status/i.test(advisory)&&/\*\*Read \/ Evidence:\*\*/i.test(advisory),'instruction-only installers carry the readable mandatory status contract');
|
|
62
77
|
check(/Rule of 3/i.test(advisory)&&/Permission boundaries are separate/i.test(advisory),'installer text preserves Rule-of-3 and permission boundaries');
|
|
63
78
|
check(read('plugins/harness-everything/scripts/lib/advisory-text.js')===advisory,'OpenAI advisory mirror matches');
|
|
64
79
|
|
|
65
80
|
const agents=read('AGENTS.md');
|
|
66
|
-
check(/Selected workflow is
|
|
81
|
+
check(/Selected workflow is a semantic contract/i.test(agents),'repository agent contract is contract-first');
|
|
67
82
|
check(/User-visible Harness Status is mandatory/i.test(agents)&&/### 🚦 Harness Status/i.test(agents)&&/nested evidence bullets/i.test(agents),'repository agent contract requires readable unified user-visible status');
|
|
68
|
-
check(/
|
|
83
|
+
check(/Tier-3\/Fable isolation disposition is mandatory/i.test(agents)&&/degraded fallback/i.test(agents),'repository worktree rule requires disposition without hard lock');
|
|
84
|
+
|
|
85
|
+
const envSkill=read('environment-detection/SKILL.md');
|
|
86
|
+
check(/semantic \*\*MUST\*\*/i.test(envSkill)&&/environment-sensitive/i.test(envSkill),'environment discovery is a conditional semantic MUST');
|
|
87
|
+
check(read('plugins/harness-everything/skills/environment-detection/SKILL.md')===envSkill,'environment skill mirror matches');
|
|
88
|
+
|
|
89
|
+
const commitSkill=read('git-commit/SKILL.md');
|
|
90
|
+
check(/MUST.*git diff --cached/i.test(commitSkill)&&/SHOULD.*split/i.test(commitSkill),'commit skill separates staged-diff MUST from split SHOULD');
|
|
91
|
+
check(read('plugins/harness-everything/skills/git-commit/SKILL.md')===commitSkill,'git-commit skill mirror matches');
|
|
69
92
|
|
|
70
93
|
const hooks=JSON.parse(read('hooks/hooks.json'));
|
|
71
94
|
check((hooks.hooks.PreToolUse||[]).some(e=>e.id==='harness:pre:workflow-gate'),'Claude packages workflow reminder hook');
|
|
72
95
|
check((hooks.hooks.PreToolUse||[]).some(e=>e.id==='harness:pre:rule-of-3'),'Claude preserves Rule-of-3 boundary');
|
|
73
96
|
check((hooks.hooks.PreToolUse||[]).some(e=>e.id==='harness:pre:action-gate'),'Claude preserves action permission gate');
|
|
74
97
|
|
|
75
|
-
console.log('\n'+(failed===0?'PASS':'FAIL')+':
|
|
98
|
+
console.log('\n'+(failed===0?'PASS':'FAIL')+': semantic contract-strength routing contract ('+failed+' failures)');
|
|
76
99
|
process.exit(failed===0?0:1);
|
|
@@ -16,10 +16,10 @@ try{
|
|
|
16
16
|
fs.writeFileSync(path.join(dir,'workflow-run.json'),JSON.stringify({schemaVersion:1,sessionId:'worktree-guidance',tier:'tier3',strategy:'iterative-single',state:'active'}));
|
|
17
17
|
const primary=runGate('Write',repo,{file_path:path.join(repo,'src.js'),content:'x'});
|
|
18
18
|
check(primary.status===0,'Tier-3 primary-tree mutation is not hard-blocked',primary.stderr);
|
|
19
|
-
check(/worktree/i.test(primary.stderr),'Tier-3 primary-tree mutation emits
|
|
19
|
+
check(/semantic MUST/i.test(primary.stderr)&&/worktree/i.test(primary.stderr),'Tier-3 primary-tree mutation emits mandatory isolation disposition without blocking',primary.stderr);
|
|
20
20
|
const mutator=runGate('Bash',repo,{command:'git status --short && rm -rf src'});
|
|
21
21
|
check(mutator.status===0,'mutation-shaped shell command remains available',mutator.stderr);
|
|
22
|
-
check(/worktree/i.test(mutator.stderr),'mutation-shaped shell command receives
|
|
22
|
+
check(/semantic MUST/i.test(mutator.stderr)&&/worktree/i.test(mutator.stderr),'mutation-shaped shell command receives the same isolation contract',mutator.stderr);
|
|
23
23
|
const readOnly=runGate('Bash',repo,{command:'git status --short'});
|
|
24
24
|
check(readOnly.status===0,'read-only discovery remains available');
|
|
25
25
|
const create=git(repo,['worktree','add',linked,'-b','guidance-test']);check(create.status===0,'linked worktree fixture creates',create.stderr);
|
|
@@ -37,4 +37,4 @@ try{
|
|
|
37
37
|
check(corrupt.status===0,'corrupt workflow state fails open',corrupt.stderr);
|
|
38
38
|
}finally{fs.rmSync(temp,{recursive:true,force:true});}
|
|
39
39
|
if(failed)process.exit(1);
|
|
40
|
-
console.log('PASS: worktree isolation is
|
|
40
|
+
console.log('PASS: worktree isolation is a semantic MUST disposition, not a cognitive lock');
|
|
@@ -18,6 +18,7 @@ assert.strictEqual(tier3.strategy, 'fable-staged');
|
|
|
18
18
|
assert.ok(tier3.requiredInvariants.includes('isolated-worktree-before-mutation'), 'Tier 3 plan must carry mutation isolation invariant');
|
|
19
19
|
assert.ok(tier3.suggestedSkills.includes('using-git-worktrees'), 'Tier 3 plan must surface the worktree workflow');
|
|
20
20
|
assert.strictEqual(tier3.workspace.required, false, 'Git worktree isolation must remain distinct from durable multi-agent workspace state');
|
|
21
|
+
assert.strictEqual(tier3.mutationIsolation.onUnavailable, 'degraded', 'unavailable isolation records an explicit degraded fallback instead of a cognitive hard block');
|
|
21
22
|
|
|
22
23
|
const tier2 = router.buildRouterContract({
|
|
23
24
|
routingStatus: 'ok',
|
|
@@ -47,6 +47,7 @@ let workflow = readJson(workflowFile);
|
|
|
47
47
|
let obligations = readJson(obligationFile);
|
|
48
48
|
check(workflow.tier === 'tier2' && workflow.strategy === 'iterative-single', 'Tier 2 receives a preliminary iterative-single route');
|
|
49
49
|
check(workflow.state === 'pending', 'selected Tier 2 workflow begins pending');
|
|
50
|
+
check(workflow.guidance?.mode === 'semantic-contract', 'persisted workflow records semantic-contract mode rather than advisory-workflow');
|
|
50
51
|
check(obligations.phase === 'planning', 'Tier 2 immediately materializes a planning contract');
|
|
51
52
|
check(obligations.obligations.map(item => item.id).join(',') === 'decompose,compose', 'planning starts with decompose then compose');
|
|
52
53
|
check(obligations.requirements.length === 0, 'requirements begin empty instead of being invented by the router');
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const assert = require('assert');
|
|
4
|
+
const childProcess = require('child_process');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const {
|
|
9
|
+
buildBom,
|
|
10
|
+
CYCLONEDX_SCHEMA_URL,
|
|
11
|
+
CYCLONEDX_VERSION,
|
|
12
|
+
validateBom,
|
|
13
|
+
writeBom
|
|
14
|
+
} = require('../scripts/generate-sbom');
|
|
15
|
+
|
|
16
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
17
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'));
|
|
18
|
+
const releaseConfig = JSON.parse(fs.readFileSync(path.join(ROOT, '.releaserc.json'), 'utf8'));
|
|
19
|
+
const execFileSync = childProcess.execFileSync;
|
|
20
|
+
const npmCommand = 'npm';
|
|
21
|
+
|
|
22
|
+
const execPlugin = releaseConfig.plugins.find(plugin => Array.isArray(plugin) && plugin[0] === '@semantic-release/exec');
|
|
23
|
+
assert.ok(execPlugin, 'semantic-release exec plugin is required for SBOM generation');
|
|
24
|
+
assert.match(execPlugin[1].prepareCmd, /generate-sbom\.js --output sbom\.cdx\.json --version \$\{nextRelease\.version\}/);
|
|
25
|
+
assert.match(execPlugin[1].prepareCmd, /generate-sbom\.js --validate sbom\.cdx\.json --version \$\{nextRelease\.version\}/);
|
|
26
|
+
|
|
27
|
+
const bom = buildBom(ROOT, {
|
|
28
|
+
version: packageJson.version,
|
|
29
|
+
timestamp: '2026-09-21T00:00:00.000Z',
|
|
30
|
+
serialNumber: 'urn:uuid:00000000-0000-5000-8000-000000000001'
|
|
31
|
+
});
|
|
32
|
+
assert.doesNotThrow(() => validateBom(bom, packageJson.version));
|
|
33
|
+
assert.strictEqual(bom.bomFormat, 'CycloneDX');
|
|
34
|
+
assert.strictEqual(bom.$schema, CYCLONEDX_SCHEMA_URL);
|
|
35
|
+
assert.strictEqual(bom.specVersion, CYCLONEDX_VERSION);
|
|
36
|
+
assert.strictEqual(CYCLONEDX_VERSION, '1.7');
|
|
37
|
+
assert.match(bom.serialNumber, /^urn:uuid:/);
|
|
38
|
+
assert.strictEqual(bom.metadata.component.version, packageJson.version);
|
|
39
|
+
assert.ok(bom.components.length > 0, 'SBOM must include lockfile components');
|
|
40
|
+
assert.ok(bom.components.every(component => component.purl.startsWith('pkg:npm/')));
|
|
41
|
+
assert.ok(bom.components.some(component => component.name.startsWith('@') && component.purl.includes('%40')), 'scoped npm packages must use valid PURLs');
|
|
42
|
+
assert.ok(bom.dependencies.some(entry => entry.ref === `pkg:npm/${packageJson.name}@${packageJson.version}`));
|
|
43
|
+
|
|
44
|
+
const output = path.join(os.tmpdir(), `harness-sbom-${process.pid}.cdx.json`);
|
|
45
|
+
try {
|
|
46
|
+
writeBom(output, ROOT, { version: packageJson.version, timestamp: '2026-09-21T00:00:00.000Z' });
|
|
47
|
+
const written = JSON.parse(fs.readFileSync(output, 'utf8'));
|
|
48
|
+
assert.doesNotThrow(() => validateBom(written, packageJson.version));
|
|
49
|
+
} finally {
|
|
50
|
+
fs.rmSync(output, { force: true });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const packRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-sbom-pack-'));
|
|
54
|
+
try {
|
|
55
|
+
fs.cpSync(ROOT, packRoot, {
|
|
56
|
+
recursive: true,
|
|
57
|
+
filter: source => {
|
|
58
|
+
const relative = path.relative(ROOT, source).replace(/\\/g, '/');
|
|
59
|
+
return relative === '' || !['.git', 'node_modules', '.husky', '.mechanism-test-opencode-home', '.mechanism-test-opencode-workspace'].some(prefix => relative === prefix || relative.startsWith(`${prefix}/`));
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
const generated = writeBom(path.join(packRoot, 'sbom.cdx.json'), packRoot, { version: packageJson.version, timestamp: '2026-09-21T00:00:00.000Z' });
|
|
63
|
+
const packOutput = execFileSync(npmCommand, ['pack', '--dry-run', '--json', '--ignore-scripts'], {
|
|
64
|
+
cwd: packRoot,
|
|
65
|
+
encoding: 'utf8',
|
|
66
|
+
shell: process.platform === 'win32',
|
|
67
|
+
env: {
|
|
68
|
+
...process.env,
|
|
69
|
+
HUSKY: '0',
|
|
70
|
+
npm_config_ignore_scripts: 'true'
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const jsonStart = packOutput.indexOf('[');
|
|
74
|
+
const jsonEnd = packOutput.lastIndexOf(']');
|
|
75
|
+
assert.ok(jsonStart >= 0 && jsonEnd > jsonStart, 'npm pack --json output must include JSON records');
|
|
76
|
+
const records = JSON.parse(packOutput.slice(jsonStart, jsonEnd + 1));
|
|
77
|
+
const files = records.flatMap(record => record.files || []).map(file => file.path);
|
|
78
|
+
assert.ok(files.includes('sbom.cdx.json'), 'npm pack must include the generated SBOM');
|
|
79
|
+
assert.strictEqual(generated.metadata.component.version, packageJson.version);
|
|
80
|
+
} finally {
|
|
81
|
+
fs.rmSync(packRoot, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let tracked = true;
|
|
85
|
+
try {
|
|
86
|
+
execFileSync('git', ['ls-files', '--error-unmatch', 'sbom.cdx.json'], { cwd: ROOT, stdio: 'ignore' });
|
|
87
|
+
} catch (_) {
|
|
88
|
+
tracked = false;
|
|
89
|
+
}
|
|
90
|
+
assert.strictEqual(tracked, false, 'release-generated SBOM must remain untracked');
|
|
91
|
+
|
|
92
|
+
console.log(`CycloneDX SBOM verified: ${bom.components.length} lockfile components and npm pack inclusion.`);
|
|
@@ -28,8 +28,8 @@ check((dockerVerify.match(/\$STATE_DIR\//g) || []).length >= 10,
|
|
|
28
28
|
'#205 docker verifier routes all state checks through STATE_DIR');
|
|
29
29
|
|
|
30
30
|
const architecture = fs.readFileSync(path.join(ROOT, 'docs/architecture.md'), 'utf8');
|
|
31
|
-
check(architecture.includes('
|
|
32
|
-
'#206 architecture
|
|
31
|
+
check(architecture.includes('MAY-level loop-awareness planning hints'),
|
|
32
|
+
'#206 architecture keeps loop-awareness numeric guidance explicitly non-mandatory');
|
|
33
33
|
check(!/\bloop budgets\b/.test(architecture),
|
|
34
34
|
'#206 architecture does not describe retired loop budgets as enforcement');
|
|
35
35
|
|
|
@@ -162,7 +162,7 @@ assert.ok(hooks.hooks.Stop?.length, 'Stop hook missing');
|
|
|
162
162
|
const hookText = JSON.stringify(hooks);
|
|
163
163
|
assert.match(hookText, /PLUGIN_ROOT/, 'plugin hooks must resolve from PLUGIN_ROOT');
|
|
164
164
|
assert.match(hookText, /commandWindows/, 'plugin hooks need a Windows command override');
|
|
165
|
-
assert.match(hookText, /workflow-gate\.js/, 'plugin hooks must package workflow
|
|
165
|
+
assert.match(hookText, /workflow-gate\.js/, 'plugin hooks must package workflow contract observation');
|
|
166
166
|
assert.match(hookText, /workflow-stop-gate\.js/, 'plugin hooks must package workflow completion reminders');
|
|
167
167
|
|
|
168
168
|
const session = spawnSync(process.execPath, [path.join(PLUGIN, 'hooks', 'session-start.js')], { encoding: 'utf8' });
|
|
@@ -190,14 +190,14 @@ assert.strictEqual(second.status, 0, second.stderr);
|
|
|
190
190
|
assert.strictEqual(first.stdout, second.stdout, 'identical routing input must produce identical output');
|
|
191
191
|
assert.match(first.stdout, /RECOMMENDED TIER:\s*Tier 2/i);
|
|
192
192
|
assert.match(first.stdout, /REQUIRED HARNESS INVARIANTS/);
|
|
193
|
-
assert.match(first.stdout, /WORKFLOW SKILLS \(
|
|
193
|
+
assert.match(first.stdout, /WORKFLOW SKILLS \(APPLICABILITY MUST BE RESOLVED\)/);
|
|
194
194
|
assert.match(first.stdout, /evaluate-suggestions-before-skip/);
|
|
195
195
|
assert.match(first.stdout, /read its complete SKILL\.md entry/);
|
|
196
196
|
assert.doesNotMatch(first.stdout, /BASE EXECUTION LOOP/);
|
|
197
|
-
assert.match(first.stdout, /ORCHESTRATION POLICY: Selected
|
|
198
|
-
assert.match(first.stdout, /WORKFLOW
|
|
197
|
+
assert.match(first.stdout, /ORCHESTRATION POLICY: Selected-topology required obligations and applicable skill core contracts are semantic MUSTs/);
|
|
198
|
+
assert.match(first.stdout, /WORKFLOW SEMANTIC CONTRACT \(NON-BLOCKING OBSERVATION\)/);
|
|
199
199
|
assert.match(first.stdout, /Selected workflow: iterative-single/);
|
|
200
|
-
assert.match(first.stdout, /Before claiming completion,
|
|
200
|
+
assert.match(first.stdout, /Before claiming completion, MUST resolve required workflow evidence and objective verification/);
|
|
201
201
|
assert.doesNotMatch(first.stdout, /budget-exhausted|reset-budget/);
|
|
202
202
|
|
|
203
203
|
const trivial = route('Update one README typo');
|
|
@@ -213,4 +213,4 @@ assert.match(unmatched.stdout, /RECOMMENDED TIER:\s*Unclassified/i);
|
|
|
213
213
|
assert.match(unmatched.stdout, /"tier":"unclassified"/i);
|
|
214
214
|
assert.doesNotMatch(unmatched.stdout, /RECOMMENDED TIER:\s*Tier 1/i);
|
|
215
215
|
|
|
216
|
-
console.log(`OpenAI plugin package verified: ${skillNames.length} skills, publication metadata, hooks, marketplace, deterministic
|
|
216
|
+
console.log(`OpenAI plugin package verified: ${skillNames.length} skills, publication metadata, hooks, marketplace, deterministic semantic-contract routing.`);
|
|
@@ -67,6 +67,7 @@ if (validContract(direct, 'direct-single')) {
|
|
|
67
67
|
check(plan.strategy === 'direct-single', 'one-file trivial task selects direct-single');
|
|
68
68
|
check(plan.strategySelection === 'selected', 'direct-single is a selected strategy');
|
|
69
69
|
check(plan.requiredInvariants.includes('visible-status-updates'), 'every selected workflow carries the user-visible status invariant');
|
|
70
|
+
check(plan.requiredInvariants.includes('environment-alignment'), 'every selected workflow carries conditional environment-alignment MUST');
|
|
70
71
|
check(plan.workspace.required === false, 'direct-single does not require a workspace');
|
|
71
72
|
check(plan.parallelism.allowed === false, 'direct-single does not parallelize');
|
|
72
73
|
}
|
|
@@ -76,15 +77,15 @@ if (validContract(iterative, 'iterative-single')) {
|
|
|
76
77
|
const plan = iterative.contract.workflowPlan;
|
|
77
78
|
check(plan.tier === 'tier2', 'ordinary test-first bug fix is tier2');
|
|
78
79
|
check(plan.strategy === 'iterative-single', 'ordinary bug fix selects iterative-single');
|
|
79
|
-
check(plan.limits.maxIterations === ITERATIVE_MAX_ITERATIONS, 'iterative-single retains
|
|
80
|
-
check(plan.limits.maxRevisionRounds === WORKFLOW_MAX_REVISION_ROUNDS, 'workflow exposes
|
|
81
|
-
check(plan.limits.maxReplans === FABLE_MAX_REPLANS, 'workflow exposes
|
|
82
|
-
check(plan.limits.maxWorkers === FABLE_MAX_WORKERS, 'workflow exposes
|
|
80
|
+
check(plan.limits.maxIterations === ITERATIVE_MAX_ITERATIONS, 'iterative-single retains a MAY iteration planning value');
|
|
81
|
+
check(plan.limits.maxRevisionRounds === WORKFLOW_MAX_REVISION_ROUNDS, 'workflow exposes a MAY revision planning value');
|
|
82
|
+
check(plan.limits.maxReplans === FABLE_MAX_REPLANS, 'workflow exposes a MAY replan planning value');
|
|
83
|
+
check(plan.limits.maxWorkers === FABLE_MAX_WORKERS, 'workflow exposes a MAY worker planning value');
|
|
83
84
|
check(plan.requiredInvariants.includes('objective-verification'), 'iterative-single carries objective verification invariant');
|
|
84
|
-
check(plan.requiredInvariants.includes('loop-awareness'), 'iterative-single carries loop-awareness
|
|
85
|
-
check(plan.suggestedSkills.includes('tdd'), 'TDD
|
|
85
|
+
check(plan.requiredInvariants.includes('loop-awareness'), 'iterative-single carries semantic loop-awareness obligation while numeric counts remain MAY');
|
|
86
|
+
check(plan.suggestedSkills.includes('tdd'), 'TDD remains applicability-conditional rather than a universal invariant');
|
|
86
87
|
check(plan.memory.write === 'none', 'ordinary iterative work cannot write durable memory');
|
|
87
|
-
check(!plan.requiredInvariants.includes('tdd'), 'suggested
|
|
88
|
+
check(!plan.requiredInvariants.includes('tdd'), 'suggested skill names remain separate from plan invariants until applicability is resolved');
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
const memoryPersist = runTier('Persist this lesson as memory after resolving the checkout regression.');
|
|
@@ -110,6 +111,8 @@ if (validContract(staged, 'fable-staged')) {
|
|
|
110
111
|
check(plan.strategy === 'fable-staged', 'dependent multi-stage work selects fable-staged');
|
|
111
112
|
check(plan.parallelism.allowed === false, 'dependent stages remain sequential');
|
|
112
113
|
check(plan.verification.mode === 'cold-verifier', 'fable-staged requires cold verification');
|
|
114
|
+
check(plan.requiredInvariants.includes('isolated-worktree-before-mutation'), 'fable-staged carries mandatory isolation disposition');
|
|
115
|
+
check(plan.suggestedSkills.includes('using-git-worktrees'), 'fable-staged surfaces worktree resolution skill');
|
|
113
116
|
}
|
|
114
117
|
|
|
115
118
|
const parallelPrompt = 'Audit the entire repository with independent read-only security, architecture, and documentation workstreams.';
|
|
@@ -287,10 +290,10 @@ const kernelIterative = spawnSync(process.execPath, [kernelRouter, 'Fix this che
|
|
|
287
290
|
encoding: 'utf8',
|
|
288
291
|
});
|
|
289
292
|
check(kernelIterative.stdout.includes('"strategy":"iterative-single"'), 'kernel consumes strategy from structured plan');
|
|
290
|
-
check(kernelIterative.stdout.includes('loop-awareness:'), 'kernel prints dynamic plan
|
|
293
|
+
check(kernelIterative.stdout.includes('loop-awareness:'), 'kernel prints dynamic semantic plan obligations');
|
|
291
294
|
check(kernelIterative.stdout.includes('visible-status-updates:'), 'kernel prints the user-visible status invariant');
|
|
292
295
|
check(kernelIterative.stdout.includes('USER-VISIBLE HARNESS STATUS CONTRACT (MUST)'), 'kernel prints the canonical mandatory user-visible status contract');
|
|
293
|
-
check(kernelIterative.stdout.includes(' - tdd'), 'kernel prints
|
|
296
|
+
check(kernelIterative.stdout.includes(' - tdd'), 'kernel prints suggested skills separately from required invariants');
|
|
294
297
|
|
|
295
298
|
for (const schemaPath of [
|
|
296
299
|
'harness-everything/schemas/router-task-shape.schema.json',
|
|
@@ -9,7 +9,7 @@ function runNode(args){return spawnSync(process.execPath,args,{cwd:ROOT,encoding
|
|
|
9
9
|
console.log('=== Workflow Guidance Contract ===');
|
|
10
10
|
for(const rel of ['harness-everything/scripts/kernel-router.js','hooks/scripts/workflow-gate.js','hooks/scripts/workflow-stop-gate.js','hooks/scripts/workflow-disposition.js','hooks/scripts/state-persist.js','hooks/scripts/rule-of-3.js','hooks/scripts/rule-of-3-tracker.js'])check(runNode(['--check',path.join(ROOT,rel)]).status===0,rel+' parses as valid JavaScript');
|
|
11
11
|
const ctx={workflow:{workflowPlan:{limits:{maxIterations:8,maxRevisionRounds:2,maxReplans:2,maxWorkers:4}}}};
|
|
12
|
-
for(const type of ['iteration','revision','replan','worker-acquire'])check(runtime.recordBudgetEvent(ctx,type,{evidence:'fixture'}).advisory===true,type+'
|
|
12
|
+
for(const type of ['iteration','revision','replan','worker-acquire'])check(runtime.recordBudgetEvent(ctx,type,{evidence:'fixture'}).advisory===true,type+' remains a MAY planning hint rather than blocking');
|
|
13
13
|
check(runtime.mutationProbeReservations(ctx)===0,'mutation probes reserve no capacity');
|
|
14
14
|
check(runtime.registerMutationProbe(ctx,'x','y')===null,'mutation probe registration is a no-op');
|
|
15
15
|
check(runtime.resetWorkflowBudget(ctx,'legacy').retired===true,'reset-budget API is retired compatibility only');
|
|
@@ -51,5 +51,5 @@ try{
|
|
|
51
51
|
check(stale.includes('independent-verifier-missing'),'Fable independent verifier is invalidated by newer handoff shell-edit evidence');
|
|
52
52
|
}finally{fs.rmSync(freshnessRoot,{recursive:true,force:true});}
|
|
53
53
|
|
|
54
|
-
console.log('\n'+(failed===0?'PASS':'FAIL')+': workflow
|
|
54
|
+
console.log('\n'+(failed===0?'PASS':'FAIL')+': workflow semantic contract mechanics ('+failed+' failures)');
|
|
55
55
|
process.exit(failed===0?0:1);
|