diff --git a/CHANGELOG.md b/CHANGELOG.md index edafc87e..b5a253d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m ## Unreleased +- fix(progress-report): **the build plan is shown once: the phase cards are the plan.** Expanding a card now shows its full rows (#, Kind, Step, Produces/Proves, Depends on, State, Scripts) and Claims, which only the duplicate "Full plan tables" block carried; that block is gone and views A (script folders) and B (module proof) are their own section. The `now` phase renders open with a selected style, opening another phase closes the previous one (accordion; `#phase-N` links still open their card), and a viewer's saved open/closed state survives the 30 s reload and wins over the default (#474) — field feedback from a requirements-driven project at Stage 5 — MendixMau (field feedback 2026-10-20) + ## v2026.10.19 - new(progress-report): **the progress report gains a Project pages section: a compact folder tree of the HTML pages found in the project's output folders (gate dashboard, analysis reports, blueprint, design system, process map, wireframes, UI reviews, test reports), each a relative link from `architecture/` with its modified date.** Pages are found by scanning the project's files on every render, never from a stored list; only the top-level folders in `PAGE_DIRS` are scanned (each named with its producer; a symlinked one is skipped), `node_modules`, `.mpr-snapshots`, `deployment`, `mprcontents`, `theme`, `.git`, vendor and dot folders are never entered, a folder with more than 8 pages folds behind a count, every folder keeps its row and lists at most 100 links (`+K more`), and the report never lists itself. Dates are shown as days, so the section is unchanged on the same day unless a listed page changed and a `--refresh` leaves the page alone. Test: `tests/wave2/test-progress-report-pages.sh` (single and two-tree layouts, Windows hrefs) — MendixMau (request 2026-10-19) diff --git a/project-bin/build-plan-status.sh b/project-bin/build-plan-status.sh index b9530361..c7f1ac32 100755 --- a/project-bin/build-plan-status.sh +++ b/project-bin/build-plan-status.sh @@ -532,10 +532,10 @@ render_plan_section() { # stdout: the plan section's HTML echo "

The plan

Nothing to show yet: ${PLAN_MSG:-build-plan.md was not read}.

" return 0 fi - "$PY" - "$PLAN_JSON" "$MDLSOURCE" <<'PYEOF' || echo "

The plan

Could not render the plan section from build-plan.md.

" + "$PY" - "$PLAN_JSON" "$MDLSOURCE" "${PHASE_DETAIL:-/dev/null}" <<'PYEOF' || echo "

The plan

Could not render the plan section from build-plan.md.

" import fnmatch, html, json, os, re, sys -src, mdl = sys.argv[1], sys.argv[2] +src, mdl, detail_out = sys.argv[1], sys.argv[2], sys.argv[3] d = json.load(open(src, encoding="utf-8")) e = lambda s: html.escape(s or "", quote=True) # `code` spans in plan cells render as , not literal backticks @@ -631,29 +631,32 @@ if named_total: print("

Scripts named in the plan: %d, of which %d are renamed done- under mdlsource/.%s

" % ( named_total, named_done, (" ⚠ %s where the plan and the disk disagree." % plural(drift_rows, "row")) if drift_rows else "")) +# One view of the plan: each phase's rows and claims go to the detail file, which progress-report.py +# splices into that phase's card. They are not printed here, or the rows would appear twice. +det = [] for p, out in zip(phases, rows_html): - print('

Phase %s — %s %s

' % ( - e(p["id"]), e(p["name"]), CLS.get(p["state"], "st-unknown"), e(p["state"]))) + h = ['' % e(p["id"]), + '

Phase state: %s

' % (CLS.get(p["state"], "st-unknown"), e(p["state"]))] if p.get("note"): - print("

%s

" % e(p["note"])) + h.append("

%s

" % e(p["note"])) if p["steps"]: - b = sum(1 for s in p["steps"] if classify(s["state"]) == "built") - print("

%d of %s built

" % (b, plural(len(p["steps"]), "row"))) - print("
" - "") - print("\n".join(out)) - print("
#KindStepProduces / ProvesDepends onStateScripts
") + h.append("
" + "") + h.append("\n".join(out)) + h.append("
#KindStepProduces / ProvesDepends onStateScripts
") else: - print("

No row table under this phase.

") + h.append("

No row table under this phase.

") if p.get("claims"): - print("
Claims (%d)
    " % len(p["claims"])) + h.append("
    Claims (%d)
      " % len(p["claims"])) for c in p["claims"]: extra = (" (%d)" % c["count"] if c.get("count") is not None else "") + (" [%s]" % c["brd"] if c.get("brd") else "") - print("
    • %s%s
    • " % (e(c["pointer"]), e(extra))) - print("
    ") + h.append("
  • %s%s
  • " % (e(c["pointer"]), e(extra))) + h.append("
") elif p.get("claimsNote"): - print("

Claims: %s

" % e(p["claimsNote"])) - print("
") + h.append("

Claims: %s

" % e(p["claimsNote"])) + h.append('') + det.append("\n".join(h)) +open(detail_out, "w", encoding="utf-8").write("\n".join(det)) w = d.get("warnings") or [] if w: print("
Parser notes (%d): lines in build-plan.md this page could not read as plan data