Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 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
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ All notable changes to this project are documented in this file.
- `adop aggregate`: read-only cross-project portfolio (scene / tool / state) across multiple `--root` artifact roots
- 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)
- `examples/`: a minimal, self-contained worked example (`examples/walkthrough/.adop/`)
- Secret-commit guard: `.gitignore` patterns plus pre-commit `detect-private-key`, `check-added-large-files`, and a local `forbid-secret-files` hook
- Coverage gate: `pytest-cov` dev dependency and a `fail_under` threshold (~84% measured)
Expand Down
19 changes: 19 additions & 0 deletions shared/python/adop_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,24 @@ def _landing_target(scene_items: list[dict[str, Any]]) -> str:
}


def _decision_owner(scene_items: list[dict[str, Any]]) -> str:
"""Who owns this decision — from the most-advanced artifact that records one."""
best: str | None = None
best_key: tuple[str, int] | None = None
for item in scene_items:
owner = _pick_first(item.get("decision_owner"))
if owner == "-":
continue
key = (
str(item.get("created_at", "")),
_EVIDENCE_STAGE.get(str(item.get("artifact_type", "")), 0),
)
if best_key is None or key >= best_key:
best_key = key
best = owner
return best or "-"


def _last_evidence(scene_items: list[dict[str, Any]]) -> str:
if not scene_items:
return "-"
Expand Down Expand Up @@ -1246,6 +1264,7 @@ def _build_lane(scene: str, scene_items: list[dict[str, Any]], state: str) -> di
else summary["what_happens_next"],
"landing_target": landing_target,
"control_model": _control_model(scene_items),
"decision_owner": _decision_owner(scene_items),
"last_evidence": _last_evidence(scene_items),
"kind_meta": _lane_meta(scene_items),
"headline": summary["headline"],
Expand Down
12 changes: 7 additions & 5 deletions shared/templates/adop-governance-dashboard-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -1506,11 +1506,13 @@ <h2>Raw record files for this decision</h2>

const summaryLines = document.getElementById("summary-lines");
summaryLines.replaceChildren();
[
["Current state", lane.state_meaning],
["Where it may be used", lane.landing_target],
["What the owner needs next", lane.next_step],
].forEach(([label, text]) => {
const summaryRows = [["Current state", lane.state_meaning]];
if (lane.decision_owner && lane.decision_owner !== "-") {
summaryRows.push(["Decision owner", lane.decision_owner]);
}
summaryRows.push(["Where it may be used", lane.landing_target]);
summaryRows.push(["What the owner needs next", lane.next_step]);
summaryRows.forEach(([label, text]) => {
const item = el("div", "summary-line");
item.appendChild(el("strong", "", label));
item.appendChild(el("span", "", text));
Expand Down
59 changes: 59 additions & 0 deletions tests/test_html_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,3 +861,62 @@ def test_latest_update_is_most_advanced_artifact_with_date(run, root):
assert "Trial plan" in ev # the most-advanced artifact, not the intake
assert "Intake" not in ev
assert ev[:4].isdigit() and ev[4] == "-" # leads with a date (YYYY-...)


def test_in_trial_lane_surfaces_decision_owner(run, root):
from adop_html import build_dashboard_payload, render_dashboard_html

assert (
run(
"quick-intake",
"--artifact-root",
root,
"--candidate",
"mypy",
"--source",
"doc",
"--use-case",
"tri",
"--why-now",
"x",
)
== 0
)
assert (
run(
"quick-compare",
"--artifact-root",
root,
"--use-case",
"tri",
"--candidate",
"mypy",
"--candidate",
"p",
"--selected",
"mypy",
)
== 0
)
assert (
run(
"quick-trial",
"--artifact-root",
root,
"--use-case",
"tri",
"--mode",
"review-assist",
"--executor",
"ci",
"--decision-owner",
"lead-eng",
"--landing-target",
"ci/x",
)
== 0
)
lane = next(ln for ln in build_dashboard_payload(Path(root))["lanes"] if ln["scene"] == "tri")
assert lane["decision_owner"] == "lead-eng"
html = render_dashboard_html(Path(root))
assert "Decision owner" in html and "lead-eng" in html