amsd-pipeline-shared 0.5.2 → 0.5.3
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.
|
@@ -603,25 +603,36 @@ archive_prior_lane_state() {
|
|
|
603
603
|
local _lanes="${LOG_DIR:-}/lanes"
|
|
604
604
|
[ -d "$_lanes" ] || return 0
|
|
605
605
|
local _run="${EPAM_RESUME_RUN:-${ORCH_RUN_ID:-}}"
|
|
606
|
-
[ -
|
|
606
|
+
if [ -z "$_run" ]; then
|
|
607
|
+
warning "[orch] the earlier lane state is not archived: there is no run id (EPAM_RESUME_RUN / ORCH_RUN_ID) — it stays where it is" || true
|
|
608
|
+
return 0
|
|
609
|
+
fi
|
|
607
610
|
local _marker=""
|
|
608
611
|
if [ -n "${EPAM_PROJECT_CONFIG_DIR:-}" ]; then
|
|
609
612
|
_marker="${EPAM_PROJECT_CONFIG_DIR}/runs/${_run}/lane-state-archived"
|
|
610
613
|
[ -f "$_marker" ] && return 0
|
|
611
614
|
fi
|
|
612
|
-
#
|
|
613
|
-
|
|
615
|
+
# B80 (RS-7): the run's start is its id when the id is a timestamp (as before); for ANY other id (every Claude workflows id is LIVE-…) it is NOW — the
|
|
616
|
+
# first time this function runs for the run — which is only safe with the marker that stops a resume from archiving the run's own state
|
|
617
|
+
local _start _how=""
|
|
614
618
|
_start=$(printf '%s' "$_run" | sed -nE 's/^([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2})([0-9]{2})([0-9]{2})Z?$/\1-\2-\3 \4:\5:\6 UTC/p')
|
|
615
|
-
[ -
|
|
619
|
+
if [ -z "$_start" ]; then
|
|
620
|
+
if [ -z "$_marker" ]; then
|
|
621
|
+
warning "[orch] the earlier lane state is not archived: run id '${_run}' carries no start time and there is no EPAM_PROJECT_CONFIG_DIR to record that it was archived (a resume would archive the run's own state)" || true
|
|
622
|
+
return 0
|
|
623
|
+
fi
|
|
624
|
+
_start=$(date -u '+%Y-%m-%d %H:%M:%S.%N UTC'); _how=" (run '${_run}' carries no start time: it starts now)"
|
|
625
|
+
fi
|
|
616
626
|
local _ref; _ref=$(mktemp "${TMPDIR:-/tmp}/run-start-XXXXXX") || return 0
|
|
617
627
|
touch -d "$_start" "$_ref" 2>/dev/null || { rm -f "$_ref"; return 0; }
|
|
618
|
-
local _dest="${LOG_DIR}/archive/lanes-before-${_run}" _n=0 _f _rel
|
|
628
|
+
local _dest="${LOG_DIR}/archive/lanes-before-${_run}" _n=0 _failed=0 _f _rel
|
|
619
629
|
while IFS= read -r -d '' _f; do
|
|
620
630
|
_rel="${_f#"$_lanes"/}"
|
|
621
|
-
mkdir -p "$_dest/$(dirname "$_rel")" 2>/dev/null && mv "$_f" "$_dest/$_rel" 2>/dev/null
|
|
631
|
+
if mkdir -p "$_dest/$(dirname "$_rel")" 2>/dev/null && mv "$_f" "$_dest/$_rel" 2>/dev/null; then _n=$((_n + 1)); else _failed=$((_failed + 1)); fi
|
|
622
632
|
done < <(find "$_lanes" -type f ! -newer "$_ref" -print0 2>/dev/null)
|
|
623
633
|
rm -f "$_ref"
|
|
624
|
-
[ "$_n" -gt 0 ] && log "[orch] archived ${_n} file(s) of earlier runs' lane state → ${_dest} (this run starts with none of it)"
|
|
634
|
+
[ "$_n" -gt 0 ] && { log "[orch] archived ${_n} file(s) of earlier runs' lane state → ${_dest} (this run starts with none of it)${_how}" || true; }
|
|
635
|
+
[ "$_failed" -gt 0 ] && { warning "[orch] ${_failed} file(s) of earlier runs' lane state could not be archived — they stay in ${_lanes}" || true; }
|
|
625
636
|
[ -n "$_marker" ] && { mkdir -p "${_marker%/*}" 2>/dev/null; date -u +%Y-%m-%dT%H:%M:%SZ > "$_marker"; }
|
|
626
637
|
return 0
|
|
627
638
|
}
|
|
@@ -223,13 +223,32 @@ qa_phase_baseline_sha() {
|
|
|
223
223
|
# phase-baseline-sha.txt: every pre-existing failure was charged to its writer, eight attempts in a
|
|
224
224
|
# row (£0 multi-lane run, 2026-10-04). Nothing resolvable is said out loud, never written as a guess.
|
|
225
225
|
qa_record_phase_baseline() {
|
|
226
|
-
local _root="${1:-}" _branch="${2:-}" _log_dir="${3:-${LOG_DIR:-}}" _sha
|
|
226
|
+
local _root="${1:-}" _branch="${2:-}" _log_dir="${3:-${LOG_DIR:-}}" _sha _have _key
|
|
227
227
|
[ -n "$_root" ] && [ -n "$_log_dir" ] || return 1
|
|
228
|
+
local _bf="$_log_dir/phase-baseline-sha.txt" _kf="$_log_dir/phase-baseline-key.txt"
|
|
229
|
+
# B77 (RS-4, = B73): THE BASELINE IS RECORDED ONCE for a run and phase. A resume starts the phase again; the baseline it had must not move to wherever HEAD
|
|
230
|
+
# is by then (that made "committed since the baseline" empty). A new phase, or a new run in the same log folder, has a different key and records its own.
|
|
231
|
+
_key="${PHASE:-main}|${ORCH_RUN_ID:-}"
|
|
232
|
+
if [ -f "$_bf" ] && [ -f "$_kf" ] && [ "$(cat "$_kf" 2>/dev/null)" = "$_key" ]; then
|
|
233
|
+
_have=$(tr -d '[:space:]' < "$_bf" 2>/dev/null)
|
|
234
|
+
if [ -n "$_have" ] && git -C "$_root" cat-file -e "${_have}^{commit}" 2>/dev/null; then
|
|
235
|
+
printf '%s' "$_have"
|
|
236
|
+
return 0
|
|
237
|
+
fi
|
|
238
|
+
warning "[orch] the recorded phase baseline (${_have:-empty}) is not a commit of $_root — recording it again" || true
|
|
239
|
+
fi
|
|
228
240
|
_sha="$(qa_phase_baseline_sha "$_root" "$_branch" 2>/dev/null || echo "")"
|
|
229
241
|
if [ -z "$_sha" ]; then
|
|
230
|
-
warning "[orch] could not resolve a baseline commit in $_root — every diff-based gate will compare against nothing"
|
|
242
|
+
warning "[orch] could not resolve a baseline commit in $_root — every diff-based gate will compare against nothing" || true
|
|
231
243
|
return 1
|
|
232
244
|
fi
|
|
233
|
-
|
|
245
|
+
# the fallback is HEAD (the codeline has no such baseline branch — cx-shared has no develop): fine at the FIRST call, and said, because it is not a fork point
|
|
246
|
+
if [ -n "$_branch" ] && ! git -C "$_root" rev-parse --verify --quiet "origin/${_branch}^{commit}" >/dev/null 2>&1 \
|
|
247
|
+
&& ! git -C "$_root" rev-parse --verify --quiet "${_branch}^{commit}" >/dev/null 2>&1; then
|
|
248
|
+
warning "[orch] baseline '${_branch}' did not resolve in $_root — the phase baseline is HEAD (${_sha:0:9}) as of now; it is recorded once and not moved" || true
|
|
249
|
+
fi
|
|
250
|
+
printf '%s\n' "$_sha" > "$_bf"
|
|
251
|
+
printf '%s\n' "$_key" > "$_kf"
|
|
234
252
|
printf '%s' "$_sha"
|
|
253
|
+
return 0
|
|
235
254
|
}
|
|
@@ -32,19 +32,35 @@ _run_release_lines() {
|
|
|
32
32
|
|
|
33
33
|
# _return_from_release_lines <codeline-root> [name] — back on the branch the record names; the record is removed.
|
|
34
34
|
_return_from_release_lines() {
|
|
35
|
-
local _gd _home
|
|
35
|
+
local _gd _home _cur
|
|
36
36
|
_gd=$(git -C "$1" rev-parse --absolute-git-dir 2>/dev/null) || return 0
|
|
37
37
|
[ -f "$_gd/epam-release-home" ] || return 0
|
|
38
38
|
_home=$(cat "$_gd/epam-release-home")
|
|
39
|
-
|
|
39
|
+
_cur=$(git -C "$1" symbolic-ref -q --short HEAD 2>/dev/null)
|
|
40
|
+
if [ -n "$_home" ] && [ "$_cur" != "$_home" ]; then
|
|
40
41
|
if git -C "$1" checkout -q "$_home" 2>/dev/null; then
|
|
41
|
-
log "[orch] Codeline '${2:-$1}': release lines done — back on ${_home}"
|
|
42
|
+
log "[orch] Codeline '${2:-$1}': release lines done — back on ${_home}" || true
|
|
42
43
|
else
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
# B81 (RS-8): the usual reason is a dirty tree (a killed session). Whatever it holds is PRESERVED first (a rescue ref, git-ops.sh), then the copy is
|
|
45
|
+
# forced home; if it still cannot go home, that is an error (rc 1, the marker kept) — never a warning that leaves the copy on the line branch.
|
|
46
|
+
if [ -n "$(git -C "$1" status --porcelain --untracked-files=all 2>/dev/null)" ]; then
|
|
47
|
+
if declare -F _preserve_uncommitted >/dev/null 2>&1; then
|
|
48
|
+
_preserve_uncommitted "$1" "${_cur//\//-}" || { error "[orch] Codeline '${2:-$1}': could not return to ${_home} after its release lines — its uncommitted work could not be preserved, so nothing was forced"; return 1; }
|
|
49
|
+
else
|
|
50
|
+
error "[orch] Codeline '${2:-$1}': could not return to ${_home} after its release lines — the tree is dirty and this install cannot preserve it (needs amsd-pipeline-shared >= 0.5.2)"
|
|
51
|
+
return 1
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
if git -C "$1" checkout -q -f "$_home" 2>/dev/null; then
|
|
55
|
+
warning "[orch] Codeline '${2:-$1}': release lines done — back on ${_home} (its tree was not clean; the work it held is preserved)" || true
|
|
56
|
+
else
|
|
57
|
+
error "[orch] Codeline '${2:-$1}': could not return to ${_home} after its release lines (it is still on ${_cur:-a detached HEAD}; any uncommitted work is preserved on a rescue ref)"
|
|
58
|
+
return 1
|
|
59
|
+
fi
|
|
45
60
|
fi
|
|
46
61
|
fi
|
|
47
62
|
rm -f "$_gd/epam-release-home"
|
|
63
|
+
return 0
|
|
48
64
|
}
|
|
49
65
|
|
|
50
66
|
# _return_codelines_from_release_lines <prd> — every codeline of the PRD a line pass left is put back before the
|
|
@@ -220,12 +220,16 @@ story_outputs_tests_for() {
|
|
|
220
220
|
# the writer skips it and the review judges the committed change. A newer rejection leaves it for the writer.
|
|
221
221
|
story_resume_completed_by_commit() {
|
|
222
222
|
local project_root="$1" log_dir="$2" prd="$3"
|
|
223
|
-
[ -n "$project_root" ] && [ -e "$project_root/.git" ] && [ -f "$prd" ] || return 0
|
|
224
|
-
|
|
223
|
+
[ -n "$project_root" ] && [ -e "$project_root/.git" ] && [ -f "$prd" ] || { echo "[resume] no story is completed by its commit: ${project_root:-no project root} is not a repository, or there is no PRD at ${prd:-none}" >&2; return 0; }
|
|
224
|
+
# B78 (RS-5): a precondition it cannot meet is SAID — the story is then left exactly as it was (the writer is invoked), and the operator can see why
|
|
225
|
+
[ -f "$log_dir/phase-baseline-sha.txt" ] || { echo "[resume] no phase baseline is recorded in ${log_dir} — cannot tell which commits are this run's; no story is completed by its commit" >&2; return 0; }
|
|
225
226
|
local _base; _base=$(tr -d '[:space:]' < "$log_dir/phase-baseline-sha.txt" 2>/dev/null)
|
|
226
|
-
[ -
|
|
227
|
+
if [ -z "$_base" ] || ! git -C "$project_root" rev-parse --verify --quiet "${_base}^{commit}" >/dev/null 2>&1; then
|
|
228
|
+
echo "[resume] the recorded phase baseline (${_base:-empty}) is not a commit of ${project_root} — no story is completed by its commit" >&2
|
|
229
|
+
return 0
|
|
230
|
+
fi
|
|
227
231
|
local _id _ct _fb _fbt
|
|
228
|
-
for _id in $(jq -r '.stories[]? | select(.completed != true) | .id' "$prd" 2>/dev/null); do
|
|
232
|
+
for _id in $(jq -r '.stories[]? | select(.completed != true and .status != "deprecated") | .id' "$prd" 2>/dev/null); do
|
|
229
233
|
_ct=$(git -C "$project_root" log "${_base}..HEAD" --grep="^${_id}:" -1 --format=%ct 2>/dev/null)
|
|
230
234
|
[ -n "$_ct" ] || continue
|
|
231
235
|
_fb="$log_dir/review-feedback-${_id}.json"
|
|
@@ -234,9 +238,9 @@ story_resume_completed_by_commit() {
|
|
|
234
238
|
[ "${_fbt:-0}" -gt "$_ct" ] && continue
|
|
235
239
|
fi
|
|
236
240
|
local _tmp; _tmp=$(mktemp)
|
|
237
|
-
jq --arg id "$_id" '(.stories[] | select(.id == $id)) |= (. + {completed: true})' "$prd" > "$_tmp" \
|
|
241
|
+
jq --arg id "$_id" '(.stories[] | select(.id == $id)) |= (. + {completed: true, status: "completed"})' "$prd" > "$_tmp" \
|
|
238
242
|
&& mv "$_tmp" "$prd" || rm -f "$_tmp"
|
|
239
|
-
echo "[resume] ${_id}: its work is committed in this run ($(git -C "$project_root" log "${_base}..HEAD" --grep="^${_id}:" -1 --format=%h 2>/dev/null)) and no review rejection is newer — the writer is not invoked again; the review judges the committed change"
|
|
243
|
+
echo "[resume] ${_id}: its work is committed in this run ($(git -C "$project_root" log "${_base}..HEAD" --grep="^${_id}:" -1 --format=%h 2>/dev/null)) and no review rejection is newer — the writer is not invoked again; the review judges the committed change" >&2
|
|
240
244
|
done
|
|
241
245
|
return 0
|
|
242
246
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amsd-pipeline-shared",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "The AMSD pipeline's shared components, one source for the bash pipeline and its Claude workflows: the model-call gateway (llm-handler.sh — retry, ladder, self-heal, cost) and the libraries it runs.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"bin": {
|