@mikenguyen69/harness 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +43 -0
  3. package/dist/build-identity.json +1 -0
  4. package/dist/cancellation.js +138 -0
  5. package/dist/cli.js +47 -0
  6. package/dist/dispatch.js +70 -0
  7. package/dist/help.js +47 -0
  8. package/dist/internal/agent/adapter/conformance.js +53 -0
  9. package/dist/internal/agent/adapter/hook.js +113 -0
  10. package/dist/internal/agent/adapter/install.js +30 -0
  11. package/dist/internal/agent/adapter/scope.js +55 -0
  12. package/dist/internal/agent/adapter/session.js +63 -0
  13. package/dist/internal/agent/adapter/settings.js +51 -0
  14. package/dist/internal/agent/cli.js +79 -0
  15. package/dist/internal/agent/evals/index.js +111 -0
  16. package/dist/internal/agent/index.js +15 -0
  17. package/dist/internal/agent/ledger-read.js +27 -0
  18. package/dist/internal/agent/routing/cli.js +104 -0
  19. package/dist/internal/agent/routing/index.js +123 -0
  20. package/dist/internal/agent/telemetry/index.js +97 -0
  21. package/dist/internal/orchestration/activity/index.js +111 -0
  22. package/dist/internal/orchestration/analyze/index.js +237 -0
  23. package/dist/internal/orchestration/cli.js +475 -0
  24. package/dist/internal/orchestration/config/index.js +66 -0
  25. package/dist/internal/orchestration/doctor/index.js +202 -0
  26. package/dist/internal/orchestration/forge/index.js +121 -0
  27. package/dist/internal/orchestration/git/index.js +181 -0
  28. package/dist/internal/orchestration/harness/cli.js +378 -0
  29. package/dist/internal/orchestration/harness/index.js +186 -0
  30. package/dist/internal/orchestration/harness/shim.js +182 -0
  31. package/dist/internal/orchestration/index.js +29 -0
  32. package/dist/internal/orchestration/loop/index.js +1107 -0
  33. package/dist/internal/orchestration/prompts/index.js +199 -0
  34. package/dist/internal/orchestration/report/index.js +125 -0
  35. package/dist/internal/orchestration/routes/index.js +85 -0
  36. package/dist/internal/orchestration/run/index.js +221 -0
  37. package/dist/internal/orchestration/runner/index.js +90 -0
  38. package/dist/internal/orchestration/runners/claude/index.js +246 -0
  39. package/dist/internal/orchestration/runners/claude/sdk.js +198 -0
  40. package/dist/internal/orchestration/runners/claude/wiring.js +98 -0
  41. package/dist/internal/orchestration/runners/codex/exec.js +114 -0
  42. package/dist/internal/orchestration/runners/codex/index.js +72 -0
  43. package/dist/internal/orchestration/runners/conformance/index.js +169 -0
  44. package/dist/internal/orchestration/runners/cursor/exec.js +531 -0
  45. package/dist/internal/orchestration/runners/cursor/index.js +184 -0
  46. package/dist/internal/orchestration/runners/stub/index.js +168 -0
  47. package/dist/internal/orchestration/runners/telemetry.js +36 -0
  48. package/dist/internal/orchestration/runstate/index.js +213 -0
  49. package/dist/internal/orchestration/runstate/publish.js +115 -0
  50. package/dist/internal/orchestration/worktree/index.js +89 -0
  51. package/dist/internal/system/adapters/index.js +19 -0
  52. package/dist/internal/system/agentops/index.js +16 -0
  53. package/dist/internal/system/agentops/scope.js +67 -0
  54. package/dist/internal/system/assets.js +45 -0
  55. package/dist/internal/system/board/cli.js +56 -0
  56. package/dist/internal/system/board/index.js +276 -0
  57. package/dist/internal/system/board/live.js +277 -0
  58. package/dist/internal/system/calibration/cli.js +45 -0
  59. package/dist/internal/system/calibration/index.js +141 -0
  60. package/dist/internal/system/cli.js +174 -0
  61. package/dist/internal/system/corpus/replay.js +79 -0
  62. package/dist/internal/system/digest/cli.js +23 -0
  63. package/dist/internal/system/digest/index.js +145 -0
  64. package/dist/internal/system/doors/classify.js +94 -0
  65. package/dist/internal/system/doors/cli.js +184 -0
  66. package/dist/internal/system/doors/index.js +249 -0
  67. package/dist/internal/system/doors/metrics.js +47 -0
  68. package/dist/internal/system/escapes/cli.js +45 -0
  69. package/dist/internal/system/escapes/index.js +81 -0
  70. package/dist/internal/system/explore/cli.js +77 -0
  71. package/dist/internal/system/explore/index.js +91 -0
  72. package/dist/internal/system/gates/cli.js +43 -0
  73. package/dist/internal/system/gates/detectors.js +55 -0
  74. package/dist/internal/system/gates/pre.js +51 -0
  75. package/dist/internal/system/hub/cli.js +51 -0
  76. package/dist/internal/system/hub/index.js +146 -0
  77. package/dist/internal/system/init/index.js +83 -0
  78. package/dist/internal/system/ledger/cli.js +54 -0
  79. package/dist/internal/system/ledger/index.js +176 -0
  80. package/dist/internal/system/manifest/index.js +207 -0
  81. package/dist/internal/system/provenance/index.js +13 -0
  82. package/dist/internal/system/report/index.js +15 -0
  83. package/dist/internal/system/runner/index.js +74 -0
  84. package/dist/internal/system/runstatus/cli.js +86 -0
  85. package/dist/internal/system/runstatus/index.js +168 -0
  86. package/dist/internal/system/sequencer/briefing.js +75 -0
  87. package/dist/internal/system/sequencer/cli.js +170 -0
  88. package/dist/internal/system/sequencer/index.js +156 -0
  89. package/dist/internal/system/spec/cli.js +110 -0
  90. package/dist/internal/system/spec/index.js +212 -0
  91. package/dist/internal/system/spec/materialize.js +111 -0
  92. package/dist/internal/system/spec/openspec-parse.js +83 -0
  93. package/dist/internal/system/spec/project.js +208 -0
  94. package/dist/internal/system/substrate/index.js +14 -0
  95. package/dist/internal/system/system/index.js +159 -0
  96. package/dist/internal/system/units/index.js +87 -0
  97. package/dist/internal/system/verify/cli.js +103 -0
  98. package/dist/internal/system/verify/declined-reasons.js +61 -0
  99. package/dist/internal/system/verify/index.js +188 -0
  100. package/dist/internal/system/verify/signing.js +79 -0
  101. package/dist/paths.js +50 -0
  102. package/dist/routes.js +93 -0
  103. package/dist/version.js +30 -0
  104. package/dist/win32-process-group.js +360 -0
  105. package/package.json +41 -0
  106. package/profiles/python/bindings.toml +59 -0
  107. package/profiles/terraform/bindings.toml +66 -0
  108. package/profiles/typescript/bindings.toml +64 -0
  109. package/profiles/typescript/smoke/README.md +8 -0
  110. package/schema/baseline.schema.json +26 -0
  111. package/schema/decision-classes.yaml +45 -0
  112. package/schema/envelope.schema.json +186 -0
  113. package/schema/ledger-event.schema.json +235 -0
  114. package/schema/manifest.schema.json +119 -0
  115. package/schema/routes.schema.json +55 -0
  116. package/schema/run-status.schema.json +162 -0
  117. package/schema/session-event.schema.json +74 -0
  118. package/schema/spec.schema.json +114 -0
  119. package/schema/system.schema.json +142 -0
  120. package/templates/ci/verify.yml +23 -0
  121. package/templates/target-kit/README.md +78 -0
  122. package/templates/target-kit/component.toml +20 -0
  123. package/templates/target-kit/orchestration.json +9 -0
  124. package/templates/target-kit/profiles/target/bindings.toml +6 -0
  125. package/templates/target-kit/routes.toml +5 -0
  126. package/templates/target-kit/specs/first-unit.yaml +11 -0
  127. package/templates/target-kit/system.toml +7 -0
@@ -0,0 +1,142 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://harness.local/schema/system.schema.json",
4
+ "title": "Contract C — system manifest (system.toml)",
5
+ "description": "Implements system-harness-blueprint.md §3 (\"Contract C — system manifest\"). The system's single source of topology: the component DAG, typed artifact handoffs, and e2e scenario ownership. Owned like policy — versioned data, changed by reviewed PR. Consumed by `harness verify --system` (blueprint §4, ring 2): DAG acyclic, no unit scope crosses a component, every consumed artifact hash matches its producer's latest. This schema describes the parsed TOML: `[system]` -> object, `[[component]]` -> array, etc.",
6
+ "type": "object",
7
+ "required": ["system", "component"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "system": {
11
+ "type": "object",
12
+ "required": ["id"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "id": {
16
+ "type": "string",
17
+ "description": "system identifier, e.g. 'acme'"
18
+ }
19
+ }
20
+ },
21
+ "component": {
22
+ "type": "array",
23
+ "minItems": 1,
24
+ "description": "one entry per component — a thing with its own build, verification, deploy surface, and blast radius. The scope unit: one agent session works one component (blueprint §1).",
25
+ "items": {
26
+ "type": "object",
27
+ "required": ["id", "profile"],
28
+ "additionalProperties": false,
29
+ "oneOf": [
30
+ {
31
+ "required": ["root"],
32
+ "description": "monorepo: component lives at a path prefix"
33
+ },
34
+ {
35
+ "required": ["repo"],
36
+ "description": "polyrepo: component lives in its own git repository"
37
+ }
38
+ ],
39
+ "properties": {
40
+ "id": {
41
+ "type": "string",
42
+ "description": "component name, unique within the system; referenced by spec.component, envelope.component_id, and other components' deps"
43
+ },
44
+ "root": {
45
+ "type": "string",
46
+ "description": "path prefix from the system root, e.g. 'apps/backend/' (monorepo). Mutually exclusive with repo."
47
+ },
48
+ "repo": {
49
+ "type": "string",
50
+ "description": "git URL when the component is its own repository, e.g. 'git@github.com:acme/acme-infra'. Mutually exclusive with root — the one line that changes when a component graduates out."
51
+ },
52
+ "profile": {
53
+ "type": "string",
54
+ "description": "base profile name, e.g. 'typescript', 'terraform', 'playwright'"
55
+ },
56
+ "deps": {
57
+ "type": "array",
58
+ "items": { "type": "string" },
59
+ "description": "component ids this one depends on; the DAG, validated acyclic. Dependencies point down only."
60
+ },
61
+ "mode": {
62
+ "enum": ["standard", "propose-only"],
63
+ "default": "standard",
64
+ "description": "propose-only = a human approves before commit (e.g. a component that is mostly UX copy)"
65
+ },
66
+ "role": {
67
+ "enum": ["standard", "integration"],
68
+ "default": "standard",
69
+ "description": "integration = runs only after every dep's verify has passed (the e2e ring, blueprint §4)"
70
+ }
71
+ }
72
+ }
73
+ },
74
+ "artifact": {
75
+ "type": "array",
76
+ "description": "typed handoffs between components — never prose. Referenced by spec.outputs / spec.consumes and proven in envelope.artifacts by hash.",
77
+ "items": {
78
+ "type": "object",
79
+ "required": ["name", "producer", "schema"],
80
+ "additionalProperties": false,
81
+ "properties": {
82
+ "name": {
83
+ "type": "string",
84
+ "description": "artifact identifier, e.g. 'rate-limit-config'"
85
+ },
86
+ "producer": {
87
+ "type": "string",
88
+ "description": "component id that publishes this artifact (exactly one)"
89
+ },
90
+ "schema": {
91
+ "type": "string",
92
+ "description": "path to the JSON Schema the artifact value validates against, e.g. 'artifacts/rate-limit-config.schema.json'"
93
+ }
94
+ }
95
+ }
96
+ },
97
+ "scenario_ownership": {
98
+ "type": "array",
99
+ "description": "e2e failure routing (blueprint §4, ring 3): a failing integration scenario becomes a new scoped unit for the owning component(s), and the failure itself becomes a corpus fixture.",
100
+ "items": {
101
+ "type": "object",
102
+ "required": ["match", "owns"],
103
+ "additionalProperties": false,
104
+ "properties": {
105
+ "match": {
106
+ "type": "string",
107
+ "description": "glob over scenario ids, e.g. 'rate-limit/*'"
108
+ },
109
+ "owns": {
110
+ "type": "array",
111
+ "minItems": 1,
112
+ "items": { "type": "string" },
113
+ "description": "component ids that own failures matching this pattern"
114
+ }
115
+ }
116
+ }
117
+ },
118
+ "door_class": {
119
+ "type": "array",
120
+ "description": "Merge-door routing as reviewed data (solution design §6.3). A merge whose facts match `match` is routed to `class`. Matched against: gate:external, artifact-producer-change, new-dependency, schema-or-api-change, security-touching, component:<id>, mode:<name>. Nothing hardcoded in src — this array plus schema/decision-classes.yaml are the whole policy.",
121
+ "items": {
122
+ "type": "object",
123
+ "required": ["match", "class"],
124
+ "additionalProperties": false,
125
+ "properties": {
126
+ "match": {
127
+ "type": "string",
128
+ "description": "a condition token, e.g. 'gate:external', 'artifact-producer-change', 'component:frontend', 'mode:propose-only'"
129
+ },
130
+ "class": {
131
+ "enum": ["two-way", "one-way", "propose-only"],
132
+ "description": "two-way auto-passes on green verify; one-way and propose-only halt for an operator decision"
133
+ },
134
+ "until": {
135
+ "type": "string",
136
+ "description": "condition that relaxes this class once measured, e.g. 'route-eval>=90' (D8)"
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
@@ -0,0 +1,23 @@
1
+ # Reusable verify workflow — consuming repos import this; `harness init`
2
+ # wires it. CI is just another caller of the same entrypoint (principle 2).
3
+ name: harness-verify
4
+
5
+ on:
6
+ workflow_call: {}
7
+
8
+ jobs:
9
+ verify:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ with: { fetch-depth: 0 } # changed-lines severity needs the base
14
+ - uses: actions/setup-node@v4
15
+ with: { node-version: 24 }
16
+ - name: Run harness verify
17
+ run: npx harness verify
18
+ - name: Upload report envelope
19
+ if: always() # calibration needs failures too
20
+ uses: actions/upload-artifact@v4
21
+ with:
22
+ name: harness-envelope
23
+ path: .harness/reports/
@@ -0,0 +1,78 @@
1
+ # Target intake kit
2
+
3
+ These templates are a reviewed starting point, not target-ready configuration.
4
+ They intentionally contain `REPLACE` markers and fail-closed gates. Copy them
5
+ only after the intake checklist is complete; replace every marker before
6
+ materializing a unit.
7
+
8
+ **Operator prerequisite:** install the published package
9
+ (`npm install --global @mikenguyen69/harness@next`) and follow
10
+ [docs/onboarding.md](../../../../docs/onboarding.md). Do not wire compiled
11
+ portfolio entrypoints for target work.
12
+
13
+ Expected target layout:
14
+
15
+ ```text
16
+ component.toml
17
+ system.toml
18
+ routes.toml
19
+ orchestration.json
20
+ profiles/target/bindings.toml
21
+ specs/first-unit.yaml
22
+ ```
23
+
24
+ Before dispatch, record:
25
+
26
+ - absolute repository path;
27
+ - base branch and exact base commit SHA;
28
+ - language/runtime/package-manager versions;
29
+ - normal install, format, lint, typecheck, test, build, and security commands;
30
+ - component IDs and absolute/relative component roots;
31
+ - the first unit's exact allowed file globs and explicit exclusions;
32
+ - external services the checks contact, including offline alternatives;
33
+ - required secret names, their source, and which subprocess may read them;
34
+ - maximum cost, wall time, parallelism, and retry count;
35
+ - whether local fast-forward is allowed or the run must stop before merge;
36
+ - rollback command and the disposable branch/worktree policy;
37
+ - evidence directory outside generated/build output;
38
+ - a low-risk first change with objective acceptance criteria.
39
+
40
+ Then:
41
+
42
+ 1. Copy and customize all templates.
43
+ 2. Run `rg -n "REPLACE" component.toml system.toml routes.toml orchestration.json profiles specs`; zero matches are required.
44
+ 3. From the target root, scaffold hooks (no separate hook-install step):
45
+
46
+ ```sh
47
+ harness init
48
+ ```
49
+
50
+ Hook installation is one step of `harness init`. Owner: system-harness
51
+ `init` composing the agent-harness hook-install path; generated commands call
52
+ `harness hook pre-tool-use`.
53
+ 4. Read-only preflight, then materialize once:
54
+
55
+ ```sh
56
+ harness spec check --specs ./specs --system ./system.toml
57
+ harness spec materialize --specs ./specs --system ./system.toml --ledger ./.harness/ledger --json
58
+ harness doctor --repo . --routes ./routes.toml --spool ./.harness/spool --json
59
+ ```
60
+
61
+ 5. Review doctor’s resolved runner/model, commands, budgets, base branch, and dirty-tree decision.
62
+ 6. Obtain separate authorization for the target dispatch and its merge policy.
63
+ Installing `@mikenguyen69/harness` authorizes neither a dry run nor a real target
64
+ run. `doctor` / `spec check` do not dispatch agents.
65
+
66
+ Only after that authorization:
67
+
68
+ ```sh
69
+ harness run --repo . --config ./orchestration.json --routes ./routes.toml --spool ./.harness/spool --report ./run-report.html
70
+ ```
71
+
72
+ Evidence lands in `.harness/ledger/`, the `--spool` directory, the `--report`
73
+ path, and (by default) `.harness/runs/<run-id>/`. On a one-way door halt,
74
+ approve then `harness resume --unit <id> …` — see
75
+ [docs/onboarding.md](../../../../docs/onboarding.md).
76
+
77
+ The operator keeps the target base SHA and evidence directory. The agent must
78
+ not infer them or broaden scope from repository contents.
@@ -0,0 +1,20 @@
1
+ # REPLACE every command/decline rationale with the target's reviewed policy.
2
+ [harness]
3
+ policy_version = "0.0.1"
4
+ profile = "target"
5
+ mode = "standard"
6
+
7
+ [gates]
8
+ # Fail closed until the target's real commands replace these sentinels.
9
+ types = { run = "node -e \"process.exit(1)\"", severity = "blocking", cost = "cheap" }
10
+ test = { run = "node -e \"process.exit(1)\"", severity = "blocking", cost = "cheap" }
11
+
12
+ spec = { declined = "REPLACE: bind the target spec check or justify declining it" }
13
+ fmt = { declined = "REPLACE: bind the target formatter" }
14
+ lint = { declined = "REPLACE: bind the target linter" }
15
+ arch = { declined = "REPLACE: bind architecture checks or document why absent" }
16
+ contract = { declined = "REPLACE: bind API/schema compatibility checks if applicable" }
17
+ size = { declined = "REPLACE: define a change-size policy" }
18
+ "gen:fresh" = { declined = "REPLACE: bind generated-artifact freshness if applicable" }
19
+ "sec:deps" = { declined = "REPLACE: bind an offline dependency advisory check" }
20
+ "sec:secrets" = { declined = "REPLACE: bind secret scanning" }
@@ -0,0 +1,9 @@
1
+ {
2
+ "forge": "local",
3
+ "baseBranch": "REPLACE-base-branch",
4
+ "maxParallel": 1,
5
+ "retryBudget": 0,
6
+ "maxRunCost": 2,
7
+ "maxRunDuration": 900000,
8
+ "runners": { "enabled": ["claude"] }
9
+ }
@@ -0,0 +1,6 @@
1
+ [harness]
2
+ profile_version = "0.0.1"
3
+
4
+ # The component contract owns the initial bindings. Move stable, shared target
5
+ # bindings here only after the first dry run proves them.
6
+ [gates]
@@ -0,0 +1,5 @@
1
+ [[route]]
2
+ profile = "target"
3
+ runner = "claude"
4
+ model = "REPLACE-approved-model"
5
+ mode = "standard"
@@ -0,0 +1,11 @@
1
+ id: first-unit
2
+ component: app
3
+ intent: >
4
+ REPLACE with one low-risk, observable change that can be reverted locally.
5
+ acceptance_criteria:
6
+ - statement: REPLACE with an objective behavior the normal test suite proves
7
+ verifier: test
8
+ scope:
9
+ - REPLACE/with/exact/allowed/glob/**
10
+ door: two-way
11
+ merge_facts: {}
@@ -0,0 +1,7 @@
1
+ [system]
2
+ id = "REPLACE-target-system-id"
3
+
4
+ [[component]]
5
+ id = "app"
6
+ root = "."
7
+ profile = "target"