amsd-pipeline-shared 0.5.0 → 0.5.2

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.
Files changed (50) hide show
  1. package/docs/gateway-baseline-2.0.80.md5 +47 -0
  2. package/docs/gateway-files.txt +47 -0
  3. package/orchestrations/config/repo-artifacts.json +23 -0
  4. package/orchestrations/config/resume-preserves.json +25 -0
  5. package/orchestrations/config/run-modes.json +47 -0
  6. package/orchestrations/scripts/lib/checkpoints.sh +175 -0
  7. package/orchestrations/scripts/lib/codeline-lanes.sh +1664 -0
  8. package/orchestrations/scripts/lib/codeline-packages.js +67 -0
  9. package/orchestrations/scripts/lib/codeline-write-perimeter.sh +318 -0
  10. package/orchestrations/scripts/lib/common.sh +66 -0
  11. package/orchestrations/scripts/lib/control-plane.sh +506 -0
  12. package/orchestrations/scripts/lib/ecosystem-registry.js +148 -0
  13. package/orchestrations/scripts/lib/engine-paths.sh +52 -0
  14. package/orchestrations/scripts/lib/flags.sh +38 -0
  15. package/orchestrations/scripts/lib/git-ops.sh +975 -0
  16. package/orchestrations/scripts/lib/halt-recovery.sh +56 -0
  17. package/orchestrations/scripts/lib/handlers/_read-input.js +88 -0
  18. package/orchestrations/scripts/lib/handlers/carry-plan.js +25 -0
  19. package/orchestrations/scripts/lib/handlers/cl-entries.js +10 -0
  20. package/orchestrations/scripts/lib/handlers/codeline-ecosystem.js +164 -0
  21. package/orchestrations/scripts/lib/handlers/codeline-manifests.js +148 -0
  22. package/orchestrations/scripts/lib/handlers/filtered-prd.js +85 -0
  23. package/orchestrations/scripts/lib/handlers/merge-lane-into-canonical.js +39 -0
  24. package/orchestrations/scripts/lib/handlers/package-engines-node.js +25 -0
  25. package/orchestrations/scripts/lib/handlers/prd-phases.js +46 -0
  26. package/orchestrations/scripts/lib/handlers/rebuild-cross-contract.js +7 -0
  27. package/orchestrations/scripts/lib/handlers/record-declared-pass.js +23 -0
  28. package/orchestrations/scripts/lib/handlers/release-line-prd.js +31 -0
  29. package/orchestrations/scripts/lib/handlers/release-lines.js +31 -0
  30. package/orchestrations/scripts/lib/handlers/repo-exclude-patterns.js +108 -0
  31. package/orchestrations/scripts/lib/handlers/resume-spec-output-present.js +16 -0
  32. package/orchestrations/scripts/lib/handlers/sibling-providers.js +43 -0
  33. package/orchestrations/scripts/lib/handlers/spanning-stories-incomplete.js +50 -0
  34. package/orchestrations/scripts/lib/handlers/spec-inputs-digest.js +48 -0
  35. package/orchestrations/scripts/lib/handlers/spec-predates-plan.js +40 -0
  36. package/orchestrations/scripts/lib/handlers/stories-lacking-spec.js +64 -0
  37. package/orchestrations/scripts/lib/handlers/write-missing-plans.js +92 -0
  38. package/orchestrations/scripts/lib/orchestration-resume.sh +74 -0
  39. package/orchestrations/scripts/lib/phase-exit.sh +90 -0
  40. package/orchestrations/scripts/lib/pipeline-commit.sh +19 -0
  41. package/orchestrations/scripts/lib/plan-hash.js +19 -0
  42. package/orchestrations/scripts/lib/plan-scope.js +73 -0
  43. package/orchestrations/scripts/lib/qa-gate-evidence.sh +235 -0
  44. package/orchestrations/scripts/lib/release-lines.sh +166 -0
  45. package/orchestrations/scripts/lib/resume-semantics.sh +31 -0
  46. package/orchestrations/scripts/lib/run-checkpoint.sh +842 -0
  47. package/orchestrations/scripts/lib/run-modes.sh +93 -0
  48. package/orchestrations/scripts/lib/story-outputs.sh +322 -0
  49. package/orchestrations/scripts/lib/story-retry-state.sh +355 -0
  50. package/package.json +1 -1
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env bash
2
+ # _run_release_lines <codeline> <lane-prd> <worktree> <lane-log-dir> <log-file> <phase-filter> <phase-runner>
3
+ #
4
+ # A SHARED CODELINE SHIPS ON EVERY RELEASE LINE ITS STORY'S PLAN NAMES. The lane has worked its stories on the
5
+ # codeline's own base; this works them once more per line the plan marks off that base (lib/handlers/release-lines.js)
6
+ # — that line's base (a branch or a release tag), its own story branch (EPAM_BRANCH_SUFFIX), its own logs, its own PRD
7
+ # copy with the stories pending again (lib/handlers/release-line-prd.js). The plan decides how many: 0, 1 or N.
8
+ #
9
+ # Operator, 2026-10-06 (AMSD-2974): "Why one? That does not work for brownfield for a shared repo", "You cannot hard
10
+ # code 1:1". The library had to ship on 8.x and as a back-port from v7.14.0 for two consumers locked to ^7.
11
+ #
12
+ # The phase runner is the lane's own (the orchestrator, "$0"), run exactly as the lane runs it. A line that fails
13
+ # fails the lane; no later line runs after it. Returns non-zero then.
14
+ # shellcheck source=resume-semantics.sh
15
+ . "$(dirname "${BASH_SOURCE[0]}")/resume-semantics.sh"
16
+ # shellcheck source=phase-exit.sh
17
+ declare -F phase_exit_is_retryable >/dev/null 2>&1 || . "$(dirname "${BASH_SOURCE[0]}")/phase-exit.sh"
18
+
19
+ _run_release_lines() {
20
+ # THE CODELINE IS LEFT ON THE BRANCH IT WAS ON. A line pass checks out the line's story branch; left there, the next
21
+ # launch's detective read cx-shared at 7.14.0 and planned its own line as 7.x (AMSD-2974, 2026-10-07).
22
+ # The branch is recorded in the codeline's git dir first: a run killed mid-line runs nothing after the pass, and
23
+ # the next launch returns the codeline from the record (_return_codelines_from_release_lines).
24
+ local _home _rc=0 _gd
25
+ _home=$(git -C "$3" symbolic-ref -q --short HEAD 2>/dev/null || true)
26
+ _gd=$(git -C "$3" rev-parse --absolute-git-dir 2>/dev/null || true)
27
+ [ -n "$_home" ] && [ -n "$_gd" ] && printf '%s\n' "$_home" > "$_gd/epam-release-home"
28
+ _run_release_lines_each "$@" || _rc=$?
29
+ _return_from_release_lines "$3" "$1"
30
+ return "$_rc"
31
+ }
32
+
33
+ # _return_from_release_lines <codeline-root> [name] — back on the branch the record names; the record is removed.
34
+ _return_from_release_lines() {
35
+ local _gd _home
36
+ _gd=$(git -C "$1" rev-parse --absolute-git-dir 2>/dev/null) || return 0
37
+ [ -f "$_gd/epam-release-home" ] || return 0
38
+ _home=$(cat "$_gd/epam-release-home")
39
+ if [ -n "$_home" ] && [ "$(git -C "$1" symbolic-ref -q --short HEAD 2>/dev/null)" != "$_home" ]; then
40
+ if git -C "$1" checkout -q "$_home" 2>/dev/null; then
41
+ log "[orch] Codeline '${2:-$1}': release lines done — back on ${_home}"
42
+ else
43
+ warning "[orch] Codeline '${2:-$1}': could not return to ${_home} after its release lines"
44
+ return 0
45
+ fi
46
+ fi
47
+ rm -f "$_gd/epam-release-home"
48
+ }
49
+
50
+ # _return_codelines_from_release_lines <prd> — every codeline of the PRD a line pass left is put back before the
51
+ # launch plans the story (AMSD-2974 run 2, 2026-10-07: the detective read cx-shared on its 7.x line branch).
52
+ _return_codelines_from_release_lines() {
53
+ local _p
54
+ while IFS=$'\t' read -r _n _p; do
55
+ [ -n "$_p" ] && [ -d "$_p" ] && _return_from_release_lines "$_p" "$_n"
56
+ done < <(jq -r '.project.outputDirs[]? | [.codeline, .path] | @tsv' "$1" 2>/dev/null)
57
+ return 0
58
+ }
59
+
60
+ _run_release_lines_each() {
61
+ local _cl="$1" _cl_prd="$2" _wt="$3" _lane_log="$4" _log_file="${5:-/dev/null}" _phase_filter="${6:-}" _runner="$7" _canonical="${8:-}"
62
+ local _lines=()
63
+ mapfile -t _lines < <("$NODE_BIN" "$SCRIPT_DIR/lib/handlers/release-lines.js" "$_cl_prd" "$_cl" "$_canonical")
64
+ [ "${#_lines[@]}" -gt 0 ] || return 0
65
+ # THE CHANGE EVERY LINE PORTS: what the codeline's own line committed for this story — from the lane's phase baseline
66
+ # to the branch the codeline was on when the lines began (recorded by _run_release_lines). Given verbatim to each
67
+ # line's writer and diff reviewers (lib/producers/fix-plan.js, template release-line-port): AMSD-2974 run 9 gave
68
+ # them only the plan's summary, and a 7.x back-port carrying a fraction of the 8.x change was approved.
69
+ local _main_branch="" _main_base="" _main_change="${_lane_log}/main-line-change.diff" _gdir
70
+ _gdir=$(git -C "$_wt" rev-parse --absolute-git-dir 2>/dev/null || true)
71
+ [ -n "$_gdir" ] && [ -f "$_gdir/epam-release-home" ] && _main_branch=$(cat "$_gdir/epam-release-home")
72
+ _main_base=$(tr -d '[:space:]' < "${_lane_log}/phase-baseline-sha.txt" 2>/dev/null || true)
73
+ rm -f "$_main_change"
74
+ if [ -n "$_main_branch" ] && [ -n "$_main_base" ]; then
75
+ git -C "$_wt" diff "$_main_base" "$_main_branch" > "$_main_change" 2>/dev/null || rm -f "$_main_change"
76
+ fi
77
+ [ -s "$_main_change" ] || { rm -f "$_main_change"; _main_change=""; }
78
+ if [ -n "$_main_change" ]; then
79
+ log "[orch] Codeline '${_cl}': each release line ports ${_main_branch}'s change ($(grep -c '^diff --git' "$_main_change") file(s), from ${_main_base:0:9})"
80
+ else
81
+ warning "[orch] Codeline '${_cl}': no committed change on its own line to port — release lines are worked from the plan alone"
82
+ fi
83
+ local _entry _line _base _slug _line_log _line_prd _phase _pex _ledger
84
+ for _entry in "${_lines[@]}"; do
85
+ [ -n "$_entry" ] || continue
86
+ _line="${_entry%%$'\t'*}"; _base="${_entry#*$'\t'}"
87
+ _slug=$(printf '%s' "$_line" | tr -c 'A-Za-z0-9._-' '-')
88
+ _line_log="${_lane_log}/lines/${_slug}"
89
+ mkdir -p "$_line_log" 2>/dev/null || true
90
+ _line_prd="${_line_log}/prd.json"
91
+ # A LINE THIS RUN COMPLETED GOES BACK TO ITS REVIEWER ON RESUME — kept, not redone, not passed over by rule
92
+ # (operator, 2026-10-08: the 7.x back-port carried a third of the 8.x fix). Its PRD and story branch are kept;
93
+ # the phase runs without --reset, so Step 1 passes it as completed and the review → rework loop judges it
94
+ # against the story's plan as it stands.
95
+ local _rerun_args=(--reset) _line_branch
96
+ if resume_preserves completed-stories && [ -f "$_line_prd" ] \
97
+ && jq -e '(.stories | length) > 0 and all(.stories[]; .status == "completed")' "$_line_prd" >/dev/null 2>&1 \
98
+ && [ -z "$("$NODE_BIN" "$SCRIPT_DIR/lib/handlers/spec-predates-plan.js" "$_line_prd" "${_canonical:-$_cl_prd}" 2>/dev/null)" ]; then
99
+ _rerun_args=()
100
+ _line_branch="${EPAM_BRANCH_PREFIX:-}AI-$(jq -r '.stories[0].id' "$_line_prd")-${_slug}"
101
+ git -C "$_wt" checkout -q "$_line_branch" 2>/dev/null \
102
+ || warning "[orch] Codeline '${_cl}': could not check out ${_line_branch} for its review"
103
+ # The story's plan as it stands — the kept line PRD holds the plan of the pass that completed it.
104
+ "$NODE_BIN" "$SCRIPT_DIR/lib/handlers/carry-plan.js" "$_line_prd" "${_canonical:-$_cl_prd}" || true
105
+ log "[orch] Codeline '${_cl}' — release line ${_line} completed in this run — its reviewer judges it again against the story's plan"
106
+ else
107
+ "$NODE_BIN" "$SCRIPT_DIR/lib/handlers/release-line-prd.js" "$_cl_prd" "$_line_prd" "$_cl" "$_line" "$_canonical" || {
108
+ error "[orch] Codeline '${_cl}': could not prepare release line ${_line}"; return 1; }
109
+ fi
110
+ log "[orch] Codeline '${_cl}' — release line ${_line}, from ${_base} (the story's plan)"
111
+ # A STEP NEVER RUNS TWICE: a story already specified for this codeline is not specified again on another line.
112
+ # The spec pass runs on the line only for a story that still lacks its spec (lib/handlers/stories-lacking-spec.js).
113
+ local _line_spec="${EPAM_SPEC_MODE:-}"
114
+ [ -z "$("$NODE_BIN" "$SCRIPT_DIR/lib/handlers/stories-lacking-spec.js" "$_line_prd" 2>/dev/null)" ] && _line_spec=0
115
+ local _phases=()
116
+ mapfile -t _phases < <("$NODE_BIN" "$SCRIPT_DIR/lib/handlers/prd-phases.js" "$_line_prd")
117
+ for _phase in "${_phases[@]}"; do
118
+ [ -n "$_phase" ] || continue
119
+ [ -n "$_phase_filter" ] && [ "$_phase" != "$_phase_filter" ] && continue
120
+ _line_phase() {
121
+ JIRA_CODELINE_RUN=1 \
122
+ EPAM_CODELINE="$_cl" \
123
+ EPAM_RELEASE_LINE="$_line" \
124
+ EPAM_MAIN_LINE_CHANGE="$_main_change" \
125
+ EPAM_MAIN_LINE_BRANCH="$_main_branch" \
126
+ EPAM_SPEC_MODE="$_line_spec" \
127
+ EPAM_BRANCH_SUFFIX="-${_slug}" \
128
+ JIRA_BASELINE_BRANCH="$_base" \
129
+ LOG_DIR="$_line_log" \
130
+ AGENT_IO_DIR="$_line_log/agent-io" \
131
+ PRD_FILE="$_line_prd" \
132
+ PROJECT_ROOT="$_wt" \
133
+ OUTPUT_DIR="$_wt" \
134
+ PHASE="$_phase" \
135
+ bash "$_runner" "$@" 2>&1 | tee -a "$_log_file"
136
+ return "${PIPESTATUS[0]}"
137
+ }
138
+ _pex=0; _line_phase "${_rerun_args[@]}" || _pex=$?
139
+ # A LINE RETRIES AS A LANE DOES (lib/phase-exit.sh): exit 2 is "the gates remediated the story — retry the
140
+ # phase"; once, with SKIP_GATE_REMEDIATION=1 (AMSD-2974 run 10: the line failed on it, the finding never
141
+ # reached its writer).
142
+ # WHILE THE GATES REMEDIATE, THE LINE'S PHASE IS RETRIED with remediation on (lib/codeline-lanes.sh, the same rule).
143
+ while phase_exit_is_retryable "$_pex"; do
144
+ log "[orch] '${_phase}' ('${_cl}' release line ${_line}): $(phase_exit_describe "$_pex") — retrying the phase"
145
+ local _rmark _rargs=(); _rmark=$(phase_retry_mark "$_wt")
146
+ mapfile -t _rargs < <(phase_exit_retry_args "$_pex")
147
+ _pex=0; _line_phase ${_rargs[@]+"${_rargs[@]}"} || _pex=$?
148
+ # THE PIPELINE NEVER LOOPS (lib/phase-exit.sh): a retry that changed nothing in the codeline is not repeated.
149
+ if phase_exit_is_retryable "$_pex" && ! phase_retry_progressed "$_wt" "$_rmark"; then
150
+ error "[orch] Phase '${_phase}' for '${_cl}' on release line ${_line}: the self-healing retry changed nothing in the codeline (still ${_rmark:0:9}) — not retrying again"
151
+ _pex=1
152
+ fi
153
+ done
154
+ if [ "$_pex" -ne 0 ]; then
155
+ error "[orch] Phase '${_phase}' for '${_cl}' on release line ${_line} failed (exit $_pex)"
156
+ return 1
157
+ fi
158
+ log "[orch] Phase '${_phase}' — '${_cl}' release line ${_line} done."
159
+ done
160
+ # The line's append-only ledgers back into the lane's, as a lane folds its own into the parent.
161
+ for _ledger in phase-cost.jsonl agent-activity.jsonl healing-events.jsonl; do
162
+ [ -s "${_line_log}/${_ledger}" ] && cat "${_line_log}/${_ledger}" >> "${_lane_log}/${_ledger}" 2>/dev/null || true
163
+ done
164
+ done
165
+ return 0
166
+ }
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env bash
2
+ # resume-semantics.sh — THE ONE ANSWER to "what does a resume keep?"
3
+ #
4
+ # Declared once in config/resume-preserves.json (see its $why for the five incidents that each
5
+ # taught one component separately). Consumers ask `resume_preserves <aspect>` and never test
6
+ # EPAM_RESUME_RUN themselves for these decisions. An aspect the declaration does not name is
7
+ # refused loudly (exit 2, message on stderr) — a consumer that asks about something undeclared
8
+ # has found a gap in the declaration, not a reason to guess.
9
+ #
10
+ # is_resume — exit 0 when EPAM_RESUME_RUN names a run
11
+ # resume_preserves <aspect> — exit 0 when this is a resume AND the aspect is declared kept;
12
+ # exit 1 on a fresh launch; exit 2 for an undeclared aspect.
13
+
14
+ _resume_preserves_file() {
15
+ local _here; _here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
+ echo "${EPAM_RESUME_PRESERVES_FILE:-$_here/../../config/resume-preserves.json}"
17
+ }
18
+
19
+ is_resume() {
20
+ [ -n "${EPAM_RESUME_RUN:-}" ]
21
+ }
22
+
23
+ resume_preserves() {
24
+ local _aspect="${1:-}"
25
+ local _file; _file="$(_resume_preserves_file)"
26
+ if [ -z "$_aspect" ] || ! jq -e --arg a "$_aspect" '.preserves[$a] // empty' "$_file" >/dev/null 2>&1; then
27
+ echo "[resume-semantics] aspect '${_aspect}' is not declared in ${_file} — nothing says whether a resume keeps it; declare it before asking" >&2
28
+ return 2
29
+ fi
30
+ is_resume
31
+ }