amsd-pipeline-shared 0.5.35 → 0.5.37
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.
|
@@ -124,16 +124,24 @@ function seed({ install, project, ticket, runsRoots }) {
|
|
|
124
124
|
*/
|
|
125
125
|
// maxRebuild: how many generated prompts without an entry the launch accepts rebuilding (operator, 2026-10-19: a short,
|
|
126
126
|
// NAMED list is acceptable). The launch states it (--max-rebuild); unstated it is 0 — every prompt must be reusable.
|
|
127
|
-
|
|
127
|
+
/** THE PROJECT THE LEG WILL USE (2026-10-24, run 13's resume refused on the install's older sets): a run that has its own project copy
|
|
128
|
+
* (the driver writes it once, at its first leg) works in it; a run not yet started works from the install's project. */
|
|
129
|
+
function launchProject({ install, project, runDir }) {
|
|
130
|
+
const own = runDir ? path.join(runDir, 'project') : '';
|
|
131
|
+
return own && fs.existsSync(own) ? own : path.join(orchOf(install), 'projects', project);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function cache({ install, project, projectConfigDir, codeline, variant = process.env.EPAM_BROWNFIELD === '1' ? 'brownfield' : '', maxRebuild = 0 }) {
|
|
128
135
|
const O = orchOf(install);
|
|
129
|
-
const
|
|
136
|
+
const PCD = projectConfigDir || path.join(O, 'projects', project);
|
|
137
|
+
const C = path.join(PCD, '.prompt-cache', codeline);
|
|
130
138
|
const b = require(path.join(scriptsOf(install), 'lib', 'project-prompt-builder.js'));
|
|
131
139
|
const tpl = (t) => path.join(O, 'prompts', 'templates', `${t}.json`);
|
|
132
140
|
// A COMPLETE SET IS REUSED WHOLE (2026-10-22): the mint step keeps a codeline whose set is complete ("completed its agents and
|
|
133
141
|
// prompts — kept") and no prompt is built, so per-prompt entries are not needed — the builder's own test, as the mint step's
|
|
134
142
|
const prev = process.env.EPAM_BROWNFIELD; process.env.EPAM_BROWNFIELD = variant === 'brownfield' ? '1' : '';
|
|
135
143
|
let whole;
|
|
136
|
-
try { whole = b.codelineSetComplete({ projectConfigDir:
|
|
144
|
+
try { whole = b.codelineSetComplete({ projectConfigDir: PCD, codeline, templatesDir: path.join(O, 'prompts', 'templates'), registryFile: path.join(O, 'agents', 'invocation-profiles.json') }); }
|
|
137
145
|
finally { if (prev === undefined) delete process.env.EPAM_BROWNFIELD; else process.env.EPAM_BROWNFIELD = prev; }
|
|
138
146
|
if (whole && whole.complete) return res('cache', true, `${codeline}: its complete set is reused whole by the mint step — nothing rebuilt`, { required: 0, missing: [], willRebuild: [] });
|
|
139
147
|
const problems = [];
|
|
@@ -141,7 +149,7 @@ function cache({ install, project, codeline, variant = process.env.EPAM_BROWNFIE
|
|
|
141
149
|
if (!prompts.length) problems.push(`no cached prompt set (${path.join(C, 'prompts')})`);
|
|
142
150
|
const minted = b.MINTED_FILES.filter((f) => !fs.existsSync(path.join(C, 'minted', f)));
|
|
143
151
|
if (minted.length) problems.push(`minted files missing: ${minted.join(', ')}`);
|
|
144
|
-
const marker = path.join(
|
|
152
|
+
const marker = path.join(PCD, '.prompt-cache', `.complete-${codeline}${variant ? `.${variant}` : ''}`);
|
|
145
153
|
if (!fs.existsSync(marker)) problems.push(`no completion marker ${path.basename(marker)}`);
|
|
146
154
|
const list = b.provisioningList({ bootstrap: readJson(path.join(O, 'prompts', 'bootstrap.json'), {}), registry: readJson(path.join(O, 'agents', 'invocation-profiles.json'), {}), templateExists: (t) => fs.existsSync(tpl(t)), templatesDir: path.join(O, 'prompts', 'templates') });
|
|
147
155
|
const multi = (t) => Object.prototype.hasOwnProperty.call(readJson(tpl(t), {}), 'bodies');
|
|
@@ -159,12 +167,12 @@ function cache({ install, project, codeline, variant = process.env.EPAM_BROWNFIE
|
|
|
159
167
|
* perfect"): each codeline folder's recorded agents and prompts, and its completion built from the current inputs
|
|
160
168
|
* (project-prompt-builder.js codelineSetComplete). A lane whose codeline has none does not run, so the launch is not started.
|
|
161
169
|
*/
|
|
162
|
-
function codelineSets({ install, project, codelines = [], env = {} }) {
|
|
170
|
+
function codelineSets({ install, project, projectConfigDir, codelines = [], env = {} }) {
|
|
163
171
|
const O = orchOf(install);
|
|
164
172
|
const b = require(path.join(scriptsOf(install), 'lib', 'project-prompt-builder.js'));
|
|
165
173
|
const prev = process.env.EPAM_BROWNFIELD; process.env.EPAM_BROWNFIELD = env.EPAM_BROWNFIELD === '1' ? '1' : '';
|
|
166
174
|
try {
|
|
167
|
-
const rows = codelines.map((codeline) => ({ codeline, ...b.codelineSetComplete({ projectConfigDir: path.join(O, 'projects', project), codeline,
|
|
175
|
+
const rows = codelines.map((codeline) => ({ codeline, ...b.codelineSetComplete({ projectConfigDir: projectConfigDir || path.join(O, 'projects', project), codeline,
|
|
168
176
|
templatesDir: path.join(O, 'prompts', 'templates'), registryFile: path.join(O, 'agents', 'invocation-profiles.json') }) }));
|
|
169
177
|
const bad = rows.filter((r) => !r.complete);
|
|
170
178
|
if (!codelines.length) return res('codeline-sets', false, 'no codeline named — the sets every lane works from cannot be checked');
|
|
@@ -322,8 +330,9 @@ function prelaunch(o) {
|
|
|
322
330
|
results.push(langfuse({ install: o.install, env: o.env, runId: o.runId, outDir: o.outDir }));
|
|
323
331
|
if (o.ticket) results.push(seed({ install: o.install, project: o.project, ticket: o.ticket, runsRoots: o.runsRoots || [] }));
|
|
324
332
|
// the variant (brownfield) is the run's, from the env the launch hands over — not this process's own environment
|
|
325
|
-
|
|
326
|
-
if (
|
|
333
|
+
const pcd = launchProject(o);
|
|
334
|
+
if (o.codeline) results.push(cache({ install: o.install, project: o.project, projectConfigDir: pcd, codeline: o.codeline, variant: (o.env || {}).EPAM_BROWNFIELD === '1' ? 'brownfield' : '', maxRebuild: o.maxRebuild || 0 }));
|
|
335
|
+
if (Array.isArray(o.codelines)) results.push(codelineSets({ install: o.install, project: o.project, projectConfigDir: pcd, codelines: o.codelines, env: o.env || {} }));
|
|
327
336
|
if (o.copy) results.push(permissions({ install: o.install, project: o.project, runDir: o.runDir, copy: o.copy }));
|
|
328
337
|
results.push(cost({ install: o.install, set: o.set || o.env.EPAM_PROVIDER_SET || 'claude', tmpDir: o.outDir }));
|
|
329
338
|
results.push(alone({ install: o.install }));
|
|
@@ -337,7 +346,7 @@ function prelaunch(o) {
|
|
|
337
346
|
return report;
|
|
338
347
|
}
|
|
339
348
|
|
|
340
|
-
module.exports = { prelaunch, prelaunchCli, preflight, langfuse, langfuseEnv, seed, cache, codelineSets, permissions, cost, ladderModels, alone, memory, noTimeout, checklist, ancestors };
|
|
349
|
+
module.exports = { prelaunch, prelaunchCli, preflight, langfuse, langfuseEnv, seed, cache, codelineSets, launchProject, permissions, cost, ladderModels, alone, memory, noTimeout, checklist, ancestors };
|
|
341
350
|
|
|
342
351
|
/**
|
|
343
352
|
* THE COMMAND, for every pipeline:
|
|
@@ -72,6 +72,26 @@ lane_codeline_set_restore() {
|
|
|
72
72
|
local _prd="${1:-}"
|
|
73
73
|
[ -n "$_prd" ] && [ -f "$_prd" ] && [ -n "${EPAM_PROJECT_CONFIG_DIR:-}" ] || { echo "[prompts] lane: no PRD or project to resolve its codeline's set from" >&2; return 1; }
|
|
74
74
|
local _here; _here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
75
|
+
# A STALE SET IS REFRESHED IN THE LEG (operator, 2026-10-24: "I asked for doctor to have full scope"): a codeline whose recorded set is
|
|
76
|
+
# no longer complete for the current templates has it brought up to date by the pipeline's own builder, in the story's context (the
|
|
77
|
+
# run's own PRD), before the lane restores it — inside the leg, so a failure is the lane's and the doctor's, never a hand-run step.
|
|
78
|
+
# The command is EPAM_PROMPT_REFRESH_CMD when set (as AI_RUNNER_CMD is), else the pipeline's refresh-project-prompts.js.
|
|
79
|
+
local _stale
|
|
80
|
+
_stale=$("${NODE_BIN:-node}" -e '
|
|
81
|
+
const b = require(process.argv[1]);
|
|
82
|
+
const codeline = b.codelineOfPrd(process.argv[3]);
|
|
83
|
+
const r = codeline && b.hasMintedSnapshot({ projectConfigDir: process.argv[2], codeline }) ? b.codelineSetComplete({ projectConfigDir: process.argv[2], codeline }) : { complete: true };
|
|
84
|
+
process.stdout.write(r.complete ? "" : `${codeline}\t${r.reason || ""}`);
|
|
85
|
+
' "${_here}/project-prompt-builder.js" "$EPAM_PROJECT_CONFIG_DIR" "$_prd" 2>/dev/null) || _stale=""
|
|
86
|
+
if [ -n "$_stale" ]; then
|
|
87
|
+
local _scl="${_stale%% *}"
|
|
88
|
+
echo "[prompts] lane: codeline ${_scl}'s recorded set is stale (${_stale#* }) — refreshed now by the pipeline's own builder" >&2
|
|
89
|
+
if ! ${EPAM_PROMPT_REFRESH_CMD:-"${NODE_BIN:-node}" "${_here}/../refresh-project-prompts.js"} --project "$EPAM_PROJECT_CONFIG_DIR" \
|
|
90
|
+
--prd "${EPAM_RUN_PRD:-$_prd}" --codeline "$_scl" --log-dir "${LOG_DIR:-${EPAM_PROJECT_CONFIG_DIR}/logs}/refresh-prompts" >&2; then
|
|
91
|
+
echo "[prompts] lane: codeline ${_scl}'s set could not be refreshed — the lane does not run a stale set" >&2
|
|
92
|
+
return 1
|
|
93
|
+
fi
|
|
94
|
+
fi
|
|
75
95
|
local _out
|
|
76
96
|
_out=$("${NODE_BIN:-node}" -e '
|
|
77
97
|
const b = require(process.argv[1]);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// byte for byte with no call, one whose template moved on is regenerated and reviewed (lib/prompt-build-calls.js, the
|
|
9
9
|
// mint's own generator and reviewer). The builder records the codeline's completion itself.
|
|
10
10
|
//
|
|
11
|
-
// refresh-project-prompts.js --project <project config dir> --prd <run PRD> [--log-dir <dir>] [--stand-in]
|
|
11
|
+
// refresh-project-prompts.js --project <project config dir> --prd <run PRD> [--codeline <id>] [--log-dir <dir>] [--stand-in]
|
|
12
12
|
//
|
|
13
13
|
// The codelines are the PRD's outputDirs, each one's id as the builder files it (codelineFromPrd of a one-codeline PRD).
|
|
14
14
|
// --stand-in: no model is called — the generator answers with the template's own text and the reviewer approves — so
|
|
@@ -54,6 +54,8 @@ async function main() {
|
|
|
54
54
|
const slice = path.join(logDir, `prd.${path.basename(o.path)}.json`);
|
|
55
55
|
fs.writeFileSync(slice, JSON.stringify({ ...prd, project: { ...prd.project, outputDirs: [o], outputDir: o.path } }));
|
|
56
56
|
const codeline = builder.codelineFromPrd(slice);
|
|
57
|
+
// --codeline <id>: only that codeline's set (a lane refreshing its own stale set, lib/prompt-variant.sh lane_codeline_set_restore)
|
|
58
|
+
if (a.codeline && codeline !== a.codeline) continue;
|
|
57
59
|
process.env.EPAM_CODELINE_ID = codeline;
|
|
58
60
|
process.env.EPAM_PROJECT_CONFIG_DIR = projectConfigDir;
|
|
59
61
|
process.env.PRD_FILE = slice;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "amsd-pipeline-shared",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.37",
|
|
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": {
|