codex-genesis-harness 0.1.8 → 0.1.9
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/.codebase/CURRENT_STATE.md +7 -33
- package/.codebase/KNOWN_PROBLEMS.md +20 -1
- package/.codebase/MODULE_INDEX.md +15 -2
- package/.codebase/PIPELINE_FLOW.md +10 -2
- package/.codebase/RECOVERY_POINTS.md +63 -0
- package/.codebase/TEST_MATRIX.md +5 -1
- package/.codebase/memories/lessons_learned.md +42 -0
- package/.codebase/state.json +130 -12
- package/.codex/skills/genesis-harness/SKILL.md +10 -1
- package/.codex/skills/genesis-harness/agents/openai.yaml +1 -2
- package/.codex/skills/genesis-harness/references/state-machine.md +4 -1
- package/.codex/skills/genesis-harness/references/workflows.md +7 -1
- package/.codex/skills/genesis-harness/scripts/init-planning.sh +245 -13
- package/.codex/skills/genesis-pipeline-orchestration/SKILL.md +15 -3
- package/.codex-plugin/plugin.json +4 -2
- package/CHANGELOG.md +21 -0
- package/README.EN.md +44 -2
- package/README.VI.md +44 -2
- package/README.md +80 -2
- package/VERSION +1 -2
- package/bin/genesis-harness.js +2121 -21
- package/contracts/features/project-registry-schema.json +37 -0
- package/contracts/observability/agent-run-schema.json +6 -1
- package/features/REGISTRY.md +9 -7
- package/fixtures/pipeline/end-to-end-project-lifecycle-fixture.md +39 -0
- package/fixtures/pipeline/feature-completion-fixture.md +26 -0
- package/fixtures/pipeline/run-to-feature-execution-fixture.md +20 -0
- package/package.json +7 -2
- package/scripts/check-repository-hygiene.js +48 -0
- package/scripts/run-evals.sh +36 -3
- package/scripts/schema/001-init.sql +129 -0
- package/scripts/schema/002-story-verify.sql +9 -0
- package/scripts/schema/003-tool-registry.sql +15 -0
- package/scripts/schema/004-intervention.sql +15 -0
- package/scripts/transition_state.sh +32 -8
- package/scripts/validation_gates.sh +2 -80
- package/scripts/verify.sh +3 -1
- package/tests/fixtures/fixture-index.md +5 -0
- package/tests/integration/cli-smoke.test.js +403 -0
- package/tests/unit/repository_hygiene.test.js +17 -0
- package/tests/unit/state_metadata.test.js +76 -0
- package/tests/unit/verify_gate.test.js +25 -0
- package/tests/unit/workflow_contracts.test.js +90 -0
- package/fixtures/tts/tts-fixture-template.md +0 -14
- package/fixtures/videos/video-fixture-template.md +0 -14
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"description": "Contract for .planning/FEATURE_REGISTRY.json generated by the lifecycle pipeline.",
|
|
4
|
+
"required_root_fields": [
|
|
5
|
+
"version",
|
|
6
|
+
"updated_at",
|
|
7
|
+
"project_status",
|
|
8
|
+
"project_verification",
|
|
9
|
+
"features"
|
|
10
|
+
],
|
|
11
|
+
"required_feature_fields": [
|
|
12
|
+
"id",
|
|
13
|
+
"status",
|
|
14
|
+
"title",
|
|
15
|
+
"path",
|
|
16
|
+
"verify_cmd",
|
|
17
|
+
"evidence",
|
|
18
|
+
"started_at",
|
|
19
|
+
"verified_at",
|
|
20
|
+
"attempts",
|
|
21
|
+
"last_error"
|
|
22
|
+
],
|
|
23
|
+
"valid_statuses": [
|
|
24
|
+
"planned",
|
|
25
|
+
"in-progress",
|
|
26
|
+
"done",
|
|
27
|
+
"verified",
|
|
28
|
+
"deprecated"
|
|
29
|
+
],
|
|
30
|
+
"valid_project_statuses": [
|
|
31
|
+
"implementation",
|
|
32
|
+
"verification",
|
|
33
|
+
"release-ready",
|
|
34
|
+
"completed"
|
|
35
|
+
],
|
|
36
|
+
"completion_rule": "A feature may become verified only after verify_cmd exits 0 and explicit evidence is persisted. A project may become completed only after all features are verified and project verification has passed."
|
|
37
|
+
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"session_id": "string — unique identifier for the agent session (e.g. UUID or date-prefixed slug)",
|
|
15
15
|
"timestamp": "ISO 8601 string",
|
|
16
16
|
"skill": "string — name of the genesis skill invoked",
|
|
17
|
-
"phase": "string — one of: init, plan, execute, verify, handoff",
|
|
17
|
+
"phase": "string — one of: init, plan, execute, verify, handoff, release",
|
|
18
18
|
"outcome": "string — one of: success, failure, partial, skipped",
|
|
19
19
|
"evidence": "string — CLI output snippet or file path proving the outcome"
|
|
20
20
|
},
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
"recovery_needed": "boolean — whether a recovery point was consulted"
|
|
26
26
|
},
|
|
27
27
|
"changelog": [
|
|
28
|
+
{
|
|
29
|
+
"version": "1.1.0",
|
|
30
|
+
"date": "2026-06-12",
|
|
31
|
+
"change": "Added release phase for project completion records"
|
|
32
|
+
},
|
|
28
33
|
{
|
|
29
34
|
"version": "1.0.0",
|
|
30
35
|
"date": "2026-06-03",
|
package/features/REGISTRY.md
CHANGED
|
@@ -35,10 +35,12 @@
|
|
|
35
35
|
| F013 | verified | Feature Registry as harness primitive (L08) | `node tests/unit/feature_registry.test.js` | genesis-harness-engineering |
|
|
36
36
|
| F014 | verified | npm pack / tarball smoke test | `bash scripts/run-evals.sh` | genesis-release |
|
|
37
37
|
| F015 | verified | spec-impact-engine propagation chain | `bash scripts/verify.sh .codex/skills/spec-impact-engine` | spec-impact-engine |
|
|
38
|
-
| F016 |
|
|
38
|
+
| F016 | verified | Cold-start test automation (L03) | `node scripts/cold-start-check.js` | genesis-harness |
|
|
39
39
|
| F017 | planned | Per-session Time-to-First-Verification KPI (L06) | `node bin/genesis-harness.js status --ttfv` | genesis-harness |
|
|
40
|
-
| F018 |
|
|
41
|
-
| F019 |
|
|
40
|
+
| F018 | verified | Scope ledger per task (L07) | `bash scripts/check-scope.sh` | genesis-harness |
|
|
41
|
+
| F019 | planned | Demo feature templates (mockup + contract + E2E) | `npx playwright test playwright/e2e/auth/login-screen.spec.js` | genesis-harness-engineering |
|
|
42
|
+
| F020 | verified | Stateful feature lifecycle (`next` → evidence-gated `complete-feature`) | `node tests/integration/cli-smoke.test.js` | genesis-pipeline-orchestration |
|
|
43
|
+
| F021 | verified | End-to-end multi-feature lifecycle with project verification, release-ready handoff, completion, event history, and audit | `node tests/integration/cli-smoke.test.js` | genesis-pipeline-orchestration |
|
|
42
44
|
|
|
43
45
|
---
|
|
44
46
|
|
|
@@ -47,10 +49,10 @@
|
|
|
47
49
|
> Update this section after each CI run.
|
|
48
50
|
|
|
49
51
|
```
|
|
50
|
-
Date: 2026-06-
|
|
51
|
-
scripts/verify.sh
|
|
52
|
-
scripts/run-evals.sh
|
|
53
|
-
|
|
52
|
+
Date: 2026-06-12T09:50:17Z
|
|
53
|
+
scripts/verify.sh → verify passed
|
|
54
|
+
scripts/run-evals.sh → evals passed
|
|
55
|
+
genesis-harness verify-gate → passed
|
|
54
56
|
```
|
|
55
57
|
|
|
56
58
|
---
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# End-to-End Project Lifecycle Fixture
|
|
2
|
+
|
|
3
|
+
## Initial State
|
|
4
|
+
|
|
5
|
+
- One feature is `in-progress`.
|
|
6
|
+
- A second feature is added as `planned`.
|
|
7
|
+
- Project state is `IMPLEMENTATION`.
|
|
8
|
+
|
|
9
|
+
## Lifecycle
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
complete active feature
|
|
13
|
+
-> mark active feature verified
|
|
14
|
+
-> promote next planned feature
|
|
15
|
+
-> keep project in IMPLEMENTATION
|
|
16
|
+
|
|
17
|
+
complete final feature
|
|
18
|
+
-> mark feature verified
|
|
19
|
+
-> clear active feature
|
|
20
|
+
-> move project to VERIFICATION
|
|
21
|
+
|
|
22
|
+
verify project
|
|
23
|
+
-> run every feature proof command
|
|
24
|
+
-> run project proof command
|
|
25
|
+
-> create project verification and handoff artifacts
|
|
26
|
+
-> move project to RELEASE_READY
|
|
27
|
+
|
|
28
|
+
complete project
|
|
29
|
+
-> require RELEASE_READY
|
|
30
|
+
-> append final lifecycle event
|
|
31
|
+
-> move project to COMPLETED
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Invariants
|
|
35
|
+
|
|
36
|
+
- Repeating a successful completion command is idempotent.
|
|
37
|
+
- A failed proof command blocks the transition and increments failure metrics.
|
|
38
|
+
- `pipeline-audit` fails on registry/state/artifact drift.
|
|
39
|
+
- Every accepted transition is appended to `.runs/<session-id>/EVENTS.jsonl`.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Feature Completion Fixture
|
|
2
|
+
|
|
3
|
+
## Given
|
|
4
|
+
|
|
5
|
+
- `.codebase/state.json` records one `active_feature`.
|
|
6
|
+
- `.planning/FEATURE_REGISTRY.json` records that feature as `in-progress`.
|
|
7
|
+
- The caller supplies a verification command and an evidence summary.
|
|
8
|
+
|
|
9
|
+
## When
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
genesis-harness complete-feature \
|
|
13
|
+
--verify-cmd "npm test" \
|
|
14
|
+
--evidence "All feature tests passed"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Expected
|
|
18
|
+
|
|
19
|
+
- The verification command exits `0`.
|
|
20
|
+
- The registry feature status becomes `verified`.
|
|
21
|
+
- `.planning/FEATURE_INDEX.md` marks the feature `[x]`.
|
|
22
|
+
- State becomes `COMPLETED` and records feature lead-time metrics.
|
|
23
|
+
- An observability run record is written.
|
|
24
|
+
- The active `.runs/<session-id>` checkpoint is refreshed.
|
|
25
|
+
|
|
26
|
+
If verification exits non-zero, completion is blocked and `failed_gate_count` increments.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Run To Feature Execution Fixture
|
|
2
|
+
|
|
3
|
+
## Input
|
|
4
|
+
|
|
5
|
+
- Command: `genesis-harness run --idea "<brief>" --yes ...`
|
|
6
|
+
- Discovery answers: product approach, primary user, v1 outcome, QA owner, stack, deployment, and test strategy
|
|
7
|
+
|
|
8
|
+
## Expected Output
|
|
9
|
+
|
|
10
|
+
- `.planning/features/<NNN>-<slug>/` exists
|
|
11
|
+
- `SPEC.md`, `PLAN.md`, `TEST_CONTRACT.md`, `TASKS.md`, `VERIFICATION.md`, and `DIAGRAM.mmd` are seeded for the first active slice
|
|
12
|
+
- `contracts/ui/<feature>/screen-contract.json` exists when the first slice is UI-capable
|
|
13
|
+
- `playwright/fixtures/<feature>-ui-fixture.md` exists when the first slice is UI-capable
|
|
14
|
+
- `contracts/api/<feature>/request.json` and `response.json` exist when the first slice is API-capable
|
|
15
|
+
- `fixtures/api/<feature>-api-fixture.md` exists when the first slice is API-capable
|
|
16
|
+
- `.planning/FEATURE_INDEX.md` registers the active slice
|
|
17
|
+
- `.planning/STATE.md` advances to `02 First Feature Execution`
|
|
18
|
+
- `.codebase/state.json` advances to `IMPLEMENTATION`
|
|
19
|
+
- `.runs/<session-id>/STATE.json` mirrors the same `IMPLEMENTATION` state and `active_feature`
|
|
20
|
+
- `genesis-harness resume` reports the active feature and the next implementation task
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-genesis-harness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Hệ thống quản trị (Harness) dành cho AI Agent (Codex) với cơ chế FSM State Persistence, Validation Gates và Test-First Workflow. Đảm bảo agent không bị trôi context.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -29,8 +29,13 @@
|
|
|
29
29
|
"playwright",
|
|
30
30
|
"observability",
|
|
31
31
|
"bin",
|
|
32
|
-
"scripts",
|
|
32
|
+
"scripts/*.js",
|
|
33
|
+
"scripts/*.sh",
|
|
34
|
+
"scripts/README.md",
|
|
35
|
+
"scripts/schema",
|
|
33
36
|
"README.md",
|
|
37
|
+
"README.EN.md",
|
|
38
|
+
"README.VI.md",
|
|
34
39
|
"LICENSE",
|
|
35
40
|
"VERSION",
|
|
36
41
|
"CHANGELOG.md"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { spawnSync } = require("child_process");
|
|
6
|
+
|
|
7
|
+
const repoRoot = path.resolve(__dirname, "..");
|
|
8
|
+
const workTreeCheck = spawnSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
9
|
+
cwd: repoRoot,
|
|
10
|
+
encoding: "utf8"
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
if (workTreeCheck.status !== 0) {
|
|
14
|
+
console.log("repository hygiene skipped: package is not inside a Git worktree");
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const result = spawnSync("git", ["ls-files", "-z"], {
|
|
19
|
+
cwd: repoRoot,
|
|
20
|
+
encoding: "utf8"
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (result.status !== 0) {
|
|
24
|
+
console.error(result.stderr || "repository hygiene failed: git ls-files failed");
|
|
25
|
+
process.exit(result.status || 1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const tracked = result.stdout.split("\0").filter(Boolean);
|
|
29
|
+
const forbidden = tracked.filter(file =>
|
|
30
|
+
file === "node_modules"
|
|
31
|
+
|| file.startsWith("node_modules/")
|
|
32
|
+
|| file === "dist"
|
|
33
|
+
|| file.startsWith("dist/")
|
|
34
|
+
|| file.endsWith(".tgz")
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (forbidden.length > 0) {
|
|
38
|
+
console.error("repository hygiene failed: generated or dependency artifacts are tracked:");
|
|
39
|
+
for (const file of forbidden.slice(0, 20)) {
|
|
40
|
+
console.error(`- ${file}`);
|
|
41
|
+
}
|
|
42
|
+
if (forbidden.length > 20) {
|
|
43
|
+
console.error(`- ... and ${forbidden.length - 20} more`);
|
|
44
|
+
}
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log("repository hygiene passed");
|
package/scripts/run-evals.sh
CHANGED
|
@@ -58,6 +58,7 @@ assert_contains "$repo_root/.codex-plugin/plugin.json" '"skills"'
|
|
|
58
58
|
assert_contains "$repo_root/.codex-plugin/plugin.json" '"genesis-skill-set"'
|
|
59
59
|
assert_contains "$repo_root/.codex-plugin/plugin.json" '$genesis-pipeline-orchestration'
|
|
60
60
|
assert_contains "$repo_root/.codex-plugin/plugin.json" '$genesis-api-contract'
|
|
61
|
+
assert_contains "$repo_root/.codex-plugin/plugin.json" 'implicit init'
|
|
61
62
|
assert_not_contains "$repo_root/.codex-plugin/plugin.json" '$pipeline-orchestration-skill'
|
|
62
63
|
assert_not_contains "$repo_root/.codex-plugin/plugin.json" '$api-contract-skill'
|
|
63
64
|
assert_contains "$harness_dir/SKILL.md" '/genesis-init'
|
|
@@ -65,6 +66,13 @@ assert_contains "$repo_root/.codex/SKILLS_INDEX.md" '/genesis-init'
|
|
|
65
66
|
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness docs-gate'
|
|
66
67
|
assert_contains "$repo_root/bin/genesis-harness.js" 'check-docs-sync.sh'
|
|
67
68
|
assert_contains "$repo_root/bin/genesis-harness.js" 'npx genesis-harness docs-gate'
|
|
69
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness resume'
|
|
70
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness next'
|
|
71
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness add-feature'
|
|
72
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness complete-feature'
|
|
73
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness verify-project'
|
|
74
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness complete-project'
|
|
75
|
+
assert_contains "$repo_root/bin/genesis-harness.js" 'genesis-harness pipeline-audit'
|
|
68
76
|
assert_contains "$harness_dir/scripts/check-docs-sync.sh" '.codebase/'
|
|
69
77
|
assert_contains "$harness_dir/scripts/check-docs-sync.sh" 'README(\.[A-Z]{2})?\.md'
|
|
70
78
|
assert_contains "$repo_root/.codebase/VISUAL_GRAPH.md" 'genesis-harness'
|
|
@@ -73,12 +81,23 @@ assert_contains "$repo_root/.codebase/PIPELINE_FLOW.md" 'contracts --> impl'
|
|
|
73
81
|
assert_not_contains "$repo_root/.codebase/VISUAL_GRAPH.md" 'Đăng nhập'
|
|
74
82
|
assert_not_contains "$repo_root/.codebase/VISUAL_GRAPH.md" 'src/auth.js'
|
|
75
83
|
assert_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'Harness Drift Gate Hardening'
|
|
76
|
-
assert_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" '2026-06-03'
|
|
77
84
|
assert_not_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" '_[Name and reference]_'
|
|
78
85
|
assert_not_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'Feature A'
|
|
79
86
|
assert_not_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'YYYY-MM-DD'
|
|
80
|
-
|
|
81
|
-
|
|
87
|
+
node - "$repo_root/.codebase/state.json" <<'NODE'
|
|
88
|
+
const fs = require("fs");
|
|
89
|
+
const state = JSON.parse(fs.readFileSync(process.argv[2], "utf8"));
|
|
90
|
+
if (state.current_state === "COMPLETED" && !state.completed_at) {
|
|
91
|
+
throw new Error("completed state must include completed_at");
|
|
92
|
+
}
|
|
93
|
+
if (state.current_state !== "COMPLETED" && Object.prototype.hasOwnProperty.call(state, "completed_at")) {
|
|
94
|
+
throw new Error("active state must not retain completed_at");
|
|
95
|
+
}
|
|
96
|
+
NODE
|
|
97
|
+
assert_contains "$repo_root/.codebase/CURRENT_STATE.md" '**Time**: '
|
|
98
|
+
assert_contains "$repo_root/.codebase/MODULE_INDEX.md" '.runs/'
|
|
99
|
+
assert_not_contains "$repo_root/.codebase/CURRENT_STATE.md" '110/110 perfect score'
|
|
100
|
+
assert_not_contains "$repo_root/.codebase/state.json" '"to": "EXECUTE"'
|
|
82
101
|
assert_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'npm run eval'
|
|
83
102
|
assert_not_contains "$repo_root/.codebase/IMPLEMENTATION_HANDOFF.md" 'rtk '
|
|
84
103
|
assert_not_contains "$repo_root/.codebase/state.json" 'rtk '
|
|
@@ -106,6 +125,16 @@ assert_contains "$repo_root/package.json" '"playwright"'
|
|
|
106
125
|
assert_contains "$repo_root/package.json" '"observability"'
|
|
107
126
|
assert_contains "$repo_root/README.md" '.codex/skills/'
|
|
108
127
|
|
|
128
|
+
plugin_version=$(node -p "require('$repo_root/.codex-plugin/plugin.json').version")
|
|
129
|
+
package_version=$(node -p "require('$repo_root/package.json').version")
|
|
130
|
+
[ "$plugin_version" = "$package_version" ] || fail "plugin version ($plugin_version) must match package version ($package_version)"
|
|
131
|
+
|
|
132
|
+
[ "$(grep -c '^- `bin/genesis-harness.js`:' "$repo_root/.codebase/MODULE_INDEX.md")" -eq 1 ] \
|
|
133
|
+
|| fail ".codebase/MODULE_INDEX.md must contain a single canonical bin/genesis-harness.js entry"
|
|
134
|
+
|
|
135
|
+
[ "$(grep -c '^- `tests/integration/cli-smoke.test.js`:' "$repo_root/.codebase/TEST_MATRIX.md")" -eq 1 ] \
|
|
136
|
+
|| fail ".codebase/TEST_MATRIX.md must describe cli-smoke in one canonical entry"
|
|
137
|
+
|
|
109
138
|
for skill_name in "${skill_names[@]}"; do
|
|
110
139
|
assert_contains "$repo_root/bin/genesis-harness.js" "$skill_name"
|
|
111
140
|
assert_contains "$repo_root/scripts/install.sh" "$skill_name"
|
|
@@ -193,6 +222,8 @@ pack_tmp="$(mktemp -d)"
|
|
|
193
222
|
npm pack --pack-destination "$pack_tmp" >/dev/null
|
|
194
223
|
tarball_path=$(ls "$pack_tmp"/*.tgz | head -n 1)
|
|
195
224
|
[ -f "$tarball_path" ] || fail "npm pack failed to produce tarball"
|
|
225
|
+
tar tzf "$tarball_path" | grep -q '^package/scripts/bin/' \
|
|
226
|
+
&& fail "packaged tarball must not include generated scripts/bin binaries"
|
|
196
227
|
(
|
|
197
228
|
cd "$pack_tmp"
|
|
198
229
|
tar xzf "$tarball_path"
|
|
@@ -208,7 +239,9 @@ assert_contains "$repo_root/features/REGISTRY.md" "| id |"
|
|
|
208
239
|
assert_contains "$repo_root/features/REGISTRY.md" "| status |"
|
|
209
240
|
assert_contains "$repo_root/features/REGISTRY.md" "| verify_cmd |"
|
|
210
241
|
assert_file "$repo_root/contracts/features/registry-schema.json"
|
|
242
|
+
assert_file "$repo_root/contracts/features/project-registry-schema.json"
|
|
211
243
|
assert_contains "$repo_root/contracts/features/registry-schema.json" '"required_columns"'
|
|
244
|
+
assert_contains "$repo_root/contracts/features/project-registry-schema.json" '"completion_rule"'
|
|
212
245
|
assert_contains "$repo_root/.codebase/MODULE_INDEX.md" "features/REGISTRY.md"
|
|
213
246
|
|
|
214
247
|
# L11 — Observability Live Data
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
-- Harness v0 schema — migration 001
|
|
2
|
+
-- Durable layer for operational harness data.
|
|
3
|
+
-- Policy docs (HARNESS.md, FEATURE_INTAKE.md, ARCHITECTURE.md) stay as
|
|
4
|
+
-- human-readable references. This database stores the operational records
|
|
5
|
+
-- that agents produce and query during work.
|
|
6
|
+
|
|
7
|
+
PRAGMA journal_mode = WAL;
|
|
8
|
+
PRAGMA foreign_keys = ON;
|
|
9
|
+
|
|
10
|
+
----------------------------------------------------------------------
|
|
11
|
+
-- Schema version
|
|
12
|
+
----------------------------------------------------------------------
|
|
13
|
+
CREATE TABLE IF NOT EXISTS schema_version (
|
|
14
|
+
version INTEGER PRIMARY KEY,
|
|
15
|
+
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
INSERT INTO schema_version (version) VALUES (1);
|
|
19
|
+
|
|
20
|
+
----------------------------------------------------------------------
|
|
21
|
+
-- Intake: classifying incoming work
|
|
22
|
+
----------------------------------------------------------------------
|
|
23
|
+
CREATE TABLE intake (
|
|
24
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
25
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
26
|
+
input_type TEXT NOT NULL
|
|
27
|
+
CHECK(input_type IN (
|
|
28
|
+
'new_spec','spec_slice','change_request',
|
|
29
|
+
'new_initiative','maintenance','harness_improvement'
|
|
30
|
+
)),
|
|
31
|
+
summary TEXT NOT NULL,
|
|
32
|
+
risk_lane TEXT NOT NULL
|
|
33
|
+
CHECK(risk_lane IN ('tiny','normal','high_risk')),
|
|
34
|
+
risk_flags TEXT, -- JSON array, e.g. ["auth","data_model"]
|
|
35
|
+
affected_docs TEXT, -- JSON array of doc paths
|
|
36
|
+
story_id TEXT, -- links to story.id when one is created
|
|
37
|
+
notes TEXT
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
----------------------------------------------------------------------
|
|
41
|
+
-- Story: work packets and their validation status
|
|
42
|
+
-- Replaces hand-edited TEST_MATRIX.md rows.
|
|
43
|
+
----------------------------------------------------------------------
|
|
44
|
+
CREATE TABLE story (
|
|
45
|
+
id TEXT PRIMARY KEY, -- e.g. US-001
|
|
46
|
+
title TEXT NOT NULL,
|
|
47
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
48
|
+
risk_lane TEXT NOT NULL
|
|
49
|
+
CHECK(risk_lane IN ('tiny','normal','high_risk')),
|
|
50
|
+
contract_doc TEXT, -- path to product doc
|
|
51
|
+
status TEXT NOT NULL DEFAULT 'planned'
|
|
52
|
+
CHECK(status IN (
|
|
53
|
+
'planned','in_progress','implemented','changed','retired'
|
|
54
|
+
)),
|
|
55
|
+
unit_proof INTEGER NOT NULL DEFAULT 0,
|
|
56
|
+
integration_proof INTEGER NOT NULL DEFAULT 0,
|
|
57
|
+
e2e_proof INTEGER NOT NULL DEFAULT 0,
|
|
58
|
+
platform_proof INTEGER NOT NULL DEFAULT 0,
|
|
59
|
+
evidence TEXT,
|
|
60
|
+
notes TEXT
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
----------------------------------------------------------------------
|
|
64
|
+
-- Decision: durable records with optional verification
|
|
65
|
+
----------------------------------------------------------------------
|
|
66
|
+
CREATE TABLE decision (
|
|
67
|
+
id TEXT PRIMARY KEY, -- e.g. 0001
|
|
68
|
+
title TEXT NOT NULL,
|
|
69
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
70
|
+
status TEXT NOT NULL DEFAULT 'proposed'
|
|
71
|
+
CHECK(status IN (
|
|
72
|
+
'proposed','accepted','superseded','rejected'
|
|
73
|
+
)),
|
|
74
|
+
doc_path TEXT, -- path to the markdown ADR
|
|
75
|
+
verify_command TEXT, -- optional check command
|
|
76
|
+
last_verified_at TEXT,
|
|
77
|
+
last_verified_result TEXT
|
|
78
|
+
CHECK(last_verified_result IN ('pass','fail') OR
|
|
79
|
+
last_verified_result IS NULL),
|
|
80
|
+
predicted_impact TEXT,
|
|
81
|
+
actual_outcome TEXT,
|
|
82
|
+
notes TEXT
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
----------------------------------------------------------------------
|
|
86
|
+
-- Backlog: harness improvement proposals with evidence loop
|
|
87
|
+
----------------------------------------------------------------------
|
|
88
|
+
CREATE TABLE backlog (
|
|
89
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
90
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
91
|
+
title TEXT NOT NULL,
|
|
92
|
+
discovered_while TEXT,
|
|
93
|
+
current_pain TEXT,
|
|
94
|
+
suggested_improvement TEXT,
|
|
95
|
+
risk TEXT CHECK(risk IN ('tiny','normal','high_risk')),
|
|
96
|
+
status TEXT NOT NULL DEFAULT 'proposed'
|
|
97
|
+
CHECK(status IN (
|
|
98
|
+
'proposed','accepted','implemented','rejected'
|
|
99
|
+
)),
|
|
100
|
+
predicted_impact TEXT,
|
|
101
|
+
actual_outcome TEXT,
|
|
102
|
+
implemented_at TEXT,
|
|
103
|
+
notes TEXT
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
----------------------------------------------------------------------
|
|
107
|
+
-- Trace: agent task execution records (observability foundation)
|
|
108
|
+
----------------------------------------------------------------------
|
|
109
|
+
CREATE TABLE trace (
|
|
110
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
111
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
112
|
+
task_summary TEXT NOT NULL,
|
|
113
|
+
intake_id INTEGER REFERENCES intake(id),
|
|
114
|
+
story_id TEXT REFERENCES story(id),
|
|
115
|
+
agent TEXT,
|
|
116
|
+
actions_taken TEXT, -- JSON array
|
|
117
|
+
files_read TEXT, -- JSON array
|
|
118
|
+
files_changed TEXT, -- JSON array
|
|
119
|
+
decisions_made TEXT, -- JSON array
|
|
120
|
+
errors TEXT, -- JSON array
|
|
121
|
+
outcome TEXT
|
|
122
|
+
CHECK(outcome IN (
|
|
123
|
+
'completed','blocked','partial','failed'
|
|
124
|
+
)),
|
|
125
|
+
duration_seconds INTEGER,
|
|
126
|
+
token_estimate INTEGER,
|
|
127
|
+
harness_friction TEXT,
|
|
128
|
+
notes TEXT
|
|
129
|
+
);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- Harness v0 schema - migration 002
|
|
2
|
+
-- Story-level mechanical verification.
|
|
3
|
+
|
|
4
|
+
ALTER TABLE story ADD COLUMN verify_command TEXT;
|
|
5
|
+
ALTER TABLE story ADD COLUMN last_verified_at TEXT;
|
|
6
|
+
ALTER TABLE story ADD COLUMN last_verified_result TEXT
|
|
7
|
+
CHECK(last_verified_result IN ('pass','fail') OR last_verified_result IS NULL);
|
|
8
|
+
|
|
9
|
+
INSERT INTO schema_version (version) VALUES (2);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Harness v0 schema - migration 003
|
|
2
|
+
-- Machine-readable registry for user-provided project tools.
|
|
3
|
+
|
|
4
|
+
CREATE TABLE tool (
|
|
5
|
+
name TEXT PRIMARY KEY,
|
|
6
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
7
|
+
provider TEXT NOT NULL DEFAULT 'custom',
|
|
8
|
+
command TEXT NOT NULL,
|
|
9
|
+
description TEXT NOT NULL,
|
|
10
|
+
args TEXT,
|
|
11
|
+
responsibility TEXT NOT NULL,
|
|
12
|
+
since TEXT NOT NULL DEFAULT 'registered'
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
INSERT INTO schema_version (version) VALUES (3);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Harness v0 schema - migration 004
|
|
2
|
+
-- Review, human, CI, or agent interventions separated from normal traces.
|
|
3
|
+
|
|
4
|
+
CREATE TABLE intervention (
|
|
5
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
7
|
+
trace_id INTEGER REFERENCES trace(id),
|
|
8
|
+
story_id TEXT,
|
|
9
|
+
type TEXT NOT NULL CHECK(type IN ('correction','override','escalation','approval')),
|
|
10
|
+
description TEXT NOT NULL,
|
|
11
|
+
source TEXT NOT NULL CHECK(source IN ('human','reviewer','ci','agent')),
|
|
12
|
+
impact TEXT
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
INSERT INTO schema_version (version) VALUES (4);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
3
5
|
if [ -z "$1" ]; then
|
|
4
6
|
echo "Usage: bash scripts/transition_state.sh <NEW_STATE> [Reason]"
|
|
5
7
|
exit 1
|
|
@@ -30,14 +32,16 @@ const fs = require('fs');
|
|
|
30
32
|
const file = '$STATE_FILE';
|
|
31
33
|
const newState = '$NEW_STATE';
|
|
32
34
|
const reason = '$REASON';
|
|
35
|
+
const now = new Date().toISOString();
|
|
33
36
|
|
|
34
37
|
const allowed = {
|
|
35
38
|
'INIT': ['REQUIREMENTS_GATHERING', 'PLANNING'],
|
|
36
39
|
'REQUIREMENTS_GATHERING': ['PLANNING'],
|
|
37
40
|
'PLANNING': ['IMPLEMENTATION'],
|
|
38
41
|
'IMPLEMENTATION': ['VERIFICATION', 'PLANNING'],
|
|
39
|
-
'VERIFICATION': ['
|
|
40
|
-
'
|
|
42
|
+
'VERIFICATION': ['RELEASE_READY', 'IMPLEMENTATION'],
|
|
43
|
+
'RELEASE_READY': ['COMPLETED', 'IMPLEMENTATION'],
|
|
44
|
+
'COMPLETED': ['INIT', 'REQUIREMENTS_GATHERING', 'IMPLEMENTATION']
|
|
41
45
|
};
|
|
42
46
|
|
|
43
47
|
let data = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
@@ -45,8 +49,18 @@ const current = data.current_state || 'INIT';
|
|
|
45
49
|
|
|
46
50
|
if (allowed[current] && allowed[current].includes(newState)) {
|
|
47
51
|
data.history = data.history || [];
|
|
48
|
-
data.history.push({ from: current, to: newState, reason: reason, timestamp:
|
|
52
|
+
data.history.push({ from: current, to: newState, reason: reason, timestamp: now, session_id: data.session_id || 'manual-transition' });
|
|
49
53
|
data.current_state = newState;
|
|
54
|
+
data.session_started_at = data.session_started_at || now;
|
|
55
|
+
data.last_updated_at = now;
|
|
56
|
+
if (newState === 'COMPLETED') {
|
|
57
|
+
data.completed_at = now;
|
|
58
|
+
data.active_work = '';
|
|
59
|
+
data.pending_tasks = [];
|
|
60
|
+
data.latest_recovery_point = reason;
|
|
61
|
+
} else {
|
|
62
|
+
delete data.completed_at;
|
|
63
|
+
}
|
|
50
64
|
fs.writeFileSync(file, JSON.stringify(data, null, 2));
|
|
51
65
|
console.log('Transition successful: ' + current + ' -> ' + newState);
|
|
52
66
|
} else {
|
|
@@ -56,11 +70,21 @@ if (allowed[current] && allowed[current].includes(newState)) {
|
|
|
56
70
|
"
|
|
57
71
|
|
|
58
72
|
if [ $? -eq 0 ]; then
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
SESSION_ID=$(node -p "JSON.parse(require('fs').readFileSync('$STATE_FILE', 'utf8')).session_id || 'manual-transition'")
|
|
74
|
+
TTFV_SECONDS=$(node -p "JSON.parse(require('fs').readFileSync('$STATE_FILE', 'utf8')).ttfv_seconds || 0")
|
|
75
|
+
cat > "$CURRENT_STATE_MD" <<EOF
|
|
76
|
+
# Current System State
|
|
77
|
+
|
|
78
|
+
**Time**: $(date +%F)
|
|
79
|
+
**Status**: \`$NEW_STATE\`
|
|
80
|
+
**Latest Session**: \`$SESSION_ID\`
|
|
81
|
+
**Time to First Verification (TTFV)**: ${TTFV_SECONDS}s
|
|
82
|
+
|
|
83
|
+
## Latest Transition
|
|
84
|
+
|
|
85
|
+
- State changed to \`$NEW_STATE\`
|
|
86
|
+
- Reason: $REASON
|
|
87
|
+
EOF
|
|
64
88
|
exit 0
|
|
65
89
|
else
|
|
66
90
|
exit 1
|