amsd-pipeline-shared 0.2.0 → 0.3.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.
@@ -59,6 +59,8 @@ content-retry ×3, the failure analyst's ladder loop, the roster review ×2). Ca
59
59
  - **On a fresh install the synthesiser cannot render its prompt**: `projects/<p>/prompts/kb-enforcement-synthesis.json`
60
60
  is a minted project prompt, absent on wf-280 ("project-authority prompt missing … Mint it"). To check against how the
61
61
  codeline cache supplies prompts before the next live leg; the self-heal listener must report a synthesis failure.
62
+ **Checked 2026-10-18: not a risk for a run with its codeline cache** — the run's project copy (run/project/prompts,
63
+ 44 prompts from .prompt-cache/<codeline>/prompts) holds it. A project with no minted or cached prompt set lacks it.
62
64
  - **The ladder position `mid` resolves to the middle tier, `high`** (seam-invocation.js resolveTierPosition: base/mid/top
63
65
  over the declared order medium/high/highest), whose chain is haiku → sonnet-5 → opus-5-5. config/llm-defaults.claude.json
64
66
  says of `medium`: "A `mid` seam never reaches Opus: 14 seams resolve here". 12 seams declare `mid` (ticket-links among
@@ -1,3 +1,4 @@
1
+ 6b83e0d700392eebdd1bae1ec233ab26 prompts/templates/codeline-discovery.json
1
2
  b2470a21b73b03abb95713f05acaa827 scripts/agent-attempt-analyst.sh
2
3
  c45cda62ef52ee95c8de6acead3408f8 scripts/lib/agent-contract.js
3
4
  f881c989bd12e76e13e017ff2d984041 scripts/lib/agent-ladder.sh
@@ -32,6 +33,6 @@ ed15fbd317db2643b19a3fd7ecd1979a scripts/lib/model-ladder.sh
32
33
  be6d0a378fa9c3bc9da6240877aaeae3 scripts/lib/tool-timeouts.js
33
34
  5574182fb27aaeabbfff261b3a8d6d39 scripts/lib/transcript-tool-calls.js
34
35
  c4b96230c15b52a845cf20fd3266fe01 scripts/llm-handler.sh
35
- 40c65de8360d5a9f59902fca26d1d7a8 scripts/update-monitor.sh
36
- dfa070b168a7c01fab8aab5a46d16192 scripts/team-lead-review.sh
37
36
  f206025f304e8320b8417a6dd6606044 scripts/spec-mode-runner.js
37
+ dfa070b168a7c01fab8aab5a46d16192 scripts/team-lead-review.sh
38
+ 40c65de8360d5a9f59902fca26d1d7a8 scripts/update-monitor.sh
@@ -1,6 +1,8 @@
1
+ prompts/templates/codeline-discovery.json
1
2
  scripts/agent-attempt-analyst.sh
2
3
  scripts/lib/agent-contract.js
3
4
  scripts/lib/agent-ladder.sh
5
+ scripts/lib/agent-messages.js
4
6
  scripts/lib/agent-si.js
5
7
  scripts/lib/constraint-compiler.js
6
8
  scripts/lib/constraint-sanity.js
@@ -32,7 +34,6 @@ scripts/lib/stage-coverage-gate.sh
32
34
  scripts/lib/tool-timeouts.js
33
35
  scripts/lib/transcript-tool-calls.js
34
36
  scripts/llm-handler.sh
35
- scripts/update-monitor.sh
36
- scripts/team-lead-review.sh
37
37
  scripts/spec-mode-runner.js
38
- scripts/lib/agent-messages.js
38
+ scripts/team-lead-review.sh
39
+ scripts/update-monitor.sh
@@ -0,0 +1,40 @@
1
+ {
2
+ "$why": [
3
+ "Moved out of lib/codeline-discovery.js buildDiscoveryPrompt on 2026-08-15 (2 of 20).",
4
+ "",
5
+ "This prompt decides which repositories a ticket belongs to, so its wording sets the scope",
6
+ "of the entire run. Extracted mechanically and pinned byte for byte by a golden capture",
7
+ "taken before the move.",
8
+ "",
9
+ "Requiring the module used to exit the requiring process: its argument check ran at import",
10
+ "time. Scoping that to direct invocation is what made the migration provable at all.",
11
+ "",
12
+ "Built from the golden OUTPUT, not from the source text. The first attempt extracted the",
13
+ "template literal verbatim and kept its JS escapes — a backslash-quote stayed two characters",
14
+ "instead of one — so the rendered prompt differed from the original by two bytes. The",
15
+ "byte-identity check caught it, which is the entire reason the golden is captured first.",
16
+ "",
17
+ "Facts added 2026-08-16. codeline-facts.json had no producer at all: every one in the repo was",
18
+ "typed by hand, so a new project had none and whatever a run learned died with it. Discovery",
19
+ "is the single producer because it is the only stage that opens every candidate repository.",
20
+ "",
21
+ "Rule 6 changed 2026-10-19 (version 3, amsd-pipeline-shared). The reason asked for \"what part of the ticket",
22
+ "it covers\", and the AC classifier reads each reason as that codeline's description (JIRA_CODELINE_DESC_*, ac-gate.js",
23
+ "codelineDesc). For a ticket naming several sites the reasons assigned work to each (\"the acceptance criteria apply to",
24
+ "GO\", \"must be wired here\"), and the classifier scoped the story to every site; where the reasons only described the",
25
+ "site (\"matching the ticket's GO component\") it chose the shared library. Same prompt, same model, both outcomes",
26
+ "(AMSD-2974, launch LIVE-AMSD-2974-8 vs the classifier probe; amsd-pipeline-workflow docs/probes/why-20261019). The",
27
+ "reason now describes the repository and its relation to the others; deciding the work stays with the classifier."
28
+ ],
29
+ "body": "You are the codeline-discovery agent for a brownfield engineering pipeline.\n\nYour task: given a set of Jira tickets and a manifest of local code repositories,\nidentify which repository (or repositories) each ticket's changes belong to.\n\nJIRA TICKETS:\n__ISSUES_SUMMARY__\n\nREPOSITORY MANIFEST (git repos only):\n__MANIFEST_SUMMARY__\n\nTHE MANIFEST ABOVE IS EVERY REPOSITORY IN THE ESTATE, in no particular order. It is\nnot ranked, not filtered and not scored: nothing has judged relevance before you, so\nposition carries no information and the first entry is not a hint.\n\nYOU HAVE TOOLS, AND THE ANSWER IS USUALLY IN THE CODE RATHER THAN IN THIS LISTING.\nNames and READMEs describe what a repository calls itself; the code shows what it\nactually implements, and two sibling repositories in the same estate routinely\ndescribe themselves almost identically.\n\n codegraph_query search indexed symbols. Pass codeline=<name from the manifest>\n to choose which repository to search; without it, a query is\n ambiguous when several are in scope.\n search find text across a repository.\n read_file open a specific file.\n list_files see how a repository is laid out.\n\nSEARCH BEFORE YOU DECIDE. Look for the thing the ticket actually asks about — the\nsymbol, the component, the configuration it names — and see which repository\ncontains it. A repository that mentions the domain in prose and a repository that\nimplements it are indistinguishable from this listing alone, and only one of them\nis the place the work belongs.\n\nRules:\n1. Match each ticket to the repository whose name, packageName, or description\n best fits the ticket's domain. Use context clues: service names, domain terms,\n technology references, component names, file path mentions.\n2. RETURN THE REPOSITORIES THE EVIDENCE SUPPORTS. An empty result stops the run,\n which is the correct outcome when the work genuinely cannot be placed — but it\n is almost never the honest answer, because you have tools and the estate is in\n front of you. Search first. If you still cannot ground a part of the ticket,\n put that part in \"unsure\" rather than selecting a repository to fill the slot:\n a guess promoted to a selection cannot be spotted afterwards, and the run will\n modify whatever you name.\n\n2a. ONE TICKET MAY SPAN SEVERAL REPOSITORIES, and you MUST return one entry for\n each. This estate is maintained as many separate codelines, so a single\n ticket routinely covers work in more than one of them — a change with both\n front-end and back-end parts, or one applied across several product areas.\n Returning a single repository for such a ticket silently drops the rest of\n the work: those repositories are never touched, and the run reports success\n having done a fraction of the job.\n\n The strongest evidence is the ticket's own \"components\" field, which is the\n tracker's record of which product areas it touches. When a ticket names\n several distinct product areas, return the repository that owns each one.\n Do not collapse them because one candidate scored highest — the ranking\n measures textual similarity to a single repository, not how much of the\n ticket that repository covers.\n\n Decide the count from the ticket. Do not aim for any particular number.\n3. SELECT ON EVIDENCE, NOT ON A HUNCH. Every selected repository must be grounded\n in something concrete you can point at:\n - a ticket component, label or phrase that names that product area, or\n - something in the repository itself (its name, its manifest, its code)\n that matches what the ticket asks for.\n POSITION IN THE LIST IS NOT EVIDENCE — there is no ranking to appeal to. Nor is\n \"it is probably the backend for X\": if you have to say likely, probably, or may\n be, you do not have evidence, you have a hunch. What you found with a tool is\n evidence, and it is the strongest kind available here.\n If a part of the ticket clearly belongs SOMEWHERE but you cannot ground it in\n one of these repositories, DO NOT SELECT ONE ANYWAY. Put it in \"unsure\" with\n what you could not resolve. An unresolved component is real information and a\n human can settle it; a guess promoted to a selection cannot be spotted later.\n Do not omit a candidate you CAN ground merely because another also fits — a\n ticket spanning several product areas needs all of them (rule 2a).\n4. Assign each selected repo a short codeline identifier: 2-20 chars, lowercase,\n alphanumeric only, no dots or dashes. Derive it from the directory name by\n removing only decoration - a domain suffix, or an organisation or platform\n prefix - and keeping the part that actually names the product. Keep every\n remaining word: for a directory \"alpha-beta-gamma\" the identifier is\n \"alphabetagamma\", NOT \"gamma\". Dropping words produces an identifier that no\n longer identifies the repository.\n5. Return exactly one entry only when the ticket genuinely belongs to exactly one\n repository. \"One entry\" is the right answer for a self-contained change, and\n the wrong answer for a ticket spanning several product areas — see rule 2a.\n6. \"reason\" must be one sentence explaining why THIS repository was selected: what the\n repository is, and how it relates to the ticket and to the other repositories you\n selected — for example, that it owns a component the ticket names, or that it uses a\n component another selected repository owns. Describe the REPOSITORY, not the work:\n do not say what must change, be built, wired or verified in it. Which repositories\n the work belongs to is decided after you, from the acceptance criteria, and it reads\n your reason as the description of the repository. Every selected repository needs its own\n reason — a single justification covering the whole set makes a wrong\n selection impossible to spot afterwards.\n7. \"evidence\" must quote the CONCRETE thing that grounds the selection: the\n ticket component/label/phrase verbatim, or the file, directory, symbol or\n manifest entry you found in that repository — including what a tool returned. It is not a second reason and not a restatement —\n if you cannot fill it without hedging, the repository belongs in \"unsure\",\n not in \"codelines\".\n8. REPORT WHAT AN AGENT WORKING IN THAT REPOSITORY WOULD NEED TO KNOW and could not\n read off the source — its \"facts\". You are the only stage that opens every\n candidate repository, so this is the one place the estate is visible at once.\n Useful facts are things like: how its tests are actually run and what they\n need in order to pass, what a build or commit hook demands before it will\n let a change through, where the source and tests live when it is not obvious,\n and any setup without which a correct change still fails.\n FACTS ARE OBSERVED, NEVER GUESSED. Each one must quote its \"source\": the file,\n script or manifest entry you read it from, verbatim enough that someone can\n open it and check. A fact you cannot source is a guess, and a guess here is\n handed to every agent that works in that repository as though it were\n established — worse than saying nothing. If you observed nothing beyond what\n the source already says, return an empty list. An empty list is an honest\n answer and it is reported; an invented fact is not detectable later.\n A FACT'S SOURCE IS A FILE INSIDE THAT REPOSITORY — its code, manifest, config,\n hooks, scripts or README. Nothing the pipeline produced is a source: not a PRD,\n not a ticket or its description, not a previous run's output, not a log. Those\n describe a ticket, not the repository; a \"fact\" taken from them is the ticket\n restated, and every later story in that repository would inherit it as truth.\n Do not restate the ticket, and do not describe what the change should be —\n these describe the REPOSITORY, and they outlive this ticket.\n\nOutput format (strict JSON, no markdown fences, no preamble, no trailing text):\n{\n \"codelines\": [\n { \"name\": \"<short-identifier-derived-from-the-directory-name>\",\n \"path\": \"/absolute/path/to/repo\",\n \"reason\": \"what this repository is, and how it relates to the ticket and to the other selected repositories\",\n \"evidence\": \"ticket component \\\"<the-component-verbatim>\\\"\",\n \"facts\": [\n { \"text\": \"what an agent working here needs to know and cannot read off the source\",\n \"source\": \"the file, script or manifest entry you read it from\" }\n ] }\n ],\n \"unsure\": [\n { \"part\": \"the part of the ticket you could not place\",\n \"why\": \"what you would need in order to place it\" }\n ]\n}",
30
+ "description": "Match each ticket to the repository or repositories its changes belong to.",
31
+ "id": "codeline-discovery",
32
+ "placeholders": [
33
+ "__ISSUES_SUMMARY__",
34
+ "__MANIFEST_SUMMARY__"
35
+ ],
36
+ "version": 3,
37
+ "seams": [
38
+ "codeline-discovery"
39
+ ]
40
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "amsd-pipeline-shared",
3
- "version": "0.2.0",
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 \u2014 retry, ladder, self-heal, cost) and the libraries it runs.",
3
+ "version": "0.3.0",
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": {
7
7
  "amsd-pipeline-shared": "bin/amsd-pipeline-shared.js"