@manhquy/flow-skill 0.4.1 → 0.5.1
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.
- package/CHANGELOG.md +5 -0
- package/README.md +5 -5
- package/README_VN.md +61 -36
- package/package.json +1 -1
- package/skills/flow/SKILL.md +14 -8
- package/skills/flow/_templates/card.md +3 -0
- package/skills/flow/eval/fixtures/f05a/flow/05-contract.md +22 -0
- package/skills/flow/eval/fixtures/f05b/flow/05-contract.md +11 -0
- package/skills/flow/eval/manifest.tsv +2 -0
- package/skills/flow/references/attestations.md +307 -0
- package/skills/flow/references/auto-run.md +7 -2
- package/skills/flow/references/command-dispatch.md +3 -1
- package/skills/flow/references/concierge.md +1 -0
- package/skills/flow/references/debt-and-halts.md +2 -0
- package/skills/flow/references/ground-truth-gates.md +3 -0
- package/skills/flow/runner/attestations.sh +1433 -0
- package/skills/flow/runner/flow.sh +227 -16
- package/skills-manifest.json +6 -2
|
@@ -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,117 @@ 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
|
-
|
|
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
|
-
|
|
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
|
+
# Cleanliness last among preflight diagnostics so risk/receipt messages still print.
|
|
1818
|
+
if ! _att_require_clean_for_consume; then
|
|
1819
|
+
echo "FAIL: dirty worktree — auto activation requires clean tree (except .flow/, locks, status/Evidence)."
|
|
1820
|
+
_att_auto_lock_release; return 1
|
|
1821
|
+
fi
|
|
1822
|
+
local cfp; cfp="$_ATT_R_subject_fingerprint"
|
|
1823
|
+
local rfp; rfp="$(_att_risk_fingerprint)"
|
|
1824
|
+
local by; by="$(_att_sanitize_label "${FLOW_SESSION_ID:-session}")"
|
|
1825
|
+
[ -n "$by" ] || by="session"
|
|
1826
|
+
_ATT_W_activated_at="$(_att_now_rfc3339)"
|
|
1827
|
+
_ATT_W_activated_by="$by"
|
|
1828
|
+
_ATT_W_integration_branch="$br"
|
|
1829
|
+
_ATT_W_risk_fingerprint="$rfp"
|
|
1830
|
+
_ATT_W_contract_fingerprint="$cfp"
|
|
1831
|
+
if ! _att_auto_write; then
|
|
1832
|
+
echo "FAIL: could not write auto-state"
|
|
1833
|
+
_att_auto_lock_release; return 1
|
|
1834
|
+
fi
|
|
1835
|
+
_att_auto_lock_release
|
|
1836
|
+
echo "PASS: auto ACTIVE on branch '$br' ($(highest_card) cards)."
|
|
1837
|
+
echo " check/card done/ready/merged workspace remove now require current receipts."
|
|
1838
|
+
echo " stop: /flow auto stop"
|
|
1664
1839
|
echo
|
|
1665
|
-
echo "
|
|
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)."
|
|
1840
|
+
echo "Orchestration remains skill-driven (AUTO principles); receipts are the mechanical trust floor."
|
|
1668
1841
|
echo "Run '/flow ready' to see parallel-safe groups."
|
|
1669
1842
|
return 0
|
|
1670
1843
|
}
|
|
@@ -2401,16 +2574,17 @@ _ws_enter() {
|
|
|
2401
2574
|
}
|
|
2402
2575
|
|
|
2403
2576
|
_ws_remove() {
|
|
2404
|
-
local branch="" force=0
|
|
2577
|
+
local branch="" force=0 card_arg=""
|
|
2405
2578
|
while [ $# -gt 0 ]; do
|
|
2406
2579
|
case "$1" in
|
|
2407
2580
|
--force) force=1 ;;
|
|
2581
|
+
--card) shift; card_arg="${1:-}" ;;
|
|
2408
2582
|
--*) echo "workspace remove: unknown arg '$1'"; return 1 ;;
|
|
2409
2583
|
*) [ -z "$branch" ] && branch="$1" || { echo "workspace remove: extra arg '$1'"; return 1; } ;;
|
|
2410
2584
|
esac
|
|
2411
2585
|
shift
|
|
2412
2586
|
done
|
|
2413
|
-
[ -n "$branch" ] || { echo "usage: /flow workspace remove <branch> [--force]"; return 1; }
|
|
2587
|
+
[ -n "$branch" ] || { echo "usage: /flow workspace remove <branch> [--force] [--card C-NNN]"; return 1; }
|
|
2414
2588
|
lock_acquire workspace || return 1
|
|
2415
2589
|
local rec wt rmout rc
|
|
2416
2590
|
rec="$(_ws_latest_by_branch "$branch")"
|
|
@@ -2423,6 +2597,30 @@ _ws_remove() {
|
|
|
2423
2597
|
# remove never journals a merge for a card still under active work.
|
|
2424
2598
|
local _gcard _gcreated
|
|
2425
2599
|
_gcard="$(_ws_get "$rec" card_id)"; _gcreated="$(_ws_get_num "$rec" created_at)"
|
|
2600
|
+
# Attested auto: merged worktrees require semantic+live receipts for mapped card
|
|
2601
|
+
if _att_auto_is_enforcing && _att_git_ok; then
|
|
2602
|
+
local tip head_oid card_id merged=0
|
|
2603
|
+
tip="$(git -C "$wt" rev-parse HEAD 2>/dev/null | tr -d '\r')"
|
|
2604
|
+
head_oid="$(_att_full_commit HEAD)"
|
|
2605
|
+
if [ -n "$tip" ] && [ -n "$head_oid" ] && { [ "$tip" = "$head_oid" ] || _att_is_ancestor "$tip" "$head_oid"; }; then
|
|
2606
|
+
merged=1
|
|
2607
|
+
fi
|
|
2608
|
+
if [ "$merged" -eq 1 ]; then
|
|
2609
|
+
card_id="$card_arg"
|
|
2610
|
+
[ -n "$card_id" ] || card_id="$(_ws_get "$rec" card_id)"
|
|
2611
|
+
card_id="$(printf '%s' "$card_id" | tr -d '\r')"
|
|
2612
|
+
if [ -z "$card_id" ] || [ "$card_id" = "null" ] || [ "$card_id" = "none" ]; then
|
|
2613
|
+
echo "FAIL: auto-active merged remove needs card identity (registry or --card C-NNN)."
|
|
2614
|
+
return 1
|
|
2615
|
+
fi
|
|
2616
|
+
card_id="$(_att_norm_card_id "$card_id")" || { echo "FAIL: bad --card"; return 1; }
|
|
2617
|
+
if ! _att_accepted_semantic card "$card_id" || ! _att_accepted_live "$card_id"; then
|
|
2618
|
+
echo "FAIL: merged worktree remove blocked — card $card_id needs current semantic+live receipts (or /flow auto stop)."
|
|
2619
|
+
return 1
|
|
2620
|
+
fi
|
|
2621
|
+
fi
|
|
2622
|
+
fi
|
|
2623
|
+
|
|
2426
2624
|
if _graph_on && [ -f "$wt/.flow/events.jsonl" ]; then
|
|
2427
2625
|
# Lifecycle-unique key: worktree paths are recycled, so a bare-path cursor would
|
|
2428
2626
|
# swallow the next lifecycle's lines. Prefix = destination sink (usage/prune group it).
|
|
@@ -3549,13 +3747,13 @@ function cmd_eval {
|
|
|
3549
3747
|
--timeout) shift; timeout="${1:-120}" ;;
|
|
3550
3748
|
--report) report_mode=1 ;;
|
|
3551
3749
|
--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 ;;
|
|
3750
|
+
*) echo "usage: /flow eval [--stage 01|02|05|card|routing] [--fixture <id>] [--n 3] [--timeout <seconds>] [--keep-going] [--report]"; return 1 ;;
|
|
3553
3751
|
esac
|
|
3554
3752
|
shift 2>/dev/null || true
|
|
3555
3753
|
done
|
|
3556
3754
|
case "$n" in ''|*[!0-9]*|0) echo "eval: --n must be a positive integer (got '$n')"; return 1 ;; esac
|
|
3557
3755
|
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
|
|
3756
|
+
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
3757
|
# Backoff between the in-run retry attempts. Default 5s; tests set 0 so the mock-suite is not
|
|
3560
3758
|
# slowed by 15s+ per degraded-path case across 3-OS CI. Bare-int validation only - a bogus
|
|
3561
3759
|
# value (`abc`) silently falls back to the default rather than aborting the batch.
|
|
@@ -3880,7 +4078,8 @@ usage: bash flow.sh <command> [args]
|
|
|
3880
4078
|
workspace <verb> Multi-agent worktree isolation: add|list|enter|remove|check|doctor (one worktree per agent)
|
|
3881
4079
|
loop-prep <card> Plumbing for ck-loop: isolated worktree + numeric Verify command + param block (thin wrapper; ck-loop is the engine)
|
|
3882
4080
|
loop-log <card> Record a finished ck-loop run (iterations/start/end/outcome) into usage-log telemetry
|
|
3883
|
-
auto
|
|
4081
|
+
auto [stop] Activate attested auto (risk + Stage 05 receipt) or stop
|
|
4082
|
+
attest <verb> Mint/status/recover attestation receipts (semantic|live-verify|status|recover)
|
|
3884
4083
|
recall Read back prior knowledge (debt/retro/playbooks/prev-card/harness) before working
|
|
3885
4084
|
unlock Clear this project's concurrency lock (after a crashed/abandoned session)
|
|
3886
4085
|
harness <args> Passthrough to the durable layer CLI (intake/story/trace/decision/backlog/query)
|
|
@@ -3895,7 +4094,7 @@ usage: bash flow.sh <command> [args]
|
|
|
3895
4094
|
doctor Check the environment (bash/python/grep/git) across macOS/Linux/Windows
|
|
3896
4095
|
eval [opts] Behavioral eval: does the LLM semantic gate flag a hollow-but-mechanically-clean
|
|
3897
4096
|
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>]
|
|
4097
|
+
[--stage 01|02|05|card|routing] [--fixture <id>] [--n 3] [--timeout <seconds>]
|
|
3899
4098
|
[--report] offline: last complete batch's scorecard + drift, zero calls
|
|
3900
4099
|
--stage routing: SEPARATE judge (concierge routing, not gate-rules FLAG/PASS);
|
|
3901
4100
|
hard-capped at 90 calls/batch, own results stream, own --report
|
|
@@ -4054,6 +4253,17 @@ cmd="${1:-status}"
|
|
|
4054
4253
|
shift 2>/dev/null || true
|
|
4055
4254
|
FLOW_LOG_CMD="$cmd"
|
|
4056
4255
|
FLOW_LOG_ARGS="$*"
|
|
4256
|
+
# Attestation privacy: never persist full argv (owner paths / potential secrets).
|
|
4257
|
+
if [ "$cmd" = "attest" ]; then
|
|
4258
|
+
_att_sub="${1:-}"
|
|
4259
|
+
_att_subj=""
|
|
4260
|
+
case "$_att_sub" in
|
|
4261
|
+
semantic|live-verify|status|recover) _att_subj="${2:-}" ;;
|
|
4262
|
+
esac
|
|
4263
|
+
# strip flag-like tokens from subject slot
|
|
4264
|
+
case "$_att_subj" in --*) _att_subj="" ;; esac
|
|
4265
|
+
FLOW_LOG_ARGS="${_att_sub}${_att_subj:+ ${_att_subj}}"
|
|
4266
|
+
fi
|
|
4057
4267
|
FLOW_LOG_START="$(_now)"
|
|
4058
4268
|
trap '_log_on_exit' EXIT
|
|
4059
4269
|
case "$cmd" in
|
|
@@ -4071,7 +4281,8 @@ case "$cmd" in
|
|
|
4071
4281
|
workspace) cmd_workspace "$@" ;;
|
|
4072
4282
|
loop-prep) cmd_loop_prep "$@" ;;
|
|
4073
4283
|
loop-log) cmd_loop_log "$@" ;;
|
|
4074
|
-
auto) cmd_auto ;;
|
|
4284
|
+
auto) cmd_auto "$@" ;;
|
|
4285
|
+
attest) cmd_attest "$@" ;;
|
|
4075
4286
|
recall) cmd_recall ;;
|
|
4076
4287
|
unlock) cmd_unlock ;;
|
|
4077
4288
|
retro) cmd_retro ;;
|
package/skills-manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "../skills/flow",
|
|
3
3
|
"destRelative": "skills/flow",
|
|
4
|
-
"fileCount":
|
|
5
|
-
"syncedAt": "2026-08-
|
|
4
|
+
"fileCount": 88,
|
|
5
|
+
"syncedAt": "2026-08-11T13:52:41.584Z",
|
|
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
|
]
|