autonomous-sdlc-harness 0.5.0 → 0.6.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.
- package/dist/commands/init.js +17 -8
- package/dist/commands/init.js.map +1 -1
- package/dist/config/check.js +27 -5
- package/dist/config/check.js.map +1 -1
- package/dist/config/model.js +54 -11
- package/dist/config/model.js.map +1 -1
- package/dist/core/pluginIdentity.js +2 -0
- package/dist/core/pluginIdentity.js.map +1 -1
- package/dist/core/writer.js +1 -0
- package/dist/core/writer.js.map +1 -1
- package/dist/doctor/checks.js +317 -40
- package/dist/doctor/checks.js.map +1 -1
- package/dist/generators/githubWorkflows.js +21 -11
- package/dist/generators/githubWorkflows.js.map +1 -1
- package/dist/remote/githubActions.js +63 -4
- package/dist/remote/githubActions.js.map +1 -1
- package/dist/retrieval/pythonBackend.js +114 -0
- package/dist/retrieval/pythonBackend.js.map +1 -0
- package/dist/retrieval/setup.js +8 -0
- package/dist/retrieval/setup.js.map +1 -1
- package/package.json +1 -1
- package/templates/README.md +1 -1
- package/templates/github/workflows/harness-control.yml +184 -0
- package/templates/github/workflows/harness-resume.yml +7 -0
- package/templates/github/workflows/harness-run.yml +100 -1
- package/templates/github/workflows/harness-trigger.yml +5 -4
- package/templates/scripts/README.md +1 -1
- package/templates/scripts/autonomous-watcher.sh +29 -2
- package/templates/scripts/docs-search-server.sh +88 -17
- package/templates/scripts/lib/harness-run-lib.sh +205 -26
- package/templates/scripts/remote-run.sh +2617 -150
- package/templates/scripts/scratch-run.sh +54 -73
- package/templates/state-dir/README-root.md +1 -1
- package/templates/state-dir/scratch/README.md +4 -2
- package/templates/state-dir/user_reviews/README.md +2 -2
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
# the repository it is operating on, reads that repository's
|
|
4
4
|
# `harness.config.json` at run time, answers "is this branch protected?",
|
|
5
5
|
# routes an inbox filename to its engine and branch (`hr_inbox_route_var`),
|
|
6
|
-
# derives a branch name from a title (`hr_derive_branch`),
|
|
6
|
+
# derives a branch name from a title (`hr_derive_branch`), judges whether a
|
|
7
|
+
# path lies strictly inside the state directory's scratch directory
|
|
8
|
+
# (`hr_scratch_path_var`), places a dropped
|
|
7
9
|
# artifact in a working copy and commits and pushes it, and derives the
|
|
8
10
|
# anchors (main checkout, work root, worktree directory, repo slug,
|
|
9
11
|
# state-dir paths) the scripts would otherwise each re-derive slightly
|
|
@@ -594,9 +596,10 @@ hr_config_load() {
|
|
|
594
596
|
# which is what lets an explicitly EMPTY list read as a configured set rather
|
|
595
597
|
# than as an absent one.
|
|
596
598
|
#
|
|
597
|
-
# A `phases.*` value that is not a boolean is emitted as
|
|
598
|
-
# string `"true"` — which `tostring` would otherwise make
|
|
599
|
-
# from `true` — reaches `hr_phase_enabled`
|
|
599
|
+
# A `phases.*` or `docs.retrieval` value that is not a boolean is emitted as
|
|
600
|
+
# `invalid`, so the string `"true"` — which `tostring` would otherwise make
|
|
601
|
+
# indistinguishable from `true` — reaches `hr_phase_enabled` or
|
|
602
|
+
# `hr_docs_retrieval_applies` as a value it refuses (2).
|
|
600
603
|
out=$(jq -n -r '
|
|
601
604
|
def s($k; $v):
|
|
602
605
|
if $v == null then empty
|
|
@@ -631,6 +634,8 @@ hr_config_load() {
|
|
|
631
634
|
s("phases.qa"; try (.phases.qa | if type == "boolean" or . == null then . else "invalid" end) catch null),
|
|
632
635
|
s("phases.docs"; try (.phases.docs | if type == "boolean" or . == null then . else "invalid" end) catch null),
|
|
633
636
|
s("execution.target"; try .execution.target catch null),
|
|
637
|
+
s("docs.retrievalBackend"; try .docs.retrievalBackend catch null),
|
|
638
|
+
s("docs.retrieval"; try (.docs.retrieval | if type == "boolean" or . == null then . else "invalid" end) catch null),
|
|
634
639
|
s("forge"; try .forge catch null),
|
|
635
640
|
s("protectedBranches.present";
|
|
636
641
|
try (if (.protectedBranches | type) == "array" then "1" else null end) catch null),
|
|
@@ -918,6 +923,53 @@ hr_forge() {
|
|
|
918
923
|
return 2
|
|
919
924
|
}
|
|
920
925
|
|
|
926
|
+
# Whether the docs phase's retrieval step runs: `phases.docs` and
|
|
927
|
+
# `docs.retrieval` both `true`. The shell mirror of `cli/src/config/model.ts` →
|
|
928
|
+
# `retrievalApplies`: change the predicate there and here together. PRINTS
|
|
929
|
+
# NOTHING: the answer is the status, as `hr_phase_enabled`'s is. 0 = both
|
|
930
|
+
# `true`; 1 = either `false` or unset; 2 = the configuration is unresolvable or
|
|
931
|
+
# either value is not a boolean — refused rather than guessed about.
|
|
932
|
+
hr_docs_retrieval_applies() {
|
|
933
|
+
local root="${1-}" status
|
|
934
|
+
hr_phase_enabled "$root" docs
|
|
935
|
+
status=$?
|
|
936
|
+
[ "$status" -eq 0 ] || return "$status"
|
|
937
|
+
hr_cfg_scalar_var "docs.retrieval" || return 1
|
|
938
|
+
case "$HR_CFG_VALUE" in
|
|
939
|
+
true) return 0 ;;
|
|
940
|
+
false) return 1 ;;
|
|
941
|
+
esac
|
|
942
|
+
return 2
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
# `docs.retrievalBackend` — which runtime the docs-retrieval index uses:
|
|
946
|
+
# `typescript` or `python`. THE ONE READER OF THE KEY IN THIS FAMILY, and the
|
|
947
|
+
# shell mirror of `cli/src/config/model.ts` → `RETRIEVAL_BACKENDS` /
|
|
948
|
+
# `DEFAULT_RETRIEVAL_BACKEND`: change the enum there and here together. Schema
|
|
949
|
+
# default `typescript`, so an absent key prints `typescript` and 1 is never
|
|
950
|
+
# returned; a `docs` parent of the wrong type (`"docs": "x"`) reads as absent
|
|
951
|
+
# too, because `hr_config_load`'s `try … catch` nulls that key alone — refusing
|
|
952
|
+
# that shape is the schema's job. 2 — printing nothing — when the configuration
|
|
953
|
+
# is unresolvable or the value is outside the enum, a refusal rather than a
|
|
954
|
+
# guess. It does NOT consult `phases.docs` / `docs.retrieval`: the key is read
|
|
955
|
+
# only inside the gate, so a caller asks `hr_docs_retrieval_applies` first and
|
|
956
|
+
# calls this only on its status 0.
|
|
957
|
+
hr_docs_retrieval_backend() {
|
|
958
|
+
local root="${1-}"
|
|
959
|
+
hr_config_load "$root" || return 2
|
|
960
|
+
if ! hr_cfg_scalar_var "docs.retrievalBackend"; then
|
|
961
|
+
printf 'typescript\n'
|
|
962
|
+
return 0
|
|
963
|
+
fi
|
|
964
|
+
case "$HR_CFG_VALUE" in
|
|
965
|
+
typescript|python)
|
|
966
|
+
printf '%s\n' "$HR_CFG_VALUE"
|
|
967
|
+
return 0
|
|
968
|
+
;;
|
|
969
|
+
esac
|
|
970
|
+
return 2
|
|
971
|
+
}
|
|
972
|
+
|
|
921
973
|
# ---------------------------------------------------------------------------
|
|
922
974
|
# Inbox routing — the one owner of the drop filename patterns.
|
|
923
975
|
# ---------------------------------------------------------------------------
|
|
@@ -1140,6 +1192,92 @@ hr_state_path() {
|
|
|
1140
1192
|
fi
|
|
1141
1193
|
}
|
|
1142
1194
|
|
|
1195
|
+
# Judge whether <path> resolves STRICTLY INSIDE `<root>/<state_dir>/scratch/`.
|
|
1196
|
+
# Usage: hr_scratch_path_var <root> <path> [<base>]
|
|
1197
|
+
#
|
|
1198
|
+
# Two callers, differing only in what they do with an accepted path:
|
|
1199
|
+
# `scratch-run.sh` executes a file there and `remote-run.sh discard` removes a
|
|
1200
|
+
# directory there. So this reports a keyword in `HR_SCRATCH_WHY` and leaves every
|
|
1201
|
+
# message and exit code to its caller.
|
|
1202
|
+
#
|
|
1203
|
+
# The rule, stated once:
|
|
1204
|
+
# - `..` is refused ANYWHERE in the argument, not only as a whole segment —
|
|
1205
|
+
# strictly stronger, and free, because nothing in that directory depends on
|
|
1206
|
+
# a file's name. Then any character outside `A-Za-z0-9._/-` is refused. Both
|
|
1207
|
+
# tests run on <path> as the caller received it, before anything resolves.
|
|
1208
|
+
# - A relative <path> resolves against <base> when given, else <root>; an
|
|
1209
|
+
# absolute one is taken as given.
|
|
1210
|
+
# - Both sides of the comparison are resolved PHYSICALLY (`cd … && pwd -P`), so
|
|
1211
|
+
# a symlinked directory planted inside the scratch tree cannot widen the
|
|
1212
|
+
# fence. The target's parent must be the scratch directory or beneath it, and
|
|
1213
|
+
# a basename of `.` (the scratch directory itself) is refused.
|
|
1214
|
+
# - A target that is itself a symlink is refused rather than followed: its
|
|
1215
|
+
# destination is outside this judgement. The target need not exist.
|
|
1216
|
+
#
|
|
1217
|
+
# Clears the other four, then sets: `HR_SCRATCH_SUBDIR` (`scratch`, mirroring the `scratch` row
|
|
1218
|
+
# of `STATE_DIR_ENTRIES` in `cli/src/generators/stateDir.ts`), `HR_SCRATCH_DIR`
|
|
1219
|
+
# (physical), `HR_SCRATCH_PARENT` (physical), `HR_SCRATCH_TARGET`
|
|
1220
|
+
# (`<parent>/<basename>`, the path a caller acts on) and `HR_SCRATCH_WHY`.
|
|
1221
|
+
# Status / `HR_SCRATCH_WHY`:
|
|
1222
|
+
# 0 accepted (WHY empty)
|
|
1223
|
+
# 1 refused — `dotdot`, `charset`, `outside`, `itself`, `symlink`
|
|
1224
|
+
# 2 the target's parent does not resolve — `no-parent`
|
|
1225
|
+
# 3 the scratch directory cannot be located — `no-config`, `no-scratch`
|
|
1226
|
+
# 4 <root> or <path> is empty — `usage`
|
|
1227
|
+
hr_scratch_path_var() {
|
|
1228
|
+
local root="${1-}" path="${2-}" base="${3-}" scratch candidate name
|
|
1229
|
+
HR_SCRATCH_DIR=""
|
|
1230
|
+
HR_SCRATCH_PARENT=""
|
|
1231
|
+
HR_SCRATCH_TARGET=""
|
|
1232
|
+
HR_SCRATCH_WHY=""
|
|
1233
|
+
HR_SCRATCH_SUBDIR='scratch'
|
|
1234
|
+
if [ -z "$root" ] || [ -z "$path" ]; then
|
|
1235
|
+
HR_SCRATCH_WHY="usage"
|
|
1236
|
+
return 4
|
|
1237
|
+
fi
|
|
1238
|
+
case "$path" in
|
|
1239
|
+
*..*) HR_SCRATCH_WHY="dotdot"; return 1 ;;
|
|
1240
|
+
esac
|
|
1241
|
+
case "$path" in
|
|
1242
|
+
*[!A-Za-z0-9._/-]*) HR_SCRATCH_WHY="charset"; return 1 ;;
|
|
1243
|
+
esac
|
|
1244
|
+
scratch=$(hr_state_path "$root" "$HR_SCRATCH_SUBDIR")
|
|
1245
|
+
if [ "$?" -ne 0 ] || [ -z "$scratch" ]; then
|
|
1246
|
+
HR_SCRATCH_WHY="no-config"
|
|
1247
|
+
return 3
|
|
1248
|
+
fi
|
|
1249
|
+
HR_SCRATCH_DIR=$(cd "$scratch" 2>/dev/null && pwd -P)
|
|
1250
|
+
if [ -z "$HR_SCRATCH_DIR" ]; then
|
|
1251
|
+
HR_SCRATCH_WHY="no-scratch"
|
|
1252
|
+
return 3
|
|
1253
|
+
fi
|
|
1254
|
+
[ -n "$base" ] || base="$root"
|
|
1255
|
+
case "$path" in
|
|
1256
|
+
/*) candidate="$path" ;;
|
|
1257
|
+
*) candidate="${base%/}/$path" ;;
|
|
1258
|
+
esac
|
|
1259
|
+
HR_SCRATCH_PARENT=$(cd "$(dirname "$candidate")" 2>/dev/null && pwd -P)
|
|
1260
|
+
if [ -z "$HR_SCRATCH_PARENT" ]; then
|
|
1261
|
+
HR_SCRATCH_WHY="no-parent"
|
|
1262
|
+
return 2
|
|
1263
|
+
fi
|
|
1264
|
+
case "$HR_SCRATCH_PARENT" in
|
|
1265
|
+
"$HR_SCRATCH_DIR" | "$HR_SCRATCH_DIR"/*) ;;
|
|
1266
|
+
*) HR_SCRATCH_WHY="outside"; return 1 ;;
|
|
1267
|
+
esac
|
|
1268
|
+
name=$(basename "$candidate")
|
|
1269
|
+
if [ "$name" = "." ]; then
|
|
1270
|
+
HR_SCRATCH_WHY="itself"
|
|
1271
|
+
return 1
|
|
1272
|
+
fi
|
|
1273
|
+
HR_SCRATCH_TARGET="$HR_SCRATCH_PARENT/$name"
|
|
1274
|
+
if [ -L "$HR_SCRATCH_TARGET" ]; then
|
|
1275
|
+
HR_SCRATCH_WHY="symlink"
|
|
1276
|
+
return 1
|
|
1277
|
+
fi
|
|
1278
|
+
return 0
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1143
1281
|
# The machine-local settings directory — one place an operator keeps values that
|
|
1144
1282
|
# vary per machine rather than per repository, which is why it is not a config
|
|
1145
1283
|
# key and not a repository file. Return 1 when there is no home to anchor it to.
|
|
@@ -1442,8 +1580,10 @@ hr_remote_record_init() {
|
|
|
1442
1580
|
# limit and readable in the Actions run list. GitHub documents no ref limit.
|
|
1443
1581
|
#
|
|
1444
1582
|
# THIS SECTION ONLY READS. It fetches nothing and creates no branch or file; a
|
|
1445
|
-
# caller that wants `origin` fresh fetches first.
|
|
1446
|
-
#
|
|
1583
|
+
# caller that wants `origin` fresh fetches first. Given a <gh_cli>, it also asks
|
|
1584
|
+
# GitHub one read per candidate — the run workflow's runs under that name — and
|
|
1585
|
+
# still writes nothing. A registry is read only when it already exists, because
|
|
1586
|
+
# `hr_registry_get` creates an absent one.
|
|
1447
1587
|
# ---------------------------------------------------------------------------
|
|
1448
1588
|
|
|
1449
1589
|
# The two limits the rule above names.
|
|
@@ -1525,11 +1665,37 @@ EOF
|
|
|
1525
1665
|
return 0
|
|
1526
1666
|
}
|
|
1527
1667
|
|
|
1528
|
-
#
|
|
1529
|
-
#
|
|
1668
|
+
# hr_branch_run_history <root> <gh_cli> <name> — 0 when the run workflow
|
|
1669
|
+
# (`HR_REMOTE_WORKFLOW_RUN_FILE`) lists a run under <name>, 1 when it lists
|
|
1670
|
+
# none, 2 when <gh_cli> cannot run, exits non-zero, or answers anything but a
|
|
1671
|
+
# JSON array. Sets no `HR_` variable: the names are assigned inside the
|
|
1672
|
+
# subshell that `cd`s to <root>.
|
|
1673
|
+
#
|
|
1674
|
+
# GitHub keeps a deleted branch's runs listed under its name, and a later run
|
|
1675
|
+
# of that name inherits them: Gate 12 round 5 found run `36569531374` of the
|
|
1676
|
+
# deleted `feat_invoices` (`docs/development.md` → Gate 12 → Round 5, finding
|
|
1677
|
+
# 1). One bounded read per candidate, not one listing of every branch, because
|
|
1678
|
+
# a bounded all-branch listing could miss an old name. Bash 3.2 and jq 1.5.
|
|
1679
|
+
hr_branch_run_history() {
|
|
1680
|
+
local root="${1-}" gh_cli="${2-}" name="${3-}" answer verdict
|
|
1681
|
+
[ -n "$root" ] && [ -n "$gh_cli" ] && [ -n "$name" ] || return 2
|
|
1682
|
+
answer=$(cd "$root" 2>/dev/null && hr_remote_names_var &&
|
|
1683
|
+
"$gh_cli" run list --workflow "$HR_REMOTE_WORKFLOW_RUN_FILE" --branch "$name" --limit 1 --json databaseId 2>/dev/null) || return 2
|
|
1684
|
+
verdict=$(printf '%s' "$answer" | jq -r 'if type == "array" then (if length > 0 then "history" else "none" end) else "other" end' 2>/dev/null) || return 2
|
|
1685
|
+
case "$verdict" in
|
|
1686
|
+
history) return 0 ;;
|
|
1687
|
+
none) return 1 ;;
|
|
1688
|
+
esac
|
|
1689
|
+
return 2
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
# Judge <name> against the listings `hr_branch_taken_lists_var` last read, then,
|
|
1693
|
+
# given a <gh_cli>, against the run workflow's history — last, so the free local
|
|
1694
|
+
# checks answer first. The answers and `HR_TAKEN_WHY` are
|
|
1695
|
+
# `hr_branch_name_taken`'s.
|
|
1530
1696
|
hr_branch_taken_judge() {
|
|
1531
1697
|
local LC_ALL=C
|
|
1532
|
-
local root="${1-}" name="${2-}" registry="${3-}" lower status nl
|
|
1698
|
+
local root="${1-}" name="${2-}" registry="${3-}" gh_cli="${4-}" lower status nl
|
|
1533
1699
|
nl='
|
|
1534
1700
|
'
|
|
1535
1701
|
HR_TAKEN_WHY=""
|
|
@@ -1557,18 +1723,29 @@ hr_branch_taken_judge() {
|
|
|
1557
1723
|
HR_TAKEN_WHY="a run registry record"
|
|
1558
1724
|
return 0
|
|
1559
1725
|
fi
|
|
1726
|
+
if [ -n "$gh_cli" ]; then
|
|
1727
|
+
status=0
|
|
1728
|
+
hr_branch_run_history "$root" "$gh_cli" "$name" || status=$?
|
|
1729
|
+
case "$status" in
|
|
1730
|
+
0) HR_TAKEN_WHY="a run of the run workflow listed under that name"; return 0 ;;
|
|
1731
|
+
1) ;;
|
|
1732
|
+
*) HR_TAKEN_WHY="the run history of $name could not be listed"; return 2 ;;
|
|
1733
|
+
esac
|
|
1734
|
+
fi
|
|
1560
1735
|
return 1
|
|
1561
1736
|
}
|
|
1562
1737
|
|
|
1563
|
-
# hr_branch_name_taken <root> <name> [<registry>] — 0 taken, 1 free,
|
|
1564
|
-
# tell. Sets `HR_TAKEN_WHY` to a short phrase naming the collision or
|
|
1565
|
-
# failure.
|
|
1566
|
-
# case-insensitively; a local
|
|
1567
|
-
# `origin/<defaultBranch>`, a directory named
|
|
1568
|
-
# `<name>_task_prompt.md`, `<name>_story_plan.md` or
|
|
1569
|
-
# merged and deleted branch still leaves; a record in
|
|
1738
|
+
# hr_branch_name_taken <root> <name> [<registry>] [<gh_cli>] — 0 taken, 1 free,
|
|
1739
|
+
# 2 cannot tell. Sets `HR_TAKEN_WHY` to a short phrase naming the collision or
|
|
1740
|
+
# the failure. A caller with no registry passes `""` before <gh_cli>. Taken: a
|
|
1741
|
+
# protected name; a branch on `origin`, compared case-insensitively; a local
|
|
1742
|
+
# branch; under `<state_dir>` on `origin/<defaultBranch>`, a directory named
|
|
1743
|
+
# <name> or a file `<name>_task_prompt.md`, `<name>_story_plan.md` or
|
|
1744
|
+
# `<name>_docs.md` — which a merged and deleted branch still leaves; a record in
|
|
1745
|
+
# an existing <registry>; given a <gh_cli>, any run of the run workflow listed
|
|
1746
|
+
# under <name> (`hr_branch_run_history`), whose listing failing is a 2.
|
|
1570
1747
|
hr_branch_name_taken() {
|
|
1571
|
-
local root="${1-}" name="${2-}" registry="${3-}"
|
|
1748
|
+
local root="${1-}" name="${2-}" registry="${3-}" gh_cli="${4-}"
|
|
1572
1749
|
HR_TAKEN_WHY=""
|
|
1573
1750
|
if [ -z "$root" ] || [ -z "$name" ]; then
|
|
1574
1751
|
HR_TAKEN_WHY="no branch name to judge"
|
|
@@ -1576,20 +1753,21 @@ hr_branch_name_taken() {
|
|
|
1576
1753
|
fi
|
|
1577
1754
|
hr_config_load "$root" || :
|
|
1578
1755
|
hr_branch_taken_lists_var "$root" || return 2
|
|
1579
|
-
hr_branch_taken_judge "$root" "$name" "$registry"
|
|
1756
|
+
hr_branch_taken_judge "$root" "$name" "$registry" "$gh_cli"
|
|
1580
1757
|
}
|
|
1581
1758
|
|
|
1582
|
-
# hr_derive_branch <root> <text> <fallback> [<registry>] — print the
|
|
1583
|
-
# and return 0; return 2, printing nothing, when a `taken`
|
|
1584
|
-
# tell or no base routes back to itself; return 3, printing
|
|
1585
|
-
# suffix through `HR_BRANCH_SUFFIX_MAX` is taken. Never a
|
|
1759
|
+
# hr_derive_branch <root> <text> <fallback> [<registry>] [<gh_cli>] — print the
|
|
1760
|
+
# derived name and return 0; return 2, printing nothing, when a `taken`
|
|
1761
|
+
# judgement could not tell or no base routes back to itself; return 3, printing
|
|
1762
|
+
# nothing, when every suffix through `HR_BRANCH_SUFFIX_MAX` is taken. Never a
|
|
1763
|
+
# guessed name. <gh_cli> reaches every judgement as `hr_branch_name_taken`'s.
|
|
1586
1764
|
#
|
|
1587
1765
|
# THE BASE MUST ROUTE BACK TO ITSELF: `hr_inbox_route_var` on each drop filename
|
|
1588
1766
|
# a run of that name produces has to give the base as its branch, so no derived
|
|
1589
1767
|
# name makes the inbox patterns ambiguous. A base that does not is replaced by
|
|
1590
1768
|
# <fallback> once.
|
|
1591
1769
|
hr_derive_branch() {
|
|
1592
|
-
local root="${1-}" text="${2-}" fallback="${3-}" registry="${4-}"
|
|
1770
|
+
local root="${1-}" text="${2-}" fallback="${3-}" registry="${4-}" gh_cli="${5-}"
|
|
1593
1771
|
local base="" candidate suffix routes n status
|
|
1594
1772
|
hr_branch_limits_var
|
|
1595
1773
|
candidate=$(hr_branch_slug "$text") || candidate="$fallback"
|
|
@@ -1615,7 +1793,7 @@ hr_derive_branch() {
|
|
|
1615
1793
|
n=1
|
|
1616
1794
|
while :; do
|
|
1617
1795
|
status=0
|
|
1618
|
-
hr_branch_taken_judge "$root" "$candidate" "$registry" || status=$?
|
|
1796
|
+
hr_branch_taken_judge "$root" "$candidate" "$registry" "$gh_cli" || status=$?
|
|
1619
1797
|
case "$status" in
|
|
1620
1798
|
1) printf '%s\n' "$candidate"; return 0 ;;
|
|
1621
1799
|
2) return 2 ;;
|
|
@@ -1704,8 +1882,9 @@ hr_push_landed() {
|
|
|
1704
1882
|
# names. Every name below is a variable `hr_remote_names_var` assigns, and it
|
|
1705
1883
|
# also assigns `HR_REMOTE_WORKFLOW_RUN_FILE`, the run workflow's file name, for
|
|
1706
1884
|
# the GitHub-route producers `hr_github_answer_route` and
|
|
1707
|
-
# `hr_github_resume_route
|
|
1708
|
-
# function spells either one,
|
|
1885
|
+
# `hr_github_resume_route` and for the run-history probe `hr_branch_run_history`.
|
|
1886
|
+
# Those two are mirrors of the header's table; no function spells either one,
|
|
1887
|
+
# or any other name here.
|
|
1709
1888
|
#
|
|
1710
1889
|
# <bundle>/status.json the job's record, fixed schema below
|
|
1711
1890
|
# <bundle>/clarifications/<branch>/ the whole branch directory, answered/ included
|