@codeam/shared 2.75.8 → 2.75.9
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/index.d.mts +108 -9
- package/dist/index.d.ts +108 -9
- package/dist/index.js +185 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +180 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2592,6 +2592,9 @@ function normalizeGuardrailPolicy(raw) {
|
|
|
2592
2592
|
var GUARDRAIL_CONFIGURE_COMMAND = "guardrail_configure";
|
|
2593
2593
|
|
|
2594
2594
|
// src/packs/types.ts
|
|
2595
|
+
var PACK_FINDINGS_FILE = "REVIEW-FINDINGS.pack.json";
|
|
2596
|
+
var MAX_PACK_FINDINGS = 50;
|
|
2597
|
+
var PACK_HANDOFF_HEADING = "## Handoff";
|
|
2595
2598
|
var PACK_START_COMMAND = "pack_start";
|
|
2596
2599
|
var PACK_ACTION_COMMAND = "pack_action";
|
|
2597
2600
|
var PACK_STATUS_COMMAND = "pack_status";
|
|
@@ -2611,6 +2614,8 @@ Method:
|
|
|
2611
2614
|
- **Verification plan** \u2014 for each criterion, the level that proves it (unit / integration / manual) and why.
|
|
2612
2615
|
3. Right-size: if the task is clearly too large for one pipeline run, narrow the criteria to a coherent first slice and record the rest under "Out of scope / next".
|
|
2613
2616
|
|
|
2617
|
+
4. Close with a \`## Handoff\` section: the criteria count, what you scoped out, and any assumption the Coder must know.
|
|
2618
|
+
|
|
2614
2619
|
Handoff bar: the spec file is committed; every acceptance criterion is testable as written; a competent implementer could start without asking you anything.`;
|
|
2615
2620
|
var CODER_PROMPT = `# Role: Coder
|
|
2616
2621
|
|
|
@@ -2621,6 +2626,7 @@ Method:
|
|
|
2621
2626
|
2. Test-first where it fits: write the test that proves a criterion, watch it fail, implement until it passes. Where strict test-first doesn't fit, still land tests alongside the change.
|
|
2622
2627
|
3. Match the project's existing style, structure, and conventions. Simplest design that fully solves the problem \u2014 no speculative abstractions, no "while I'm here" changes.
|
|
2623
2628
|
4. Run the project's tests / linters / build and make them pass.
|
|
2629
|
+
5. Close with a \`## Handoff\` section: which criteria are implemented (by number) and where their tests live, anything you consciously did NOT do, and what the Reviewer should look at first.
|
|
2624
2630
|
|
|
2625
2631
|
Handoff bar: every acceptance criterion is implemented and covered by a test; the project's checks pass; the work is committed in focused commits.`;
|
|
2626
2632
|
var REVIEWER_PROMPT = `# Role: Reviewer
|
|
@@ -2636,21 +2642,42 @@ Method:
|
|
|
2636
2642
|
- **Conventions & naming** \u2014 matches the surrounding code; names say what things are.
|
|
2637
2643
|
- **Safety** \u2014 no secrets, credentials, or debugging remnants in code, tests, or fixtures.
|
|
2638
2644
|
3. Fix what is justified \u2014 smallest change that resolves the finding, keeping behavior. Re-run the checks after material fixes.
|
|
2639
|
-
4.
|
|
2640
|
-
|
|
2641
|
-
|
|
2645
|
+
4. Write your findings as DATA to \`REVIEW-FINDINGS.pack.json\` at the repo root \u2014 the next stage verifies them one by one, so what is not in this file does not get verified. Exact shape:
|
|
2646
|
+
\`\`\`json
|
|
2647
|
+
{
|
|
2648
|
+
"findings": [
|
|
2649
|
+
{
|
|
2650
|
+
"id": "R1",
|
|
2651
|
+
"severity": "blocker | major | minor | nit",
|
|
2652
|
+
"title": "one line: what is wrong",
|
|
2653
|
+
"detail": "why it matters and what you did about it",
|
|
2654
|
+
"file": "src/path/to/file.ts",
|
|
2655
|
+
"line": 42,
|
|
2656
|
+
"resolution": "fixed | deferred | wont_fix | needs_verification",
|
|
2657
|
+
"commit": "abcdef1234"
|
|
2658
|
+
}
|
|
2659
|
+
],
|
|
2660
|
+
"checked": ["what you audited when the list is empty: e.g. error paths of X, test coverage of Y"]
|
|
2661
|
+
}
|
|
2662
|
+
\`\`\`
|
|
2663
|
+
Every finding you fixed says \`fixed\` with its commit; anything you deliberately left says \`deferred\` or \`wont_fix\` with the reason in \`detail\`; anything you could not verify says \`needs_verification\`. An empty \`findings\` array is a valid, honest result \u2014 then \`checked\` must say what you looked at. Commit this file with your stage.
|
|
2664
|
+
5. Close with a \`## Handoff\` section: what you found (counts by severity), what you fixed, what you deliberately left, and what the next stage must verify.
|
|
2665
|
+
|
|
2666
|
+
Handoff bar: checks pass on YOUR final commit; every fix is committed; \`REVIEW-FINDINGS.pack.json\` is committed and lists every finding with its resolution (an empty list says what you checked).`;
|
|
2642
2667
|
var QA_PROMPT = `# Role: QA
|
|
2643
2668
|
|
|
2644
2669
|
You are the final gate. You verify the delivered work against the acceptance criteria as a whole \u2014 end to end, the way a demanding user would \u2014 and produce the run's closing report.
|
|
2645
2670
|
|
|
2646
2671
|
Method:
|
|
2647
2672
|
1. Read the task and \`SPEC.pack.md\` (when present). Your contract is the acceptance criteria; without a spec, derive them from the task.
|
|
2648
|
-
2.
|
|
2649
|
-
3.
|
|
2650
|
-
4.
|
|
2651
|
-
5.
|
|
2673
|
+
2. Read \`REVIEW-FINDINGS.pack.json\` (when present \u2014 the Reviewer's structured findings, also summarized in your handoff input). Every finding there is an item on YOUR checklist: a \`fixed\` one must be verified fixed without regression; a \`deferred\`/\`wont_fix\` one must be judged acceptable or escalated; a \`needs_verification\` one is yours to settle.
|
|
2674
|
+
3. For EACH criterion, verify it against the real project: run the relevant tests, execute the code paths where feasible, inspect actual behavior/output. Do not take earlier stages' word for anything.
|
|
2675
|
+
4. Run the project's full checks (tests, lint, types, build) one final time.
|
|
2676
|
+
5. Write \`QA-REPORT.pack.md\` at the repo root with two sections: **Acceptance criteria** \u2014 per-criterion verdict (\u2705 verified / \u26A0\uFE0F partially / \u274C failed \u2014 with evidence for each); **Review findings** \u2014 per finding id, verdict (\u2705 verified fixed / \u26A0\uFE0F still open / \u274C regressed \u2014 with evidence). Then the checks' results, anything not verifiable in this environment (stated plainly), and a short "ready to ship?" conclusion.
|
|
2677
|
+
6. If a criterion FAILS: fix it only when the fix is small and unambiguous; otherwise mark it failed with exact evidence \u2014 the user decides. Never paper over a failure.
|
|
2678
|
+
7. Close with a \`## Handoff\` section: the ship/no-ship conclusion, the failed or open items by id, and what you could not verify.
|
|
2652
2679
|
|
|
2653
|
-
Handoff bar: the report is committed; every verdict carries evidence; the conclusion is honest about anything unverified.`;
|
|
2680
|
+
Handoff bar: the report is committed; every verdict carries evidence; every finding id from the Reviewer appears in the report; the conclusion is honest about anything unverified.`;
|
|
2654
2681
|
|
|
2655
2682
|
// src/packs/registry.ts
|
|
2656
2683
|
var PACK_REGISTRY = {
|
|
@@ -2674,7 +2701,9 @@ var PACK_REGISTRY = {
|
|
|
2674
2701
|
skillIds: ["code-review", "code-naming"],
|
|
2675
2702
|
prompt: REVIEWER_PROMPT,
|
|
2676
2703
|
// Review-only: approving clean with no change is success, not a stall.
|
|
2677
|
-
requiresCommit: false
|
|
2704
|
+
requiresCommit: false,
|
|
2705
|
+
// Leaves REVIEW-FINDINGS.pack.json — the next stage gets a list, not prose.
|
|
2706
|
+
producesFindings: true
|
|
2678
2707
|
}
|
|
2679
2708
|
]
|
|
2680
2709
|
},
|
|
@@ -2705,7 +2734,9 @@ var PACK_REGISTRY = {
|
|
|
2705
2734
|
skillIds: ["code-review", "code-naming"],
|
|
2706
2735
|
prompt: REVIEWER_PROMPT,
|
|
2707
2736
|
// Review-only: approving clean with no change is success, not a stall.
|
|
2708
|
-
requiresCommit: false
|
|
2737
|
+
requiresCommit: false,
|
|
2738
|
+
// Leaves REVIEW-FINDINGS.pack.json — the next stage gets a list, not prose.
|
|
2739
|
+
producesFindings: true
|
|
2709
2740
|
},
|
|
2710
2741
|
{
|
|
2711
2742
|
role: "qa",
|
|
@@ -2735,8 +2766,140 @@ You are ONE specialist role in a multi-role pipeline running on this repository.
|
|
|
2735
2766
|
- **Never leave the tree broken.** Run the project's checks before finishing when the project has them; your stage ends with a working tree the next role can build on.
|
|
2736
2767
|
- **Do not push, force-push, or touch remotes** \u2014 the pipeline works locally; publishing is the user's call at the end.
|
|
2737
2768
|
- **Never read, edit, or commit anything under \`.codeam/\`** \u2014 that is the pipeline's own ledger, not project code.
|
|
2738
|
-
- **Finish
|
|
2739
|
-
- **If you
|
|
2769
|
+
- **Finish with a \`## Handoff\` section.** When your stage's job is done and committed, end your reply with a heading \`## Handoff\` followed by 2-6 lines: what you did, what you verified, anything the next stage must know. That section \u2014 not the rest of your reply \u2014 is what the next role receives. Don't ask "should I continue?" \u2014 the pipeline advances automatically.
|
|
2770
|
+
- **If you need the user's decision** (contradictory requirements, a real product choice), ask ONE clear question and end your reply with 2-4 numbered options on their own lines (\`1. \u2026\`), then stop. The pipeline pauses until they answer in this conversation; keep working in it once they do, and commit as usual.
|
|
2771
|
+
- **If you are genuinely blocked** (missing access, a broken environment you cannot fix), say exactly what is blocking you and stop \u2014 the user is supervising and will decide.`;
|
|
2772
|
+
|
|
2773
|
+
// src/packs/findings.ts
|
|
2774
|
+
var SEVERITIES = /* @__PURE__ */ new Set([
|
|
2775
|
+
"blocker",
|
|
2776
|
+
"major",
|
|
2777
|
+
"minor",
|
|
2778
|
+
"nit"
|
|
2779
|
+
]);
|
|
2780
|
+
var RESOLUTIONS = /* @__PURE__ */ new Set([
|
|
2781
|
+
"fixed",
|
|
2782
|
+
"deferred",
|
|
2783
|
+
"wont_fix",
|
|
2784
|
+
"needs_verification"
|
|
2785
|
+
]);
|
|
2786
|
+
var TITLE_MAX = 200;
|
|
2787
|
+
var DETAIL_MAX = 1200;
|
|
2788
|
+
function parsePackFindings(raw) {
|
|
2789
|
+
const text = stripFence(raw).trim();
|
|
2790
|
+
if (text.length === 0) return { ok: false, error: "findings file is empty" };
|
|
2791
|
+
let data;
|
|
2792
|
+
try {
|
|
2793
|
+
data = JSON.parse(text);
|
|
2794
|
+
} catch {
|
|
2795
|
+
const salvaged = salvageJson(text);
|
|
2796
|
+
if (salvaged === null) return { ok: false, error: "findings file is not valid JSON" };
|
|
2797
|
+
data = salvaged;
|
|
2798
|
+
}
|
|
2799
|
+
const container = Array.isArray(data) ? { findings: data } : data;
|
|
2800
|
+
if (!isRecord(container) || !Array.isArray(container.findings)) {
|
|
2801
|
+
return { ok: false, error: 'findings file has no "findings" array' };
|
|
2802
|
+
}
|
|
2803
|
+
const findings = [];
|
|
2804
|
+
let dropped = 0;
|
|
2805
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2806
|
+
for (const entry of container.findings) {
|
|
2807
|
+
const f = coerceFinding(entry, findings.length + 1);
|
|
2808
|
+
if (!f) {
|
|
2809
|
+
dropped += 1;
|
|
2810
|
+
continue;
|
|
2811
|
+
}
|
|
2812
|
+
if (seen.has(f.id)) f.id = `${f.id}-${findings.length + 1}`;
|
|
2813
|
+
seen.add(f.id);
|
|
2814
|
+
findings.push(f);
|
|
2815
|
+
if (findings.length >= MAX_PACK_FINDINGS) break;
|
|
2816
|
+
}
|
|
2817
|
+
const truncated = container.findings.length - dropped - findings.length;
|
|
2818
|
+
const checked = Array.isArray(container.checked) ? container.checked.filter((c) => typeof c === "string" && c.trim().length > 0).slice(0, 20) : void 0;
|
|
2819
|
+
const notes = [];
|
|
2820
|
+
if (dropped > 0) notes.push(`${dropped} malformed entr${dropped === 1 ? "y" : "ies"} dropped`);
|
|
2821
|
+
if (truncated > 0)
|
|
2822
|
+
notes.push(`list truncated to ${MAX_PACK_FINDINGS} (${truncated} more in the file)`);
|
|
2823
|
+
return {
|
|
2824
|
+
ok: true,
|
|
2825
|
+
value: {
|
|
2826
|
+
findings,
|
|
2827
|
+
...checked && checked.length > 0 ? { checked } : {},
|
|
2828
|
+
...notes.length > 0 ? { note: notes.join("; ") } : {}
|
|
2829
|
+
}
|
|
2830
|
+
};
|
|
2831
|
+
}
|
|
2832
|
+
function coerceFinding(entry, ordinal) {
|
|
2833
|
+
if (!isRecord(entry)) return null;
|
|
2834
|
+
const title = str(entry.title) ?? str(entry.summary);
|
|
2835
|
+
if (!title) return null;
|
|
2836
|
+
const id = str(entry.id) ?? `R${ordinal}`;
|
|
2837
|
+
const severityRaw = (str(entry.severity) ?? "").toLowerCase();
|
|
2838
|
+
const resolutionRaw = (str(entry.resolution) ?? str(entry.status) ?? "").toLowerCase().replace(/[\s-]+/g, "_");
|
|
2839
|
+
const line = typeof entry.line === "number" && Number.isFinite(entry.line) && entry.line > 0 ? Math.floor(entry.line) : void 0;
|
|
2840
|
+
const detail = str(entry.detail) ?? str(entry.description);
|
|
2841
|
+
const file = str(entry.file) ?? str(entry.path);
|
|
2842
|
+
const commit = str(entry.commit);
|
|
2843
|
+
return {
|
|
2844
|
+
id: id.slice(0, 32),
|
|
2845
|
+
severity: SEVERITIES.has(severityRaw) ? severityRaw : "major",
|
|
2846
|
+
title: title.slice(0, TITLE_MAX),
|
|
2847
|
+
...detail ? { detail: detail.slice(0, DETAIL_MAX) } : {},
|
|
2848
|
+
...file ? { file: file.slice(0, 300) } : {},
|
|
2849
|
+
...line !== void 0 ? { line } : {},
|
|
2850
|
+
resolution: RESOLUTIONS.has(resolutionRaw) ? resolutionRaw : "needs_verification",
|
|
2851
|
+
...commit && /^[0-9a-f]{7,40}$/i.test(commit) ? { commit: commit.slice(0, 10) } : {}
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2854
|
+
function extractHandoffSection(reply) {
|
|
2855
|
+
const lines = reply.split("\n");
|
|
2856
|
+
const want = PACK_HANDOFF_HEADING.replace(/^#+\s*/, "").toLowerCase();
|
|
2857
|
+
let start = -1;
|
|
2858
|
+
let level = 0;
|
|
2859
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2860
|
+
const m = lines[i].match(/^\s{0,3}(#{1,4})\s+(.+?)\s*#*\s*$/);
|
|
2861
|
+
if (m && m[2].trim().toLowerCase().replace(/[:.]+$/, "") === want) {
|
|
2862
|
+
start = i;
|
|
2863
|
+
level = m[1].length;
|
|
2864
|
+
break;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
if (start < 0) return null;
|
|
2868
|
+
const body = [];
|
|
2869
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
2870
|
+
const m = lines[i].match(/^\s{0,3}(#{1,6})\s+/);
|
|
2871
|
+
if (m && m[1].length <= level) break;
|
|
2872
|
+
body.push(lines[i]);
|
|
2873
|
+
}
|
|
2874
|
+
const text = body.join("\n").trim();
|
|
2875
|
+
return text.length > 0 ? text : null;
|
|
2876
|
+
}
|
|
2877
|
+
function isRecord(v) {
|
|
2878
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2879
|
+
}
|
|
2880
|
+
function str(v) {
|
|
2881
|
+
return typeof v === "string" && v.trim().length > 0 ? v.trim() : void 0;
|
|
2882
|
+
}
|
|
2883
|
+
function stripFence(raw) {
|
|
2884
|
+
const m = raw.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
2885
|
+
return m ? m[1] : raw;
|
|
2886
|
+
}
|
|
2887
|
+
function salvageJson(text) {
|
|
2888
|
+
for (const [open, close] of [
|
|
2889
|
+
["{", "}"],
|
|
2890
|
+
["[", "]"]
|
|
2891
|
+
]) {
|
|
2892
|
+
const a = text.indexOf(open);
|
|
2893
|
+
const b = text.lastIndexOf(close);
|
|
2894
|
+
if (a >= 0 && b > a) {
|
|
2895
|
+
try {
|
|
2896
|
+
return JSON.parse(text.slice(a, b + 1));
|
|
2897
|
+
} catch {
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
return null;
|
|
2902
|
+
}
|
|
2740
2903
|
|
|
2741
2904
|
// src/api-url.ts
|
|
2742
2905
|
var DEFAULT_API_BASE_URL = "https://api.codeagent-mobile.com";
|
|
@@ -2982,10 +3145,13 @@ export {
|
|
|
2982
3145
|
MANAGED_AGENT_SUBTITLE,
|
|
2983
3146
|
MANAGED_PROVIDER_DISPLAY_NAMES,
|
|
2984
3147
|
MANAGED_PROVIDER_IDS,
|
|
3148
|
+
MAX_PACK_FINDINGS,
|
|
2985
3149
|
MODEL_CONTEXT_WINDOW,
|
|
2986
3150
|
MODEL_PRICING,
|
|
2987
3151
|
OBSERVER_BRIDGE_PORT,
|
|
2988
3152
|
PACK_ACTION_COMMAND,
|
|
3153
|
+
PACK_FINDINGS_FILE,
|
|
3154
|
+
PACK_HANDOFF_HEADING,
|
|
2989
3155
|
PACK_REGISTRY,
|
|
2990
3156
|
PACK_START_COMMAND,
|
|
2991
3157
|
PACK_STATUS_COMMAND,
|
|
@@ -3013,6 +3179,7 @@ export {
|
|
|
3013
3179
|
clampHopBudget,
|
|
3014
3180
|
classifyStack,
|
|
3015
3181
|
detectedIntegrationsFromDeps,
|
|
3182
|
+
extractHandoffSection,
|
|
3016
3183
|
getAgent,
|
|
3017
3184
|
getContextWindow,
|
|
3018
3185
|
getEnabledAgents,
|
|
@@ -3036,6 +3203,7 @@ export {
|
|
|
3036
3203
|
isSkillId,
|
|
3037
3204
|
normalizeAgentId,
|
|
3038
3205
|
normalizeGuardrailPolicy,
|
|
3206
|
+
parsePackFindings,
|
|
3039
3207
|
publicToInternal,
|
|
3040
3208
|
recommendForDeps,
|
|
3041
3209
|
renderToLines,
|