Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
d3e42a8
perf(exec): opt-in mx-check gate, Windows exec overhead fixes (#584, …
claude Oct 28, 2026
ed66333
fix(exec): drop … if exists (re-create idiom) no longer forces a full…
claude Oct 28, 2026
c25f1f0
perf(exec): full build at batch boundaries instead of every 5th exec …
claude Oct 29, 2026
48eb365
feat(doctor, init): measure exec performance; Gate mode: check for ne…
claude Oct 29, 2026
3a2d20a
fix(exec): review of #587: no gate state outside check mode, refresh …
claude Oct 29, 2026
f164b46
Merge origin/master into perf/windows-exec-speed; credit the CHANGELO…
claude Oct 29, 2026
a7cb3cf
test(gate-kind): no email literal in fixture git config (leak guard)
claude Oct 29, 2026
71ff2c3
feat(exec): mx check gate is the default; Gate mode: full opts out
claude Oct 29, 2026
d3e4127
fix(hooks): sync installs the pre-push full-build hook on existing pr…
claude Oct 29, 2026
f0aaf6e
perf(exec): ~55% fewer forks, ~60% fewer process starts per exec (#58…
claude Oct 29, 2026
7f36ebe
Merge remote-tracking branch 'origin/perf/windows-exec-speed' into pe…
claude Oct 29, 2026
d89de4d
docs(CHANGELOG): drop the pre-default duplicates the merge kept; cred…
claude Oct 29, 2026
362b4d2
fix(lint-gate): the receipt-check skip keys on content, not mtimes (#…
claude Oct 29, 2026
2e99ddf
test(lint-receipt): T1b rewrites in place and keeps the folder mtime,…
claude Oct 29, 2026
16d6b1f
Merge remote-tracking branch 'origin/master' into perf/exec-overhead
claude Oct 29, 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
2 changes: 1 addition & 1 deletion CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bin/doctor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ if [ -n "$_perf_log" ] && [ -f "$_perf_log" ] && grep -q 'steps: ' "$_perf_log"
warn "slow execs — $_pmsg"
[ "$_pgate" -gt "${MXTK_PERF_GATE_WARN:-45}" ] && note "The gate (mxbuild) dominates: 'Gate mode: check' in PROJECT.md runs mx check per exec and the full build before push."
[ -n "$_spawn_ms" ] && [ "$_spawn_ms" -gt "${MXTK_SPAWN_WARN_MS:-30}" ] && note "Process starts are slow too (above): that is the machine, not the model — see the advice there."
note "Per-command profile of one exec: MXTK_PROFILE=1 ./bin/exec.sh <script> (prints the 15 slowest lines)."
note "Per-command profile of one exec: MXTK_PROFILE=1 ./bin/exec.sh <script> (prints the 15 slowest lines; MXTK_PROFILE=2 traces the scripts it starts too)."
else
ok "$_pmsg"
fi
Expand Down
13 changes: 8 additions & 5 deletions bin/exec-approval.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@

set -u

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

PROJECT_DIR="${1:-}"
ACTION="${2:-}"

Expand Down Expand Up @@ -129,9 +127,14 @@ if [ -z "$MODE" ] && [ -f "$PROJECT_DIR/PROJECT.md" ]; then
# first occurrence wins so an appended log entry cannot silently retune the project. The whole
# rest of the line is the value, so any trailing note is invalid → `ask`. (interview-mode.sh
# allows a note after `steering` only; this read deliberately stays exact.)
FROM_MD=$(grep -iEm1 '^[[:space:]]*(-[[:space:]]*)?\**Exec approval\**[[:space:]]*:' "$PROJECT_DIR/PROJECT.md" 2>/dev/null \
| sed -E 's/.*[Aa]pproval\**[[:space:]]*:[[:space:]]*//' \
| tr '[:upper:]' '[:lower:]' | tr -d '[:space:]*`')
# grep first, alone: most projects have no such line, and the sed | tr | tr behind it then
# ran over empty input (three process starts to produce nothing).
FROM_MD=""
_EA_LINE=$(grep -iEm1 '^[[:space:]]*(-[[:space:]]*)?\**Exec approval\**[[:space:]]*:' "$PROJECT_DIR/PROJECT.md" 2>/dev/null || true)
if [ -n "$_EA_LINE" ]; then
FROM_MD=$(printf '%s\n' "$_EA_LINE" | sed -E 's/.*[Aa]pproval\**[[:space:]]*:[[:space:]]*//' \
| tr '[:upper:]' '[:lower:]' | tr -d '[:space:]*`')
fi
if [ -n "$FROM_MD" ]; then
if is_valid "$FROM_MD"; then
MODE="$FROM_MD"; SOURCE="PROJECT.md"
Expand Down
9 changes: 8 additions & 1 deletion bin/mdl-scan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,14 @@ done
[ -f "$SCRIPT" ] && [ -r "$SCRIPT" ] || { echo "mdl-scan: cannot read script: $SCRIPT" >&2; exit 2; }
if [ -n "$MPR" ] && [ ! -f "$MPR" ]; then echo "mdl-scan: -p: no such model: $MPR" >&2; exit 2; fi

RULES="${MDL_SCAN_RULES:-$(cd "$(dirname "$0")" && pwd)/lib/mdl-scan-rules.tsv}"
# The script's own folder, as a string op when $0 is already a path (a cd | dirname | pwd was
# three process starts per exec); an absolute path stays as it was, a relative one is anchored.
if [ -n "${MDL_SCAN_RULES:-}" ]; then RULES="$MDL_SCAN_RULES"
else
_msd="${0%/*}"; [ "$_msd" != "$0" ] || _msd=.
case "$_msd" in /*) ;; *) _msd="$(cd "$_msd" && pwd)" ;; esac
RULES="$_msd/lib/mdl-scan-rules.tsv"
fi
[ -r "$RULES" ] || { echo "mdl-scan: rules file missing: $RULES" >&2; exit 2; }

awk -F'\t' -v file="$SCRIPT" '
Expand Down
177 changes: 116 additions & 61 deletions project-bin/_common.sh

Large diffs are not rendered by default.

46 changes: 28 additions & 18 deletions project-bin/build-plan-status.sh
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,14 @@ MDLSOURCE="$ROOT/mdlsource"
MODULES_DIR="$ROOT/architecture/modules"
REGISTER="$ROOT/docs/improvement-register.md"
BUILD_PLAN="$ROOT/architecture/build-plan.md"
STAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
if [ -n "${EPOCHSECONDS:-}" ]; then TZ=UTC printf -v STAMP '%(%Y-%m-%dT%H:%M:%SZ)T' -1 # bash 5: no date process
else STAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"; fi

# PROJECT.md `Progress report: off | ask | auto` (default ask). off = this script never writes the
# page; ask and auto only change what the agent does at a stage gate or module close (the skills
# say: ask once, or open it), so the script treats them the same.
report_name() { # the page name lives in progress-report.py (REPORT_FILE); asked once, here
REPORT_FILE="$("${PY:-python3}" "$(dirname "${BASH_SOURCE[0]}")/progress-report.py" --print-name 2>/dev/null)" # portability-ok: PY is resolve_py output; python3 only if unset
REPORT_FILE="$("${PY:-python3}" "${_bpd:-$(dirname "${BASH_SOURCE[0]}")}/progress-report.py" --print-name 2>/dev/null)" # portability-ok: PY is resolve_py output; python3 only if unset
[ -n "$REPORT_FILE" ] || REPORT_FILE="progress-report.html"
}
progress_report_setting() {
Expand All @@ -116,12 +117,21 @@ progress_report_setting() {
PHASE_ROWS=""
PHASE_COUNT=0
if [ -d "$MDLSOURCE" ]; then
# Counted with globs: the find | wc | tr (and basename) per phase folder were five process
# starts each. dotglob + the symlink test keep find -type f's answer.
_dg=0; shopt -q dotglob && _dg=1
for d in "$MDLSOURCE"/*/; do
[ -d "$d" ] || continue
phase="$(basename "$d")"
total=$(find "$d" -maxdepth 1 -type f \( -name '*.mdl' -o -name '*.sql' \) | wc -l | tr -d ' ')
_dn="${d%/}"; phase="${_dn##*/}"
total=0; done_ct=0
shopt -s dotglob # only for the file globs: the phase folders themselves stay non-hidden
for _pf in "$d"*.mdl "$d"*.sql; do
[ -f "$_pf" ] && [ ! -L "$_pf" ] || continue
total=$((total + 1))
case "${_pf##*/}" in done-*) done_ct=$((done_ct + 1)) ;; esac
done
[ "$_dg" = 1 ] || shopt -u dotglob
[ "$total" -eq 0 ] && continue
done_ct=$(find "$d" -maxdepth 1 -type f \( -name 'done-*.mdl' -o -name 'done-*.sql' \) | wc -l | tr -d ' ')
pct=$(( total > 0 ? done_ct * 100 / total : 0 ))
status="pending"
[ "$done_ct" -gt 0 ] && status="in-progress"
Expand All @@ -142,7 +152,7 @@ REVIEWED_COUNT=0
if [ -d "$MODULES_DIR" ]; then
for d in "$MODULES_DIR"/*/; do
[ -d "$d" ] || continue
module="$(basename "$d")"
_dn="${d%/}"; module="${_dn##*/}"
briefed="no"
if [ -f "$d/module-brief.md" ]; then
briefed="yes"
Expand Down Expand Up @@ -170,14 +180,13 @@ if [ -d "$MODULES_DIR" ]; then
reviewed="not yet"
if [ -f "$summary" ]; then
REVIEWED_COUNT=$((REVIEWED_COUNT+1))
if grep -q $'\tFAULT\t' "$summary" 2>/dev/null; then
reviewed="INCOMPLETE (instrument fault)"
elif grep -q $'\tFINDING\t' "$summary" 2>/dev/null; then
reviewed="FINDINGS"
else
reviewed="CLEAN"
fi
age_s=$(( $(date +%s) - $(date -r "$summary" +%s 2>/dev/null || echo 0) ))
_sum=""; IFS= read -r -d '' _sum < "$summary" 2>/dev/null || true # two greps over it, in-shell
case "$_sum" in
*$'\tFAULT\t'*) reviewed="INCOMPLETE (instrument fault)" ;;
*$'\tFINDING\t'*) reviewed="FINDINGS" ;;
*) reviewed="CLEAN" ;;
esac
age_s=$(( ${EPOCHSECONDS:-$(date +%s)} - $(date -r "$summary" +%s 2>/dev/null || echo 0) ))
age_d=$(( age_s / 86400 ))
reviewed="$reviewed (${age_d}d ago)"
fi
Expand Down Expand Up @@ -432,9 +441,10 @@ PYEOF
}

if [ "$WRITE_JSON" -eq 1 ] || [ "$WRITE_HTML" -eq 1 ]; then
if [ -f "$(dirname "${BASH_SOURCE[0]}")/_common.sh" ]; then
_bpd="${BASH_SOURCE[0]%/*}"; [ "$_bpd" != "${BASH_SOURCE[0]}" ] || _bpd=. # dirname without a process
if [ -f "$_bpd/_common.sh" ]; then
# shellcheck disable=SC1091
. "$(dirname "${BASH_SOURCE[0]}")/_common.sh"
. "$_bpd/_common.sh"
fi
if ! type resolve_py >/dev/null 2>&1; then
resolve_py() {
Expand Down Expand Up @@ -532,7 +542,7 @@ render_plan_section() { # stdout: the plan section's HTML
echo "<h2>The plan</h2><p class=empty>Nothing to show yet: ${PLAN_MSG:-build-plan.md was not read}.</p>"
return 0
fi
"$PY" - "$PLAN_JSON" "$MDLSOURCE" "${PHASE_DETAIL:-/dev/null}" "$ROOT" "$(dirname "${BASH_SOURCE[0]}")/progress-report.py" <<'PYEOF' || echo "<h2>The plan</h2><p class=empty>Could not render the plan section from build-plan.md.</p>"
"$PY" - "$PLAN_JSON" "$MDLSOURCE" "${PHASE_DETAIL:-/dev/null}" "$ROOT" "${_bpd:-$(dirname "${BASH_SOURCE[0]}")}/progress-report.py" <<'PYEOF' || echo "<h2>The plan</h2><p class=empty>Could not render the plan section from build-plan.md.</p>"
import fnmatch, html, json, os, re, sys

src, mdl, detail_out, proj, gen = sys.argv[1:6]
Expand Down Expand Up @@ -709,7 +719,7 @@ PYEOF
# architecture/build-plan.html is left exactly where it is: not read, not rewritten, not deleted.
if [ "$WRITE_HTML" -eq 1 ]; then
SKIP_HTML=""
GEN="$(dirname "${BASH_SOURCE[0]}")/progress-report.py"
GEN="${_bpd:-$(dirname "${BASH_SOURCE[0]}")}/progress-report.py"
report_name
OUT="$ROOT/architecture/$REPORT_FILE"
SETTING="$(progress_report_setting)"
Expand Down
Loading
Loading