easy-coding-harness 1.0.0 → 1.0.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.
- package/CHANGELOG.md +18 -0
- package/README.md +15 -4
- package/dist/cli.js +33 -92
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/common/skills/ec-analysis/SKILL.md +13 -14
- package/templates/common/skills/ec-config/SKILL.md +3 -1
- package/templates/common/skills/ec-implementing/SKILL.md +11 -2
- package/templates/common/skills/ec-quality/SKILL.md +5 -0
- package/templates/common/skills/ec-task-management/SKILL.md +9 -2
- package/templates/common/skills/ec-tdd-init/SKILL.md +13 -9
- package/templates/common/skills/ec-workflow/SKILL.md +12 -3
- package/templates/main-constraint/AGENTS.md.tpl +7 -1
- package/templates/main-constraint/CLAUDE.md.tpl +7 -1
- package/templates/runtime/tools/easy_coding_tdd_readiness.py +18 -18
- package/templates/shared-hooks/easy_coding_state.py +341 -55
- package/templates/shared-hooks/easy_dev_spec.py +3 -1
package/package.json
CHANGED
|
@@ -28,21 +28,16 @@ shows the compound high-risk and complexity signals required for Strict. Do not
|
|
|
28
28
|
repositories, the full Spec, broad Git history, or every architecture section merely to prove
|
|
29
29
|
that a bounded task might be complicated.
|
|
30
30
|
|
|
31
|
-
For a task with `task.json.spec_source`,
|
|
31
|
+
For a task with `task.json.spec_source`, use `resume-spec-context` against the stored source, exact
|
|
32
32
|
`selected_spec_tasks`, and only their stored `task.repo_paths` bindings. Schema, Spec ID, design
|
|
33
33
|
revision, and `design_sha256` must still match. A changed `document_sha256` with the same design is
|
|
34
34
|
normal shared progress; refresh `execution_revision` without invalidating plan/QUALITY
|
|
35
|
-
evidence. An execution revision rollback is blocking.
|
|
36
|
-
|
|
35
|
+
evidence. An execution revision rollback is blocking. Reuse the ready consumption returned by
|
|
36
|
+
creation/claim in this session; otherwise load it once with:
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py
|
|
40
|
-
--
|
|
41
|
-
--spec-task <selected-task-id> [--spec-task <selected-task-id>]... \
|
|
42
|
-
[--repo-path <repo-id>=<stored-path>]...
|
|
43
|
-
|
|
44
|
-
{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py select-dev-spec-scope \
|
|
45
|
-
--spec <stored-source> --spec-task <selected-task-id> [--spec-task <selected-task-id>]...
|
|
39
|
+
{{PYTHON_CMD}} {{platform_config_dir}}/hooks/easy_coding_state.py resume-spec-context \
|
|
40
|
+
--task-id <task-id> --agent <agent-id> --session-file <P>
|
|
46
41
|
```
|
|
47
42
|
|
|
48
43
|
Load only the returned per-repository consumption closures: manifest/global context, selected
|
|
@@ -186,8 +181,9 @@ When TDD is enabled for a Java code task, make `test-strategy.md` record:
|
|
|
186
181
|
status are non-blocking and never require an intermediate commit or push. Include these exact,
|
|
187
182
|
language-independent contract markers: `local_test_gate: required` and
|
|
188
183
|
`remote_ci_acceptance: non-blocking`.
|
|
189
|
-
- current `tdd_readiness_status=ready`;
|
|
190
|
-
`
|
|
184
|
+
- current `tdd_readiness_status=ready`; a missing receipt requires `ec-tdd-init`, while
|
|
185
|
+
`needs_repair` requires fixing the reported entry without resetting TDD configuration.
|
|
186
|
+
Build-file content changes use current task tests and coverage; they do not require reinit.
|
|
191
187
|
|
|
192
188
|
The state API mechanically freezes current Git `HEAD` per repository into `task.tdd_baselines`
|
|
193
189
|
when ANALYSIS advances to IMPLEMENT. Plan the local command with that exact SHA and the frozen
|
|
@@ -306,6 +302,9 @@ waiting; it never changes the selected execution depth.
|
|
|
306
302
|
incomplete selected-task coverage, or an open Unit/Step/File/Symbol/Test traceability gap.
|
|
307
303
|
|
|
308
304
|
If evidence requires changing Canonical task boundaries, contracts, files, symbols, Steps, Tests,
|
|
309
|
-
or dependencies,
|
|
305
|
+
or dependencies, obtain confirmation and run `begin-spec-change --affected-task <id> --summary
|
|
306
|
+
<confirmed-change> --agent <agent-id> --session-file <P>` before editing. This persists the
|
|
307
|
+
intent across handoffs and blocks implementation/acceptance until synchronization. Update the original static design with revision +1,
|
|
310
308
|
restore READY, and call `sync-spec-design --affected-task ...`. This invalidates the old local
|
|
311
|
-
plan.
|
|
309
|
+
plan. Run `resume-spec-context` after synchronization, then refresh derived artifacts. Never
|
|
310
|
+
substitute edits to the derived `dev-spec.md`, and never edit `EDS:EXECUTION` by hand.
|
|
@@ -71,6 +71,8 @@ still generates the GitLab TEST-stage job, but Harness does not wait for or reco
|
|
|
71
71
|
results as acceptance evidence.
|
|
72
72
|
|
|
73
73
|
Before any project/session enable action, require `tdd_readiness_status=ready`. If it is not ready,
|
|
74
|
-
|
|
74
|
+
route `needs_init` to `ec-tdd-init` and `needs_repair` to the reported repair. Preserve existing
|
|
75
|
+
settings on failure; never offer or persist "enable now, initialize later". Normal build-file
|
|
76
|
+
changes do not require initialization, and a CLI upgrade must preserve project/session TDD values.
|
|
75
77
|
Readiness means infrastructure can measure future changed production lines. It does not certify
|
|
76
78
|
repository-wide coverage and does not require tests for unchanged historical code.
|
|
@@ -9,6 +9,12 @@ Use only after ANALYSIS has frozen `task.json.workflow_mode` to `fast`, `standar
|
|
|
9
9
|
`strict`. Read `dev-spec.md`, the latest `plan` record in `execution.jsonl`, relevant RULES
|
|
10
10
|
and ABSTRACT sections, and `test-strategy.md` for code tasks.
|
|
11
11
|
|
|
12
|
+
For a Canonical-backed task, consume the ready `spec_context.consumption` returned on creation
|
|
13
|
+
or claim. On session resume or after design sync, call `resume-spec-context --agent <agent-id>
|
|
14
|
+
--session-file <P>`. The bound source and selected changes/steps/tests govern the implementation;
|
|
15
|
+
handoff summaries and derived plans cannot substitute for this context. A blocked context or
|
|
16
|
+
pending `spec_change` stops implementation until the original source is repaired/synchronized.
|
|
17
|
+
|
|
12
18
|
If frozen `task.tdd_enabled` is not `true`, IMPLEMENT writes production and planned test code but
|
|
13
19
|
does not run lint, typecheck, test, build, or coverage commands. Deterministic execution belongs
|
|
14
20
|
to QUALITY's Verification Gate. TDD is the only exception because RED/GREEN/REFACTOR commands are
|
|
@@ -167,8 +173,11 @@ checks:[], issues:[], needs_attention:[]
|
|
|
167
173
|
6. For parallel units, detect overlapping writes before advancing.
|
|
168
174
|
7. If implementation needs a file, symbol, repository, or source step outside the mapped
|
|
169
175
|
Canonical change set, stop and return to ANALYSIS instead of expanding scope implicitly.
|
|
170
|
-
8. If a static Canonical change is confirmed,
|
|
171
|
-
|
|
176
|
+
8. If a static Canonical change is confirmed, first persist it with `begin-spec-change
|
|
177
|
+
--affected-task <id> --summary <confirmed-change> --agent <agent-id> --session-file <P>`.
|
|
178
|
+
Revise the original design by exactly one revision, validate READY and use `sync-spec-design`;
|
|
179
|
+
then `resume-spec-context` and rebuild the local plan in ANALYSIS. Never edit the
|
|
180
|
+
machine-owned execution block. If a writeback was
|
|
172
181
|
interrupted, run `reconcile-spec-execution` with the stored idempotent pending action.
|
|
173
182
|
Reconciliation only consumes dispatch/result evidence created after the current `in_progress`
|
|
174
183
|
acknowledgment; it never opens a new repair attempt or reuses an earlier attempt's result.
|
|
@@ -10,6 +10,11 @@ does not modify source, tests, configuration, plans, or task scope.
|
|
|
10
10
|
|
|
11
11
|
## Candidate freeze
|
|
12
12
|
|
|
13
|
+
For Canonical-backed tasks, load the current session's bound selection through `resume-spec-context`
|
|
14
|
+
when resuming. Pass that original consumption closure to both gates and compare selected contracts,
|
|
15
|
+
changes, Steps and Tests against the candidate. Pending `spec_change` blocks QUALITY acceptance
|
|
16
|
+
until source revision synchronization and ANALYSIS replanning have completed.
|
|
17
|
+
|
|
13
18
|
Call `evidence-fingerprints` once and use the returned implementation/config fingerprints for
|
|
14
19
|
the whole attempt. It also returns the runtime-owned `quality_attempt` number, start time, evidence
|
|
15
20
|
boundary, and repair count. Every Review and Verification record in this attempt must carry that
|
|
@@ -18,7 +18,8 @@ Call the state API snapshot and show:
|
|
|
18
18
|
- active and resumable tasks.
|
|
19
19
|
- for Canonical-backed tasks: source locator/path mode, Spec ID/design revision/design digest,
|
|
20
20
|
document digest, execution revision, writeback status, selected task IDs, repository
|
|
21
|
-
bindings/baseline status,
|
|
21
|
+
bindings/baseline status, pending dependency evidence, loaded context version/session, and
|
|
22
|
+
pending confirmed Spec change.
|
|
22
23
|
|
|
23
24
|
Mode inspection and configuration belongs to `ec-config`. If the user asks to change Approval,
|
|
24
25
|
Workflow, TDD, or the TDD coverage threshold, route there and do not mutate those fields here.
|
|
@@ -36,9 +37,15 @@ selection or creation to `ec-lite` so the user can exit it first.
|
|
|
36
37
|
When creating from a Canonical Spec, call `inspect-dev-spec --manifest-only`, display the complete
|
|
37
38
|
task and dependency selection, then call `create-task-from-spec` only after explicit user
|
|
38
39
|
selection. Multiple selected Spec tasks still create one Harness task. Do not call
|
|
39
|
-
`select-dev-spec-scope` during
|
|
40
|
+
`select-dev-spec-scope` during discovery. Creation and claim return the selected consumption
|
|
41
|
+
closure; consume it before stage work. On a resumed session, use `resume-spec-context` with
|
|
42
|
+
the current agent/session. A blocked context allows repair/rebind/sync, but blocks advancement.
|
|
40
43
|
Initialize missing shared execution before creation. Support `rebind-spec-source` only when the
|
|
41
44
|
new file matches schema + spec_id + design revision + design_sha256 and does not roll execution
|
|
42
45
|
revision backward. A pending writeback is repaired with `reconcile-spec-execution`, never by
|
|
43
46
|
editing the execution JSON block or starting a different writeback. A deterministic rejected
|
|
44
47
|
action is cleared with `status:error`; correct its input instead of replaying it.
|
|
48
|
+
|
|
49
|
+
Confirmed requirement changes use `begin-spec-change` before editing the original source.
|
|
50
|
+
Its summary and affected tasks survive handoff. Finish revision + READY + `sync-spec-design`,
|
|
51
|
+
then reload context and refresh the plan in ANALYSIS. Do not clear a pending change manually.
|
|
@@ -27,13 +27,14 @@ initialization.
|
|
|
27
27
|
First run:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
python3 .easy-coding/tools/easy_coding_tdd_readiness.py --cwd . check
|
|
30
|
+
python3 .easy-coding/tools/easy_coding_tdd_readiness.py --cwd . check --include-ci
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
If it returns `ready`, report the recorded build/CI contract and stop without creating a task.
|
|
34
34
|
The user may then use `ec-config` or `easy-coding config` to enable TDD.
|
|
35
35
|
|
|
36
|
-
If it returns `needs_init`, inspect only the infrastructure needed
|
|
36
|
+
If it returns `needs_init` or `needs_repair`, inspect only the reported infrastructure needed
|
|
37
|
+
to form a confirmed initialization or repair plan:
|
|
37
38
|
|
|
38
39
|
- Maven/Gradle files and the existing JUnit runner;
|
|
39
40
|
- JaCoCo XML generation configuration;
|
|
@@ -90,13 +91,16 @@ frozen Workflow Mode's applicable build/test/CI syntax checks, then performs onl
|
|
|
90
91
|
readiness check:
|
|
91
92
|
|
|
92
93
|
```bash
|
|
93
|
-
python3 .easy-coding/tools/easy_coding_tdd_readiness.py --cwd . check
|
|
94
|
+
python3 .easy-coding/tools/easy_coding_tdd_readiness.py --cwd . check --include-ci
|
|
94
95
|
```
|
|
95
96
|
|
|
96
|
-
The `QUALITY -> MEMORY` gate requires the
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
The `QUALITY -> MEMORY` gate requires the full initialization check to return `ready`.
|
|
98
|
+
Recorded SHA-256 values are historical snapshots, not freshness gates. Ordinary POM versions,
|
|
99
|
+
dependencies, build plugins, formatting, CI changes, and managed tool upgrades do not require
|
|
100
|
+
reinitialization. Daily `check` validates local entry points and task-variable contracts;
|
|
101
|
+
`--include-ci` additionally validates the initialization build/CI contract. Missing receipts
|
|
102
|
+
return `needs_init`; damaged receipts or required entries return `needs_repair`. Repair the
|
|
103
|
+
reported entry, repeat applicable tests, and preserve the user's TDD settings.
|
|
100
104
|
|
|
101
|
-
After completion,
|
|
102
|
-
enable route. Do not treat readiness as consent to
|
|
105
|
+
After completion, report the unchanged TDD setting and provide the explicit project/session
|
|
106
|
+
enable route when it is off. Do not treat readiness as consent to change it.
|
|
@@ -82,8 +82,8 @@ or `qoder`. Never use a display or source-author attribution such as `Codex with
|
|
|
82
82
|
failure: never copy, mirror, or rewrite the source Spec because of it.
|
|
83
83
|
|
|
84
84
|
Then call `create-task-from-spec` once for the complete selection. Do not call
|
|
85
|
-
`select-dev-spec-scope` during
|
|
86
|
-
|
|
85
|
+
`select-dev-spec-scope` during discovery; creation returns the selected consumption closure
|
|
86
|
+
for `ec-analysis` to use directly. A document without a Canonical manifest remains a legacy ANALYSIS input
|
|
87
87
|
for an ordinary task. A malformed, DRAFT, or otherwise non-READY Canonical Spec stays blocked
|
|
88
88
|
and must never be downgraded to the legacy route. A READY Canonical Spec without shared
|
|
89
89
|
execution remains readable, but run `initialize-spec-execution` before selection can become an
|
|
@@ -118,7 +118,9 @@ or `qoder`. Never use a display or source-author attribution such as `Codex with
|
|
|
118
118
|
`<source-task-id>-><dependency-task-id>=<evidence>`.
|
|
119
119
|
Explicit project-external Spec files are supported and stored as absolute locators. If that
|
|
120
120
|
locator moves, use `rebind-spec-source`; never guess by basename. Shared execution progress is
|
|
121
|
-
written only through state API writer commands.
|
|
121
|
+
written only through state API writer commands. Confirmed static design edits first require
|
|
122
|
+
`begin-spec-change --affected-task <id> --summary <confirmed-change> --agent <agent-id>
|
|
123
|
+
--session-file <P>`, then revision + READY +
|
|
122
124
|
`sync-spec-design`; never hand-edit the `EDS:EXECUTION` region.
|
|
123
125
|
4. When the user explicitly invokes `ec-tdd-init`, let that skill own preflight and create a
|
|
124
126
|
`type=tdd-init` code task only after scope confirmation. Do not reinterpret it as an ordinary
|
|
@@ -155,6 +157,13 @@ writeback remains pending or conflicted. A deterministic writer rejection report
|
|
|
155
157
|
clears the pending action so the corrected action can proceed; never overwrite a different
|
|
156
158
|
pending action.
|
|
157
159
|
|
|
160
|
+
Creation and claim return `spec_context.consumption` for the stored selection. Consume it before
|
|
161
|
+
dispatching a stage. After session resume or design sync, call `resume-spec-context --agent
|
|
162
|
+
<agent-id> --session-file <P>` and consume its returned closure. A blocked context requires
|
|
163
|
+
source repair or design sync; never continue from a handoff summary alone. If `spec_change` is
|
|
164
|
+
pending, resume that confirmed change on the bound original file before implementation/QUALITY.
|
|
165
|
+
Recovery preserves the original event author/idempotency key and the current task owner separately.
|
|
166
|
+
|
|
158
167
|
## Boundary handling
|
|
159
168
|
|
|
160
169
|
Use `request-transition` for a boundary that requires approval, then present the complete
|
|
@@ -54,6 +54,8 @@ First run `ec-init`; daily work goes through `ec-workflow`.
|
|
|
54
54
|
- TDD is session override > project `behavior.tdd_enabled` > `false`; its changed-line threshold
|
|
55
55
|
is session override > project `behavior.tdd_coverage_threshold` > `90`. ANALYSIS -> IMPLEMENT
|
|
56
56
|
freezes both. TDD may be enabled only after `ec-tdd-init` records valid infrastructure readiness;
|
|
57
|
+
build version/content changes require fresh task evidence, not reinitialization. Repair missing
|
|
58
|
+
local entries without resetting TDD; CLI upgrades preserve project/session/frozen task settings;
|
|
57
59
|
there is no enable-now/init-later state. The dedicated `tdd-init` task always freezes TDD off and
|
|
58
60
|
initializes only changed-line coverage infrastructure, never historical business-test coverage.
|
|
59
61
|
Disabled TDD adds no CI scan, JaCoCo work, commands, artifacts, or stronger gates. Enabled TDD
|
|
@@ -108,7 +110,11 @@ First run `ec-init`; daily work goes through `ec-workflow`.
|
|
|
108
110
|
`document_sha256` and `execution_revision` may advance through shared writer commands. Project-
|
|
109
111
|
external explicit Spec paths are allowed and may be repaired only with identity-checked rebind.
|
|
110
112
|
Runtime progress must use the shared writer with CAS/idempotency and reconciliation; static
|
|
111
|
-
design changes
|
|
113
|
+
confirmed design changes first use `begin-spec-change`, then revision + READY + `sync-spec-design`.
|
|
114
|
+
Creation/claim returns selected source context; session resume and design sync require
|
|
115
|
+
`resume-spec-context` before work. Pending changes block implementation/acceptance across agents.
|
|
116
|
+
Preserve the original writer actor while retaining the current owner during reconciliation.
|
|
117
|
+
Never hand-edit `EDS:EXECUTION`.
|
|
112
118
|
Selected source tasks remain `implemented` through local QUALITY and become `verified`
|
|
113
119
|
only when the accepted QUALITY -> MEMORY boundary is actually applied.
|
|
114
120
|
- Canonical routing is two-pass: first use manifest-only discovery for the current worktree, then
|
|
@@ -52,6 +52,8 @@ First run `/ec-init`; daily work goes through `/ec-workflow`.
|
|
|
52
52
|
- TDD is session override > project `behavior.tdd_enabled` > `false`; its changed-line threshold
|
|
53
53
|
is session override > project `behavior.tdd_coverage_threshold` > `90`. ANALYSIS -> IMPLEMENT
|
|
54
54
|
freezes both. TDD may be enabled only after `ec-tdd-init` records valid infrastructure readiness;
|
|
55
|
+
build version/content changes require fresh task evidence, not reinitialization. Repair missing
|
|
56
|
+
local entries without resetting TDD; CLI upgrades preserve project/session/frozen task settings;
|
|
55
57
|
there is no enable-now/init-later state. The dedicated `tdd-init` task always freezes TDD off and
|
|
56
58
|
initializes only changed-line coverage infrastructure, never historical business-test coverage.
|
|
57
59
|
Disabled TDD adds no CI scan, JaCoCo work, commands, artifacts, or stronger gates. Enabled TDD
|
|
@@ -106,7 +108,11 @@ First run `/ec-init`; daily work goes through `/ec-workflow`.
|
|
|
106
108
|
`document_sha256` and `execution_revision` may advance through shared writer commands. Project-
|
|
107
109
|
external explicit Spec paths are allowed and may be repaired only with identity-checked rebind.
|
|
108
110
|
Runtime progress must use the shared writer with CAS/idempotency and reconciliation; static
|
|
109
|
-
design changes
|
|
111
|
+
confirmed design changes first use `begin-spec-change`, then revision + READY + `sync-spec-design`.
|
|
112
|
+
Creation/claim returns selected source context; session resume and design sync require
|
|
113
|
+
`resume-spec-context` before work. Pending changes block implementation/acceptance across agents.
|
|
114
|
+
Preserve the original writer actor while retaining the current owner during reconciliation.
|
|
115
|
+
Never hand-edit `EDS:EXECUTION`.
|
|
110
116
|
Selected source tasks remain `implemented` through local QUALITY and become `verified`
|
|
111
117
|
only when the accepted QUALITY -> MEMORY boundary is actually applied.
|
|
112
118
|
- Canonical routing is two-pass: first use manifest-only discovery for the current worktree, then
|
|
@@ -118,21 +118,18 @@ def parse_records(root: Path, value: object, field: str, reasons: list[str]) ->
|
|
|
118
118
|
reasons.append(f"{field} contains an invalid record")
|
|
119
119
|
continue
|
|
120
120
|
file_name = item.get("path")
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
reasons.append(f"{field} contains an invalid path or SHA-256")
|
|
121
|
+
if not isinstance(file_name, str) or not file_name.strip() or Path(file_name).is_absolute():
|
|
122
|
+
reasons.append(f"{field} contains an invalid path")
|
|
124
123
|
continue
|
|
125
124
|
try:
|
|
126
125
|
_, resolved = project_file(root, file_name)
|
|
127
|
-
if sha256(resolved) != expected:
|
|
128
|
-
reasons.append(f"readiness file changed: {file_name}")
|
|
129
126
|
contents.append(resolved.read_text(encoding="utf-8"))
|
|
130
127
|
except (OSError, UnicodeError, ReadinessError) as error:
|
|
131
128
|
reasons.append(str(error))
|
|
132
129
|
return contents
|
|
133
130
|
|
|
134
131
|
|
|
135
|
-
def inspect(root: Path) -> dict[str, object]:
|
|
132
|
+
def inspect(root: Path, include_ci: bool = False) -> dict[str, object]:
|
|
136
133
|
receipt = root / RECEIPT
|
|
137
134
|
if not receipt.is_file():
|
|
138
135
|
return {
|
|
@@ -145,7 +142,7 @@ def inspect(root: Path) -> dict[str, object]:
|
|
|
145
142
|
manifest = json.loads(receipt.read_text(encoding="utf-8"))
|
|
146
143
|
except (OSError, UnicodeError, json.JSONDecodeError):
|
|
147
144
|
return {
|
|
148
|
-
"status": "
|
|
145
|
+
"status": "needs_repair",
|
|
149
146
|
"coverage_scope": COVERAGE_SCOPE,
|
|
150
147
|
"reasons": ["TDD readiness receipt is invalid"],
|
|
151
148
|
"receipt": RECEIPT.as_posix(),
|
|
@@ -182,7 +179,6 @@ def inspect(root: Path) -> dict[str, object]:
|
|
|
182
179
|
manifest_ci_files = manifest.get("ci_files")
|
|
183
180
|
manifest_tool_files = manifest.get("tool_files")
|
|
184
181
|
build_contents = parse_records(root, manifest_build_files, "build_files", reasons)
|
|
185
|
-
ci_contents = parse_records(root, manifest_ci_files, "ci_files", reasons)
|
|
186
182
|
parse_records(root, manifest_tool_files, "tool_files", reasons)
|
|
187
183
|
build_paths = {
|
|
188
184
|
Path(item.get("path", "")).name
|
|
@@ -196,8 +192,6 @@ def inspect(root: Path) -> dict[str, object]:
|
|
|
196
192
|
} if isinstance(manifest_ci_files, list) else set()
|
|
197
193
|
if not build_paths.intersection(JAVA_BUILD_FILE_NAMES):
|
|
198
194
|
reasons.append("build_files must include a Maven or Gradle Java build file")
|
|
199
|
-
if not ci_paths.intersection(GITLAB_CI_ENTRY_FILES):
|
|
200
|
-
reasons.append("ci_files must include the project-root GitLab CI entry file")
|
|
201
195
|
tool_paths = {
|
|
202
196
|
item.get("path", "").replace("\\", "/")
|
|
203
197
|
for item in manifest_tool_files
|
|
@@ -205,12 +199,16 @@ def inspect(root: Path) -> dict[str, object]:
|
|
|
205
199
|
} if isinstance(manifest_tool_files, list) else set()
|
|
206
200
|
if COVERAGE_TOOL_PATH not in tool_paths:
|
|
207
201
|
reasons.append(f"tool_files must include {COVERAGE_TOOL_PATH}")
|
|
208
|
-
if
|
|
209
|
-
|
|
210
|
-
|
|
202
|
+
if include_ci:
|
|
203
|
+
ci_contents = parse_records(root, manifest_ci_files, "ci_files", reasons)
|
|
204
|
+
if not ci_paths.intersection(GITLAB_CI_ENTRY_FILES):
|
|
205
|
+
reasons.append("ci_files must include the project-root GitLab CI entry file")
|
|
206
|
+
if not any("jacoco" in content.lower() for content in build_contents):
|
|
207
|
+
reasons.append("build files do not configure JaCoCo")
|
|
208
|
+
reasons.extend(ci_contract_reasons(ci_contents))
|
|
211
209
|
|
|
212
210
|
return {
|
|
213
|
-
"status": "ready" if not reasons else "
|
|
211
|
+
"status": "ready" if not reasons else "needs_repair",
|
|
214
212
|
"coverage_scope": COVERAGE_SCOPE,
|
|
215
213
|
"reasons": list(dict.fromkeys(reasons)),
|
|
216
214
|
"receipt": RECEIPT.as_posix(),
|
|
@@ -274,7 +272,7 @@ def record(args: argparse.Namespace, root: Path) -> dict[str, object]:
|
|
|
274
272
|
temporary = receipt.with_suffix(f".tmp-{os.getpid()}")
|
|
275
273
|
temporary.write_text(json.dumps(manifest, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
|
276
274
|
temporary.replace(receipt)
|
|
277
|
-
result = inspect(root)
|
|
275
|
+
result = inspect(root, include_ci=True)
|
|
278
276
|
if result["status"] != "ready":
|
|
279
277
|
raise ReadinessError("Recorded readiness receipt did not pass validation.")
|
|
280
278
|
return result
|
|
@@ -284,7 +282,8 @@ def main() -> int:
|
|
|
284
282
|
parser = argparse.ArgumentParser(description="Easy Coding Java TDD readiness tool")
|
|
285
283
|
parser.add_argument("--cwd", default=".")
|
|
286
284
|
subcommands = parser.add_subparsers(dest="command", required=True)
|
|
287
|
-
subcommands.add_parser("check")
|
|
285
|
+
check_parser = subcommands.add_parser("check")
|
|
286
|
+
check_parser.add_argument("--include-ci", action="store_true")
|
|
288
287
|
record_parser = subcommands.add_parser("record")
|
|
289
288
|
record_parser.add_argument("--build-file", action="append", default=[])
|
|
290
289
|
record_parser.add_argument("--ci-file", action="append", default=[])
|
|
@@ -294,9 +293,10 @@ def main() -> int:
|
|
|
294
293
|
args = parser.parse_args()
|
|
295
294
|
root = Path(args.cwd).resolve()
|
|
296
295
|
try:
|
|
297
|
-
result = inspect(root) if args.command == "check" else record(args, root)
|
|
296
|
+
result = inspect(root, args.include_ci) if args.command == "check" else record(args, root)
|
|
298
297
|
except (OSError, UnicodeError, ReadinessError) as error:
|
|
299
|
-
|
|
298
|
+
status = "needs_repair" if (root / RECEIPT).exists() else "needs_init"
|
|
299
|
+
print(json.dumps({"status": status, "reasons": [str(error)]}, ensure_ascii=False))
|
|
300
300
|
return 2
|
|
301
301
|
print(json.dumps(result, ensure_ascii=False))
|
|
302
302
|
return 0 if result["status"] == "ready" else 1
|