Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
762ef52
fix: close generic-completeness audit findings (C1-C4, U1-U5)
maruwork Jun 19, 2026
2547d30
fix: close round-2/3 security, sync, and dashboard-fidelity audit fin…
maruwork Jun 19, 2026
1d8ed8e
fix: dashboard fidelity, Windows concurrency, summary scaling, lint p…
maruwork Jun 19, 2026
ea9a814
feat: schema-version tolerance, cross-project aggregate, coverage gate
maruwork Jun 19, 2026
453987f
style: make ruff check + ruff format clean for CI (pre-commit gate)
maruwork Jun 19, 2026
a0c678f
fix(ci): make mypy green by collapsing dead relative-import branch
maruwork Jun 19, 2026
f650046
ci: re-trigger PR checks
maruwork Jun 19, 2026
69c66fc
feat(html): add a back-to-top button to the dashboard
maruwork Jun 19, 2026
827902a
chore: declutter repo root (move community files to .github/, drop st…
maruwork Jun 19, 2026
1db33fc
fix: init creates nested overlay parent; summary hides stale structur…
maruwork Jun 19, 2026
c0144f2
chore: convert to a clean pure-tool repo (drop self-dogfooding appara…
maruwork Jun 19, 2026
77b8ce5
docs: add a minimal, self-contained worked example under examples/
maruwork Jun 19, 2026
8300d4f
fix(ci): repair invalid ci.yml YAML that startup-failed every run sin…
maruwork Jun 19, 2026
db142d5
test: de-flake concurrent id-minting test on loaded CI (12 -> 5 workers)
maruwork Jun 19, 2026
6f2ba5d
ci: trigger hosted run on fixed tree
maruwork Jun 19, 2026
3f31731
chore: block secrets/.env/keys from ever being committed
maruwork Jun 19, 2026
3375bb1
Merge main (squash of #11) into branch, keeping the branch superset
maruwork Jun 19, 2026
7b5a2a0
test: give concurrent id-mint test an effectively-unbounded retry budget
maruwork Jun 19, 2026
559ed34
Merge main into branch before re-merge (keep branch superset)
maruwork Jun 19, 2026
4a1c7ba
docs: fill in the Unreleased changelog (was incorrectly 'Nothing yet')
maruwork Jun 19, 2026
bb0a860
Merge main into branch (keep branch superset)
maruwork Jun 19, 2026
3b006b6
fix(html): "Latest update" shows the most-recent artifact with its date
maruwork Jun 20, 2026
0a7fda1
Merge main (keep branch superset)
maruwork Jun 20, 2026
3267cce
feat(html): show decision_owner in the decision detail
maruwork Jun 20, 2026
8032bdb
Merge main (keep branch superset)
maruwork Jun 20, 2026
9f4a28e
fix(cli): return a JSON error (exit 11) instead of a raw traceback on…
maruwork Jun 20, 2026
b69ffee
Merge main (keep branch superset)
maruwork Jun 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ All notable changes to this project are documented in this file.

- `adop reject`: reject a candidate from `proposed` / `blocked` / `hold` without running a trial (terminal for the scene)
- `adop aggregate`: read-only cross-project portfolio (scene / tool / state) across multiple `--root` artifact roots
- `adop render-html`: render the canonical HTML governance dashboard from an artifact root
- Schema-version tolerance: `MIN_READABLE_SCHEMA_VERSION` keeps older artifacts valid after an upgrade; a too-new `schema_version` reports "written by a newer adop; upgrade adop" instead of a generic invalid
- HTML dashboard: a "Back to top" button
- HTML dashboard: the decision detail now shows the `decision_owner` for lanes that record one (was only in the raw JSON)
Expand All @@ -26,6 +27,7 @@ All notable changes to this project are documented in this file.
- `adop init`: creates a nested `--overlay` parent directory instead of crashing with `FileNotFoundError`
- `adop summary`: no longer prints a comparison-time structural gap once a scene has advanced to `in-trial` or later
- CI: repaired `ci.yml` (a Windows PowerShell here-string broke the workflow YAML, startup-failing every run since 0.1.1); de-flaked the concurrent id-mint test on loaded runners
- CLI no longer leaks a raw `KeyError` / traceback when a parent artifact is missing a field a handler reads (e.g. a hand-edited or schema-drifted trial packet); it returns a JSON error envelope with exit 11

### Changed

Expand All @@ -34,7 +36,7 @@ All notable changes to this project are documented in this file.

### Tests

- Suite grew from 105 to 199 tests
- Suite grew from 105 to 202 tests

## 0.1.1 - 2026-06-17

Expand Down
14 changes: 14 additions & 0 deletions shared/python/adop_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3179,6 +3179,20 @@ def main(argv: list[str] | None = None) -> int:
except artifacts.AdopArtifactError as exc:
_emit(artifacts.json_response(args.command, "error", [], [str(exc)]))
return 11
except KeyError as exc:
# A schema-drifted or hand-edited parent artifact can be missing a field a
# handler reads directly (e.g. packet["landing_target"]). The store
# tolerates older/forward records, so surface this as a JSON-native schema
# error instead of leaking a raw KeyError traceback.
_emit(
artifacts.json_response(
args.command, "error", [], [f"artifact missing required field: {exc}"]
)
)
return 11
except Exception as exc: # noqa: BLE001 — JSON-native CLI must never leak a raw traceback
_emit(artifacts.json_response(args.command, "error", [], [f"unexpected error: {exc}"]))
return 11


if __name__ == "__main__":
Expand Down
90 changes: 90 additions & 0 deletions tests/test_lifecycle_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -949,3 +949,93 @@ def test_reject_open_trial_directs_to_close(run, root):
== 0
)
assert run("reject", "--artifact-root", root, "--use-case", "r", "--reject-reason", "no") == 7


def test_close_trial_on_corrupt_packet_returns_clean_error(run, root):
"""A parent artifact missing a required field must yield a JSON error, not a traceback."""
import json as _json
from pathlib import Path

assert (
run(
"quick-intake",
"--artifact-root",
root,
"--candidate",
"ruff",
"--source",
"doc",
"--use-case",
"s",
"--why-now",
"x",
)
== 0
)
assert (
run(
"quick-compare",
"--artifact-root",
root,
"--use-case",
"s",
"--candidate",
"ruff",
"--candidate",
"p",
"--selected",
"ruff",
)
== 0
)
assert (
run(
"quick-trial",
"--artifact-root",
root,
"--use-case",
"s",
"--mode",
"review-assist",
"--executor",
"ci",
"--decision-owner",
"o",
"--landing-target",
"l",
)
== 0
)
pkt = next(Path(root).glob("adop_trial-packet_*.json"))
data = _json.loads(pkt.read_text(encoding="utf-8"))
del data["landing_target"]
pkt.write_text(_json.dumps(data), encoding="utf-8")
# Must not raise a bare KeyError; main() converts it to exit 11.
assert (
run(
"close-trial",
"--artifact-root",
root,
"--trial-id",
"tr-001",
"--verdict",
"hold",
"--observed-effect",
"x",
"--judgment-reason",
"j",
"--next-action",
"n",
"--recurring-control-decision",
"no",
"--root-cause-hypothesis",
"h",
"--preventive-action",
"p",
"--why-this-problem-recurred",
"w",
"--reopen-condition",
"later",
)
== 11
)