@agent-native/core 0.49.18 → 0.49.19
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/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +5 -8
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +33 -16
- package/dist/cli/recap.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/recap.js
CHANGED
|
@@ -2256,21 +2256,30 @@ function recoverRecapFailureEnv(env = process.env) {
|
|
|
2256
2256
|
return recovered;
|
|
2257
2257
|
}
|
|
2258
2258
|
/**
|
|
2259
|
-
* Files that, if a PR touches them, would let that PR rewrite
|
|
2260
|
-
*
|
|
2261
|
-
* recap CLI from trusted base-branch source (or an installed package), so
|
|
2262
|
-
* package code such as `packages/core/**`
|
|
2263
|
-
* PR-modified CLI code.
|
|
2259
|
+
* Files that, if a PR touches them, would let that PR rewrite repo-pinned skill
|
|
2260
|
+
* instructions or agent config the trusted recap job loads. The workflow runs
|
|
2261
|
+
* the recap CLI from trusted base-branch source (or an installed package), so
|
|
2262
|
+
* normal package code such as `packages/core/**` and recap workflow YAML can be
|
|
2263
|
+
* recapped without executing PR-modified CLI code.
|
|
2264
2264
|
*/
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2265
|
+
function normalizeRecapSkillSourceMode(value) {
|
|
2266
|
+
return (value || "auto").toLowerCase();
|
|
2267
|
+
}
|
|
2268
|
+
function isRepoPinnedRecapSkillSource(value) {
|
|
2269
|
+
return normalizeRecapSkillSourceMode(value) === "repo";
|
|
2270
|
+
}
|
|
2271
|
+
export function isRecapSensitivePath(p, options = {}) {
|
|
2272
|
+
const skillSource = options.skillSource;
|
|
2273
|
+
if (/(^|\/)\.claude\//.test(p) ||
|
|
2269
2274
|
/(^|\/)CLAUDE\.md$/.test(p) ||
|
|
2270
2275
|
/(^|\/)AGENTS\.md$/.test(p) ||
|
|
2271
2276
|
/(^|\/)\.mcp\.json$/.test(p)) {
|
|
2272
2277
|
return true;
|
|
2273
2278
|
}
|
|
2279
|
+
if (isRepoPinnedRecapSkillSource(skillSource) &&
|
|
2280
|
+
/(^|\/)skills\/visual-(recap|plan|plans)\//.test(p)) {
|
|
2281
|
+
return true;
|
|
2282
|
+
}
|
|
2274
2283
|
return false;
|
|
2275
2284
|
}
|
|
2276
2285
|
/**
|
|
@@ -2330,12 +2339,19 @@ export function evaluateRecapGate(input) {
|
|
|
2330
2339
|
if (model && !/^[a-zA-Z0-9._-]{1,80}$/.test(model)) {
|
|
2331
2340
|
reasons.push("invalid VISUAL_RECAP_MODEL value (must match [a-zA-Z0-9._-]{1,80})");
|
|
2332
2341
|
}
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
//
|
|
2338
|
-
|
|
2342
|
+
const skillSource = normalizeRecapSkillSourceMode(input.skillSource);
|
|
2343
|
+
if (skillSource && !["auto", "latest", "repo"].includes(skillSource)) {
|
|
2344
|
+
reasons.push('invalid VISUAL_RECAP_SKILL_SOURCE value (expected "auto", "latest", or "repo")');
|
|
2345
|
+
}
|
|
2346
|
+
// Self-modifying guard: if this PR changes the visual-recap/visual-plan skill
|
|
2347
|
+
// when CI is explicitly pinned to repo-local skill instructions, or any agent
|
|
2348
|
+
// config the runner would load (.claude/**, CLAUDE.md, AGENTS.md, .mcp.json),
|
|
2349
|
+
// skip the ENTIRE job — not just the agent — so a PR can never rewrite what
|
|
2350
|
+
// the agent loads (skill, hooks, settings) and exfiltrate the publish/API
|
|
2351
|
+
// secrets. In the default auto/latest modes the recap prompt comes from the
|
|
2352
|
+
// trusted bundled skill, so visual skill and recap workflow files are ordinary
|
|
2353
|
+
// reviewed content and may be recapped.
|
|
2354
|
+
const hits = input.changedFiles.filter((p) => isRecapSensitivePath(p, { skillSource }));
|
|
2339
2355
|
if (hits.length) {
|
|
2340
2356
|
reasons.push(`PR modifies recap-control files (${hits.slice(0, 3).join(", ")}${hits.length > 3 ? ", …" : ""}) — skipping so untrusted PR code never runs with secrets`);
|
|
2341
2357
|
}
|
|
@@ -2428,6 +2444,7 @@ async function runGate() {
|
|
|
2428
2444
|
hasOpenai: process.env.HAS_OPENAI === "true",
|
|
2429
2445
|
agentRaw: process.env.AGENT,
|
|
2430
2446
|
model: process.env.VISUAL_RECAP_MODEL,
|
|
2447
|
+
skillSource: process.env.VISUAL_RECAP_SKILL_SOURCE,
|
|
2431
2448
|
changedFiles,
|
|
2432
2449
|
});
|
|
2433
2450
|
// If listing PR files failed, append the same fail-closed reason the inline
|
|
@@ -3022,7 +3039,7 @@ Usage:
|
|
|
3022
3039
|
VISUAL_RECAP_MODEL), the repo from $GITHUB_REPOSITORY, and the PR's changed
|
|
3023
3040
|
files from the GitHub REST API (paged, with GH_TOKEN/GITHUB_TOKEN). Skips
|
|
3024
3041
|
drafts, forks, bot authors, the missing-secret case, an invalid agent/model,
|
|
3025
|
-
and any PR that touches recap-control files (
|
|
3042
|
+
and any PR that touches recap-control files (repo-pinned skill instructions,
|
|
3026
3043
|
.claude/**, CLAUDE.md, AGENTS.md, .mcp.json) — failing CLOSED on any
|
|
3027
3044
|
file-list error. Writes run=<true|false> and agent=<claude|codex> to
|
|
3028
3045
|
$GITHUB_OUTPUT.
|