@manhquy/flow-skill 0.4.1 → 0.5.0

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.
@@ -16,7 +16,7 @@
16
16
 
17
17
  set -u
18
18
 
19
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
19
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
20
20
  TEMPLATE_DIR="$SCRIPT_DIR/../_templates"
21
21
  LAW_DIR="$SCRIPT_DIR/../law"
22
22
  PLAYBOOKS_DIR="$SCRIPT_DIR/../playbooks"
@@ -59,6 +59,10 @@ LOCK_FILE="$ROOT/flow/.lock"
59
59
  LOCK_DIR="$ROOT/flow/.lock.d" # atomic mkdir claim dir (W5 guard); winner then writes $LOCK_FILE metadata
60
60
  HARNESS_PY="$SCRIPT_DIR/../harness/flow_harness.py"
61
61
 
62
+ # Attestations library (risk, receipts, auto policy) — optional-soft: missing file is fatal for v0.28+.
63
+ # shellcheck source=attestations.sh
64
+ . "$SCRIPT_DIR/attestations.sh"
65
+
62
66
  # Eval (LLM semantic-gate behavioral harness; opt-in, billable - see 'eval' command).
63
67
  # FLOW_EVAL_MANIFEST is a TEST-ONLY override (e.g. a synthetic CRLF manifest fixture) - it does
64
68
  # NOT widen the v1 trust boundary: artifact paths still resolve as $EVAL_DIR/fixtures/<id>/<rel>,
@@ -740,6 +744,8 @@ cmd_status() {
740
744
  echo " project: $ROOT"
741
745
  echo " mode: $(cat "$MODE_FILE" 2>/dev/null | tr -d '\r' || echo teach) (default teach)"
742
746
  echo " type: $(get_project_type) (done = $(done_def_for_type "$(get_project_type)"))"
747
+ local _ast; _ast="$(_att_auto_state_read 2>/dev/null || echo INACTIVE)"
748
+ echo " auto: $_ast$([ "$_ast" = ACTIVE ] && echo " (receipts enforced)" || true)"
743
749
  lock_warn
744
750
  echo
745
751
  echo "NEXT -> $(_next_action)"
@@ -845,11 +851,16 @@ cmd_resume() {
845
851
 
846
852
  echo "flow resume"
847
853
  echo " project: $ROOT"
854
+ local _ast; _ast="$(_att_auto_state_read 2>/dev/null || echo INACTIVE)"
855
+ echo " auto: $_ast"
848
856
  echo
849
857
 
850
858
  if [ ! -s "$EVENTS_FILE" ]; then
851
859
  echo "no telemetry - showing gate state only"
852
860
  echo
861
+ local _ast; _ast="$(_att_auto_state_read 2>/dev/null || echo INACTIVE)"
862
+ echo "auto: $_ast"
863
+ echo
853
864
  _gate_state_brief "$idx"
854
865
  echo
855
866
  echo "NEXT -> $(_next_action)"
@@ -949,6 +960,21 @@ cmd_resume() {
949
960
 
950
961
  cmd_next() {
951
962
  lock_acquire next || return 1
963
+ # v0.28: warning-only stage semantic receipt guidance (never hard-blocks next)
964
+ if _att_git_ok 2>/dev/null; then
965
+ local _cur_stage _rp _st
966
+ _cur_stage="$(stage_name_at "$(current_stage_idx)" 2>/dev/null || true)"
967
+ if [ -n "$_cur_stage" ] && _att_is_stage "$_cur_stage" 2>/dev/null; then
968
+ _rp="$(_att_receipt_path semantic_gate stage "$_cur_stage" 2>/dev/null || true)"
969
+ if [ -n "$_rp" ]; then
970
+ _st="$(_att_receipt_status "$_rp" 2>/dev/null || echo missing)"
971
+ case "$_st" in
972
+ current) : ;;
973
+ *) echo "WARNING: stage $_cur_stage semantic receipt is $_st (auto will require a current pass; see references/attestations.md)" ;;
974
+ esac
975
+ fi
976
+ fi
977
+ fi
952
978
  local idx; idx="$(current_stage_idx)"
953
979
  if [ "$idx" -lt 0 ]; then
954
980
  mkdir -p "$FLOW_DIR"
@@ -1171,17 +1197,63 @@ cmd_card_done() { # CLI-owned flip to done, gated by the SAME done-rules as '/fl
1171
1197
  if [ -z "$file" ] || [ ! -f "$file" ]; then echo "FAIL: card not found for '$arg' (looked for ${file:-?})"; return 1; fi
1172
1198
  local id orig; id="$(basename "$file" .md)"; FLOW_LOG_CARD="$id"; orig="$(card_status "$file")"
1173
1199
  if [ -z "$orig" ]; then echo "FAIL: $id has no 'status:' line — run '/flow check $id' to see what's missing."; return 1; fi
1200
+
1201
+ # Attested auto: validate receipts BEFORE status mutation; integration-checkout owned.
1202
+ local enforce=0
1203
+ if _att_auto_is_enforcing; then
1204
+ enforce=1
1205
+ if ! _att_is_main_worktree; then
1206
+ local mainp; mainp="$(_att_main_worktree_path)"
1207
+ echo "FAIL: active auto card done is integration-checkout owned."
1208
+ echo " cd ${mainp:-<main>} && bash <skill>/runner/flow.sh card done $id"
1209
+ return 1
1210
+ fi
1211
+ _att_auto_lock_acquire || return 1
1212
+ local lname; lname="$(_att_subject_lock_name semantic_gate "$id")"
1213
+ local lname2; lname2="$(_att_subject_lock_name live_verify "$id")"
1214
+ _att_lock_acquire "$lname" || { _att_auto_lock_release; return 1; }
1215
+ _att_lock_acquire "$lname2" || { _att_lock_release "$lname"; _att_auto_lock_release; return 1; }
1216
+ if ! _att_enforce_card "$id" 1 1; then
1217
+ _att_lock_release "$lname2"; _att_lock_release "$lname"; _att_auto_lock_release
1218
+ return 1
1219
+ fi
1220
+ # prospective done evidence without mutating status
1221
+ if ! {
1222
+ local st0; st0="$(card_status "$file")"
1223
+ # temporary view: require verify boxes + evidence as if done
1224
+ if grep -qE '^[[:space:]]*- \[ \]' "$file" 2>/dev/null; then
1225
+ echo "FAIL: Verify has unchecked boxes"; false
1226
+ elif grep -q '\[FILL' "$file" 2>/dev/null; then
1227
+ echo "FAIL: unfilled [FILL]"; false
1228
+ else
1229
+ local ev score
1230
+ ev="$(_evidence_body "$file")"
1231
+ if _evidence_is_empty "$ev"; then echo "FAIL: empty Evidence"; false
1232
+ else
1233
+ score="$(_evidence_signal_score "$ev" "${FLOW_PROJECT_ROOT:-$PWD}")"
1234
+ [ "$score" -ge 2 ] || { echo "FAIL: Evidence multi-signal floor ($score/2)"; false; }
1235
+ fi
1236
+ fi
1237
+ }; then
1238
+ _att_lock_release "$lname2"; _att_lock_release "$lname"; _att_auto_lock_release
1239
+ echo "FAIL: $id prospective done-evidence gate failed (status unchanged)."
1240
+ return 1
1241
+ fi
1242
+ fi
1243
+
1174
1244
  # On INT/TERM after flip-to-done: restore todo and abort (fail-closed). Never continue
1175
1245
  # into durable complete after a partial restore.
1176
1246
  # shellcheck disable=SC2064
1177
1247
  trap '_set_card_status "'"$file"'" "todo" 2>/dev/null || true; trap - INT TERM; exit 130' INT TERM
1178
1248
  if ! _set_card_status "$file" done; then
1179
1249
  trap - INT TERM
1250
+ [ "$enforce" = "1" ] && { _att_lock_release "$lname2"; _att_lock_release "$lname"; _att_auto_lock_release; }
1180
1251
  echo "FAIL: could not write status for $id"
1181
1252
  return 1
1182
1253
  fi
1183
1254
  if cmd_check "$id"; then # cmd_check enforces evidence/verify AND records the durable done-trace
1184
1255
  trap - INT TERM
1256
+ [ "$enforce" = "1" ] && { _att_lock_release "$lname2"; _att_lock_release "$lname"; _att_auto_lock_release; }
1185
1257
  _inflight_clear "$id"
1186
1258
  # card-verify-live: the done boundary is the EVIDENCE gate passing, not the merge
1187
1259
  # (merge != shipped) - dependents unblock on card status, matching cmd_ready.
@@ -1190,6 +1262,7 @@ cmd_card_done() { # CLI-owned flip to done, gated by the SAME done-rules as '/fl
1190
1262
  return 0
1191
1263
  fi
1192
1264
  trap - INT TERM
1265
+ [ "$enforce" = "1" ] && { _att_lock_release "$lname2"; _att_lock_release "$lname"; _att_auto_lock_release; }
1193
1266
  # Always force todo on gate fail (even if orig was hollow done) — never leave hollow done.
1194
1267
  _set_card_status "$file" todo
1195
1268
  echo
@@ -1432,6 +1505,22 @@ cmd_check() {
1432
1505
  fi
1433
1506
  fi
1434
1507
 
1508
+ # Attestation: warn when inactive; hard-require when auto active/stale/invalid
1509
+ local need_live=0 enforce=0
1510
+ [ "$st" = "done" ] && need_live=1
1511
+ if _att_auto_is_enforcing; then enforce=1; fi
1512
+ if ! _att_enforce_card "$id" "$need_live" "$enforce"; then
1513
+ found=1
1514
+ fi
1515
+ # risk advisory (manual)
1516
+ if [ "$enforce" != "1" ]; then
1517
+ local rv; rv="$(_card_risk_validate "$file" manual 2>/dev/null || echo invalid)"
1518
+ case "$rv" in
1519
+ unknown) echo " note: risk=unknown — classify before /flow auto" ;;
1520
+ invalid:*) echo " note: risk metadata invalid ($rv)" ;;
1521
+ esac
1522
+ fi
1523
+
1435
1524
  if [ "$found" -eq 0 ]; then
1436
1525
  echo "PASS: $id is valid (status: $st)."
1437
1526
  # card-review boundary: the gate verdict IS the evidence the executor records
@@ -1612,6 +1701,7 @@ cmd_ready() {
1612
1701
  echo "FAIL: planning not complete - no cards to schedule yet."
1613
1702
  return 1
1614
1703
  fi
1704
+ local any_buildable=0
1615
1705
  local total; total="$(highest_card)"
1616
1706
  if [ "$total" -le 0 ]; then echo "No cards created yet. Run '/flow card'."; return 0; fi
1617
1707
  echo "flow ready - buildable todo cards (deps met). Operator dispatches; runner advises."
@@ -1637,34 +1727,112 @@ cmd_ready() {
1637
1727
  elif ! _card_done_evidence_ok "$depfile"; then
1638
1728
  ok=0
1639
1729
  echo " note: dep $(basename "$depfile" .md) is status=done but ## Evidence fails world-state signal (re-check or paste real proof)"
1730
+ elif _att_auto_is_enforcing; then
1731
+ depid="$(basename "$depfile" .md)"
1732
+ if ! _att_accepted_semantic card "$depid" || ! _att_accepted_live "$depid"; then
1733
+ ok=0
1734
+ echo " note: dep $depid missing current semantic/live receipts (auto active)"
1735
+ fi
1640
1736
  fi
1641
1737
  done
1642
1738
  if [ "$ok" -eq 1 ]; then
1643
1739
  echo " BUILDABLE $id (deps: ${deps:-none})"
1644
1740
  _card_allowed_files "$f" | sed 's/^/ allowed: /'
1741
+ any_buildable=1
1645
1742
  else
1646
1743
  echo " blocked $id (deps unmet or evidence floor failed: ${deps:-none})"
1647
1744
  fi
1648
1745
  done
1746
+ # Auto-active: if any todo cards exist but none are buildable, exit non-zero so
1747
+ # automation cannot treat a fully receipt-blocked graph as green.
1748
+ if _att_auto_is_enforcing; then
1749
+ local any_todo=0
1750
+ for f in "$CARDS_DIR"/C-*.md; do
1751
+ [ -e "$f" ] || continue
1752
+ [ "$(card_status "$f")" = "todo" ] && any_todo=1
1753
+ done
1754
+ if [ "${any_todo:-0}" -eq 1 ] && [ "${any_buildable:-0}" -eq 0 ]; then
1755
+ return 1
1756
+ fi
1757
+ fi
1649
1758
  return 0
1650
1759
  }
1651
1760
 
1652
1761
  cmd_auto() {
1762
+ # flow auto [stop] — activate/refresh attested auto policy, or clear it
1763
+ local sub="${1:-}"
1764
+ if [ "$sub" = "stop" ]; then
1765
+ if [ -n "${2:-}" ]; then echo "usage: /flow auto stop"; return 2; fi
1766
+ _att_auto_lock_acquire || return 1
1767
+ _att_auto_clear
1768
+ _att_auto_lock_release
1769
+ echo "PASS: auto state cleared (manual warning-only mode)."
1770
+ return 0
1771
+ fi
1772
+ if [ -n "$sub" ]; then echo "usage: /flow auto | /flow auto stop"; return 2; fi
1773
+
1653
1774
  lock_acquire auto || return 1
1654
- echo "flow auto - preflight"
1775
+ _att_auto_lock_acquire || return 1
1776
+ echo "flow auto - preflight (attested execution)"
1777
+
1778
+ if ! _att_git_ok; then
1779
+ echo "FAIL: /flow auto requires a Git repository."; _att_auto_lock_release; return 1
1780
+ fi
1781
+ if ! _att_is_main_worktree; then
1782
+ local mainp; mainp="$(_att_main_worktree_path)"
1783
+ echo "FAIL: activate auto only from the main worktree (not a linked/detached checkout)."
1784
+ echo " cd ${mainp:-<main>} && FLOW_PROJECT_ROOT=${mainp:-} bash <skill>/runner/flow.sh auto"
1785
+ _att_auto_lock_release; return 1
1786
+ fi
1787
+ local br; br="$(git -C "$ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\r')"
1788
+ if [ -z "$br" ] || [ "$br" = "HEAD" ]; then
1789
+ echo "FAIL: detached HEAD — checkout an integration branch first."
1790
+ _att_auto_lock_release; return 1
1791
+ fi
1792
+ if ! _att_supervisor_capable; then
1793
+ echo "FAIL: reliable process-group supervisor unavailable — live auto refused on this platform."
1794
+ _att_auto_lock_release; return 1
1795
+ fi
1655
1796
  if ! planning_complete; then
1656
1797
  echo "FAIL: planning not complete. Finish stages 00-05 first."
1657
- return 1
1798
+ _att_auto_lock_release; return 1
1658
1799
  fi
1659
1800
  if [ "$(highest_card)" -le 0 ]; then
1660
1801
  echo "FAIL: no cards. Run '/flow card' to create the build cards first."
1661
- return 1
1662
- fi
1663
- echo "PASS: preflight ok ($(highest_card) cards, planning complete)."
1802
+ _att_auto_lock_release; return 1
1803
+ fi
1804
+
1805
+ echo "--- risk set ---"
1806
+ if ! _att_risk_preflight; then
1807
+ echo "FAIL: risk preflight blocked activation (classify every card; security-class needs DEBT ack)."
1808
+ _att_auto_lock_release; return 1
1809
+ fi
1810
+
1811
+ echo "--- Stage 05 semantic receipt ---"
1812
+ if ! _att_accepted_semantic stage 05-contract; then
1813
+ echo "FAIL: need current accepted semantic_gate receipt for 05-contract."
1814
+ echo " mint: flow attest semantic --stage 05-contract --revision HEAD --owner <committed-manifest>"
1815
+ _att_auto_lock_release; return 1
1816
+ fi
1817
+ local cfp; cfp="$_ATT_R_subject_fingerprint"
1818
+ local rfp; rfp="$(_att_risk_fingerprint)"
1819
+ local by; by="$(_att_sanitize_label "${FLOW_SESSION_ID:-session}")"
1820
+ [ -n "$by" ] || by="session"
1821
+ _ATT_W_activated_at="$(_att_now_rfc3339)"
1822
+ _ATT_W_activated_by="$by"
1823
+ _ATT_W_integration_branch="$br"
1824
+ _ATT_W_risk_fingerprint="$rfp"
1825
+ _ATT_W_contract_fingerprint="$cfp"
1826
+ if ! _att_auto_write; then
1827
+ echo "FAIL: could not write auto-state"
1828
+ _att_auto_lock_release; return 1
1829
+ fi
1830
+ _att_auto_lock_release
1831
+ echo "PASS: auto ACTIVE on branch '$br' ($(highest_card) cards)."
1832
+ echo " check/card done/ready/merged workspace remove now require current receipts."
1833
+ echo " stop: /flow auto stop"
1664
1834
  echo
1665
- echo "Autonomous orchestration is driven by the /flow SKILL.md AUTO PRINCIPLES"
1666
- echo "(subagent per card, planner review + verify, worktree isolation, Tier-C halts"
1667
- echo "for security-class debt, state in card files + AUTO-LOG.md)."
1835
+ echo "Orchestration remains skill-driven (AUTO principles); receipts are the mechanical trust floor."
1668
1836
  echo "Run '/flow ready' to see parallel-safe groups."
1669
1837
  return 0
1670
1838
  }
@@ -2401,16 +2569,17 @@ _ws_enter() {
2401
2569
  }
2402
2570
 
2403
2571
  _ws_remove() {
2404
- local branch="" force=0
2572
+ local branch="" force=0 card_arg=""
2405
2573
  while [ $# -gt 0 ]; do
2406
2574
  case "$1" in
2407
2575
  --force) force=1 ;;
2576
+ --card) shift; card_arg="${1:-}" ;;
2408
2577
  --*) echo "workspace remove: unknown arg '$1'"; return 1 ;;
2409
2578
  *) [ -z "$branch" ] && branch="$1" || { echo "workspace remove: extra arg '$1'"; return 1; } ;;
2410
2579
  esac
2411
2580
  shift
2412
2581
  done
2413
- [ -n "$branch" ] || { echo "usage: /flow workspace remove <branch> [--force]"; return 1; }
2582
+ [ -n "$branch" ] || { echo "usage: /flow workspace remove <branch> [--force] [--card C-NNN]"; return 1; }
2414
2583
  lock_acquire workspace || return 1
2415
2584
  local rec wt rmout rc
2416
2585
  rec="$(_ws_latest_by_branch "$branch")"
@@ -2423,6 +2592,30 @@ _ws_remove() {
2423
2592
  # remove never journals a merge for a card still under active work.
2424
2593
  local _gcard _gcreated
2425
2594
  _gcard="$(_ws_get "$rec" card_id)"; _gcreated="$(_ws_get_num "$rec" created_at)"
2595
+ # Attested auto: merged worktrees require semantic+live receipts for mapped card
2596
+ if _att_auto_is_enforcing && _att_git_ok; then
2597
+ local tip head_oid card_id merged=0
2598
+ tip="$(git -C "$wt" rev-parse HEAD 2>/dev/null | tr -d '\r')"
2599
+ head_oid="$(_att_full_commit HEAD)"
2600
+ if [ -n "$tip" ] && [ -n "$head_oid" ] && { [ "$tip" = "$head_oid" ] || _att_is_ancestor "$tip" "$head_oid"; }; then
2601
+ merged=1
2602
+ fi
2603
+ if [ "$merged" -eq 1 ]; then
2604
+ card_id="$card_arg"
2605
+ [ -n "$card_id" ] || card_id="$(_ws_get "$rec" card_id)"
2606
+ card_id="$(printf '%s' "$card_id" | tr -d '\r')"
2607
+ if [ -z "$card_id" ] || [ "$card_id" = "null" ] || [ "$card_id" = "none" ]; then
2608
+ echo "FAIL: auto-active merged remove needs card identity (registry or --card C-NNN)."
2609
+ return 1
2610
+ fi
2611
+ card_id="$(_att_norm_card_id "$card_id")" || { echo "FAIL: bad --card"; return 1; }
2612
+ if ! _att_accepted_semantic card "$card_id" || ! _att_accepted_live "$card_id"; then
2613
+ echo "FAIL: merged worktree remove blocked — card $card_id needs current semantic+live receipts (or /flow auto stop)."
2614
+ return 1
2615
+ fi
2616
+ fi
2617
+ fi
2618
+
2426
2619
  if _graph_on && [ -f "$wt/.flow/events.jsonl" ]; then
2427
2620
  # Lifecycle-unique key: worktree paths are recycled, so a bare-path cursor would
2428
2621
  # swallow the next lifecycle's lines. Prefix = destination sink (usage/prune group it).
@@ -3549,13 +3742,13 @@ function cmd_eval {
3549
3742
  --timeout) shift; timeout="${1:-120}" ;;
3550
3743
  --report) report_mode=1 ;;
3551
3744
  --keep-going) keep_going=1 ;;
3552
- *) echo "usage: /flow eval [--stage 01|02|card|routing] [--fixture <id>] [--n 3] [--timeout <seconds>] [--keep-going] [--report]"; return 1 ;;
3745
+ *) echo "usage: /flow eval [--stage 01|02|05|card|routing] [--fixture <id>] [--n 3] [--timeout <seconds>] [--keep-going] [--report]"; return 1 ;;
3553
3746
  esac
3554
3747
  shift 2>/dev/null || true
3555
3748
  done
3556
3749
  case "$n" in ''|*[!0-9]*|0) echo "eval: --n must be a positive integer (got '$n')"; return 1 ;; esac
3557
3750
  case "$timeout" in ''|*[!0-9]*|0) echo "eval: --timeout must be a positive integer seconds value (got '$timeout')"; return 1 ;; esac
3558
- case "$stage_filter" in ""|01|02|card|routing) : ;; *) echo "eval: --stage must be one of 01|02|card|routing (got '$stage_filter')"; return 1 ;; esac
3751
+ case "$stage_filter" in ""|01|02|05|card|routing) : ;; *) echo "eval: --stage must be one of 01|02|05|card|routing (got '$stage_filter')"; return 1 ;; esac
3559
3752
  # Backoff between the in-run retry attempts. Default 5s; tests set 0 so the mock-suite is not
3560
3753
  # slowed by 15s+ per degraded-path case across 3-OS CI. Bare-int validation only - a bogus
3561
3754
  # value (`abc`) silently falls back to the default rather than aborting the batch.
@@ -3880,7 +4073,8 @@ usage: bash flow.sh <command> [args]
3880
4073
  workspace <verb> Multi-agent worktree isolation: add|list|enter|remove|check|doctor (one worktree per agent)
3881
4074
  loop-prep <card> Plumbing for ck-loop: isolated worktree + numeric Verify command + param block (thin wrapper; ck-loop is the engine)
3882
4075
  loop-log <card> Record a finished ck-loop run (iterations/start/end/outcome) into usage-log telemetry
3883
- auto Preflight an autonomous run (orchestration in SKILL.md)
4076
+ auto [stop] Activate attested auto (risk + Stage 05 receipt) or stop
4077
+ attest <verb> Mint/status/recover attestation receipts (semantic|live-verify|status|recover)
3884
4078
  recall Read back prior knowledge (debt/retro/playbooks/prev-card/harness) before working
3885
4079
  unlock Clear this project's concurrency lock (after a crashed/abandoned session)
3886
4080
  harness <args> Passthrough to the durable layer CLI (intake/story/trace/decision/backlog/query)
@@ -3895,7 +4089,7 @@ usage: bash flow.sh <command> [args]
3895
4089
  doctor Check the environment (bash/python/grep/git) across macOS/Linux/Windows
3896
4090
  eval [opts] Behavioral eval: does the LLM semantic gate flag a hollow-but-mechanically-clean
3897
4091
  fixture? Opt-in, BILLABLE (skips cleanly with zero calls if 'claude' CLI absent).
3898
- [--stage 01|02|card|routing] [--fixture <id>] [--n 3] [--timeout <seconds>]
4092
+ [--stage 01|02|05|card|routing] [--fixture <id>] [--n 3] [--timeout <seconds>]
3899
4093
  [--report] offline: last complete batch's scorecard + drift, zero calls
3900
4094
  --stage routing: SEPARATE judge (concierge routing, not gate-rules FLAG/PASS);
3901
4095
  hard-capped at 90 calls/batch, own results stream, own --report
@@ -4054,6 +4248,17 @@ cmd="${1:-status}"
4054
4248
  shift 2>/dev/null || true
4055
4249
  FLOW_LOG_CMD="$cmd"
4056
4250
  FLOW_LOG_ARGS="$*"
4251
+ # Attestation privacy: never persist full argv (owner paths / potential secrets).
4252
+ if [ "$cmd" = "attest" ]; then
4253
+ _att_sub="${1:-}"
4254
+ _att_subj=""
4255
+ case "$_att_sub" in
4256
+ semantic|live-verify|status|recover) _att_subj="${2:-}" ;;
4257
+ esac
4258
+ # strip flag-like tokens from subject slot
4259
+ case "$_att_subj" in --*) _att_subj="" ;; esac
4260
+ FLOW_LOG_ARGS="${_att_sub}${_att_subj:+ ${_att_subj}}"
4261
+ fi
4057
4262
  FLOW_LOG_START="$(_now)"
4058
4263
  trap '_log_on_exit' EXIT
4059
4264
  case "$cmd" in
@@ -4071,7 +4276,8 @@ case "$cmd" in
4071
4276
  workspace) cmd_workspace "$@" ;;
4072
4277
  loop-prep) cmd_loop_prep "$@" ;;
4073
4278
  loop-log) cmd_loop_log "$@" ;;
4074
- auto) cmd_auto ;;
4279
+ auto) cmd_auto "$@" ;;
4280
+ attest) cmd_attest "$@" ;;
4075
4281
  recall) cmd_recall ;;
4076
4282
  unlock) cmd_unlock ;;
4077
4283
  retro) cmd_retro ;;
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "source": "../skills/flow",
3
3
  "destRelative": "skills/flow",
4
- "fileCount": 84,
5
- "syncedAt": "2026-08-11T08:09:29.734Z",
4
+ "fileCount": 88,
5
+ "syncedAt": "2026-08-11T12:32:58.107Z",
6
6
  "fileList": [
7
7
  "SKILL.md",
8
8
  "_templates/00-idea.md",
@@ -18,6 +18,8 @@
18
18
  "eval/fixtures/f01b/flow/01-research.md",
19
19
  "eval/fixtures/f02a/flow/02-scope.md",
20
20
  "eval/fixtures/f02b/flow/02-scope.md",
21
+ "eval/fixtures/f05a/flow/05-contract.md",
22
+ "eval/fixtures/f05b/flow/05-contract.md",
21
23
  "eval/fixtures/fcda/.flow/.gitkeep",
22
24
  "eval/fixtures/fcda/cards/C-001.md",
23
25
  "eval/fixtures/fcdb/.flow/.gitkeep",
@@ -67,6 +69,7 @@
67
69
  "references/agent-detection.md",
68
70
  "references/agent-stage-mapping.md",
69
71
  "references/antigravity-integration.md",
72
+ "references/attestations.md",
70
73
  "references/auto-run.md",
71
74
  "references/claudekit-skills.md",
72
75
  "references/codex-integration.md",
@@ -86,6 +89,7 @@
86
89
  "references/project-types.md",
87
90
  "references/stage-state-machine.md",
88
91
  "references/ui-patterns-tcr.md",
92
+ "runner/attestations.sh",
89
93
  "runner/flow.cmd",
90
94
  "runner/flow.sh"
91
95
  ]