@dadado/agent-kit-cli 5.15.1 → 5.17.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.
- package/dashboard/dashboard-data.mjs +69 -65
- package/dashboard/lib/guards.d.mts +5 -0
- package/dashboard/lib/guards.mjs +31 -0
- package/dashboard/lib/identity-probe.mjs +56 -0
- package/dashboard/lib/pipeline-cache.mjs +58 -0
- package/dashboard/lib/processes.mjs +71 -0
- package/dashboard/serve.mjs +43 -1
- package/dashboard/start-broadcast.mjs +2 -12
- package/dashboard/start.mjs +2 -13
- package/dist/add-HTYIFKMN.js +150 -0
- package/dist/chunk-2IPXQFJE.js +253 -0
- package/dist/chunk-2RDRMGD3.js +82 -0
- package/dist/chunk-2YU2H7I6.js +42 -0
- package/dist/chunk-4IWG5CVE.js +214 -0
- package/dist/chunk-5VCOWTTP.js +6 -0
- package/dist/chunk-77V75A7O.js +39 -0
- package/dist/chunk-7HDQEK6T.js +26 -0
- package/dist/chunk-AW74INUW.js +1456 -0
- package/dist/chunk-B73KQ5KX.js +972 -0
- package/dist/chunk-CBCW5R5J.js +484 -0
- package/dist/chunk-DE3LQFSJ.js +18 -0
- package/dist/chunk-DQA434Y4.js +106 -0
- package/dist/chunk-F4VMYR7U.js +318 -0
- package/dist/chunk-F6C3GFKV.js +57 -0
- package/dist/chunk-HFUH3HVS.js +282 -0
- package/dist/chunk-HS7LVVLO.js +74 -0
- package/dist/chunk-IHROBTNM.js +135 -0
- package/dist/chunk-KD2MYBB6.js +213 -0
- package/dist/chunk-MAPOQEA2.js +43 -0
- package/dist/chunk-N3HTJVBR.js +341 -0
- package/dist/chunk-NQ7IQ5XT.js +26 -0
- package/dist/chunk-OUQZC744.js +1315 -0
- package/dist/chunk-PCCQUWE5.js +817 -0
- package/dist/chunk-PNFF6OU3.js +273 -0
- package/dist/chunk-PNG7LO2F.js +53 -0
- package/dist/chunk-QTON2GQX.js +203 -0
- package/dist/chunk-S6GMFDKV.js +50 -0
- package/dist/chunk-SMGFN3Z4.js +503 -0
- package/dist/chunk-STGFBAYT.js +641 -0
- package/dist/chunk-TFZ2JUXH.js +1081 -0
- package/dist/chunk-VY7MTPJ2.js +205 -0
- package/dist/chunk-W24CMQ32.js +525 -0
- package/dist/chunk-WW3YZKHW.js +165 -0
- package/dist/chunk-ZB43YMHW.js +20 -0
- package/dist/chunk-ZCTSUQRR.js +874 -0
- package/dist/chunk-ZXKZBTXE.js +17 -0
- package/dist/contribute-C6AW2P6J.js +367 -0
- package/dist/cursor-awareness-KTL2RGKD.js +77 -0
- package/dist/dashboard-YSNUGBFY.js +21 -0
- package/dist/dashboard-broadcast-M4CMW7RX.js +119 -0
- package/dist/diff-VHNR62SI.js +74 -0
- package/dist/doctor-PET2HRRJ.js +236 -0
- package/dist/dogfood-KKFVRWT6.js +366 -0
- package/dist/guard-EHXF76ID.js +530 -0
- package/dist/handoff-3UI6VKVG.js +302 -0
- package/dist/hook-DYIMKJYL.js +1074 -0
- package/dist/index.js +62 -14068
- package/dist/init-Q4LBM6KT.js +127 -0
- package/dist/install-RHOS3OYZ.js +34 -0
- package/dist/mission-control-LJACEVVN.js +89 -0
- package/dist/monitors-QV2IS3MP.js +176 -0
- package/dist/plan-index-JMC7Z4DW.js +44 -0
- package/dist/public-inbound-radar-WP3XF7GS.js +68 -0
- package/dist/remote-issues-SZ4HDQL5.js +44 -0
- package/dist/run-I3BFGULT.js +243 -0
- package/dist/run-plan-FO7CL4M3.js +118 -0
- package/dist/scan-NI2SWJ2E.js +33 -0
- package/dist/setup-global-M42GEODI.js +340 -0
- package/dist/status-XPVQVQMX.js +150 -0
- package/dist/update-FJ2EBZVO.js +283 -0
- package/dist/validate-V2CW7J4B.js +201 -0
- package/package.json +3 -3
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatSkippedSymlinks,
|
|
3
|
+
logApplyStats
|
|
4
|
+
} from "./chunk-HS7LVVLO.js";
|
|
5
|
+
import {
|
|
6
|
+
REGISTRY_CLI_ARGS,
|
|
7
|
+
resolveRegistryFromCli
|
|
8
|
+
} from "./chunk-PNG7LO2F.js";
|
|
9
|
+
import {
|
|
10
|
+
logger
|
|
11
|
+
} from "./chunk-ZB43YMHW.js";
|
|
12
|
+
import {
|
|
13
|
+
allPacks,
|
|
14
|
+
allSkills,
|
|
15
|
+
buildManifest,
|
|
16
|
+
findPack,
|
|
17
|
+
findSkill,
|
|
18
|
+
installPack,
|
|
19
|
+
installSkill,
|
|
20
|
+
loadAgentKitManifest,
|
|
21
|
+
loadRegistry,
|
|
22
|
+
resolveProtectedGlobs,
|
|
23
|
+
saveManifest,
|
|
24
|
+
upsertIdList
|
|
25
|
+
} from "./chunk-AW74INUW.js";
|
|
26
|
+
import "./chunk-5VCOWTTP.js";
|
|
27
|
+
import {
|
|
28
|
+
KIT_VERSION
|
|
29
|
+
} from "./chunk-7HDQEK6T.js";
|
|
30
|
+
import "./chunk-77V75A7O.js";
|
|
31
|
+
|
|
32
|
+
// src/commands/add.ts
|
|
33
|
+
import { defineCommand } from "citty";
|
|
34
|
+
var addCommand = defineCommand({
|
|
35
|
+
meta: {
|
|
36
|
+
name: "add",
|
|
37
|
+
description: "Install a skill or L1 pack from the registry."
|
|
38
|
+
},
|
|
39
|
+
args: {
|
|
40
|
+
id: {
|
|
41
|
+
type: "positional",
|
|
42
|
+
description: "Skill id or pack id from registry"
|
|
43
|
+
},
|
|
44
|
+
skill: {
|
|
45
|
+
type: "boolean",
|
|
46
|
+
description: "Force treat id as a skill (when pack shares the same id)",
|
|
47
|
+
default: false
|
|
48
|
+
},
|
|
49
|
+
pack: {
|
|
50
|
+
type: "boolean",
|
|
51
|
+
description: "Force treat id as a pack (when skill shares the same id)",
|
|
52
|
+
default: false
|
|
53
|
+
},
|
|
54
|
+
cwd: {
|
|
55
|
+
type: "string",
|
|
56
|
+
default: process.cwd()
|
|
57
|
+
},
|
|
58
|
+
...REGISTRY_CLI_ARGS
|
|
59
|
+
},
|
|
60
|
+
async run({ args }) {
|
|
61
|
+
if (!args.id) throw new Error("Provide an id: agent-kit add <skill|pack>");
|
|
62
|
+
if (args.skill && args.pack) {
|
|
63
|
+
throw new Error("Use only one of --skill or --pack");
|
|
64
|
+
}
|
|
65
|
+
const existing = await loadAgentKitManifest(args.cwd, { onWarning: logger.warn });
|
|
66
|
+
const registry = await resolveRegistryFromCli({
|
|
67
|
+
cwd: args.cwd,
|
|
68
|
+
registry: args.registry,
|
|
69
|
+
url: args.url,
|
|
70
|
+
ref: args.ref,
|
|
71
|
+
refresh: args.refresh,
|
|
72
|
+
manifest: existing
|
|
73
|
+
});
|
|
74
|
+
try {
|
|
75
|
+
const protectedGlobs = resolveProtectedGlobs(existing);
|
|
76
|
+
const index = await loadRegistry(registry.root);
|
|
77
|
+
const asSkill = allSkills(index).find((s) => s.id === args.id);
|
|
78
|
+
const asPack = allPacks(index).find((p) => p.id === args.id);
|
|
79
|
+
const base = existing ? { ...existing } : buildManifest({
|
|
80
|
+
version: KIT_VERSION,
|
|
81
|
+
profile: "default",
|
|
82
|
+
registryUrl: registry.url,
|
|
83
|
+
registryRef: registry.ref
|
|
84
|
+
});
|
|
85
|
+
const skipped = (stats) => {
|
|
86
|
+
if (stats.skippedSymlink.length === 0) return false;
|
|
87
|
+
logger.error(formatSkippedSymlinks(stats.skippedSymlink));
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
return true;
|
|
90
|
+
};
|
|
91
|
+
const finish = async (kind, id) => {
|
|
92
|
+
if (kind === "skill") base.skills = upsertIdList(base.skills, id);
|
|
93
|
+
else base.packs = upsertIdList(base.packs, id);
|
|
94
|
+
if (registry.url || registry.ref) {
|
|
95
|
+
base.registry = {
|
|
96
|
+
url: registry.url ?? base.registry?.url,
|
|
97
|
+
ref: registry.ref ?? base.registry?.ref
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
base.version = KIT_VERSION;
|
|
101
|
+
await saveManifest(args.cwd, base);
|
|
102
|
+
};
|
|
103
|
+
if (args.skill) {
|
|
104
|
+
const skill = await findSkill(registry.root, args.id);
|
|
105
|
+
const stats = await installSkill(registry.root, args.cwd, skill, { protectedGlobs });
|
|
106
|
+
logApplyStats(stats);
|
|
107
|
+
if (skipped(stats)) return;
|
|
108
|
+
await finish("skill", skill.id);
|
|
109
|
+
logger.success(`Skill '${skill.id}' added.`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (args.pack) {
|
|
113
|
+
const pack = await findPack(registry.root, args.id);
|
|
114
|
+
const stats = await installPack(registry.root, args.cwd, pack.id, { protectedGlobs });
|
|
115
|
+
logApplyStats(stats);
|
|
116
|
+
if (skipped(stats)) return;
|
|
117
|
+
await finish("pack", pack.id);
|
|
118
|
+
logger.success(`Pack '${pack.id}' added.`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (asSkill && asPack) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`'${args.id}' is both a skill and a pack. Disambiguate: agent-kit add --skill ${args.id} | agent-kit add --pack ${args.id}`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
if (asSkill) {
|
|
127
|
+
const stats = await installSkill(registry.root, args.cwd, asSkill, { protectedGlobs });
|
|
128
|
+
logApplyStats(stats);
|
|
129
|
+
if (skipped(stats)) return;
|
|
130
|
+
await finish("skill", asSkill.id);
|
|
131
|
+
logger.success(`Skill '${asSkill.id}' added.`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (asPack) {
|
|
135
|
+
const stats = await installPack(registry.root, args.cwd, asPack.id, { protectedGlobs });
|
|
136
|
+
logApplyStats(stats);
|
|
137
|
+
if (skipped(stats)) return;
|
|
138
|
+
await finish("pack", asPack.id);
|
|
139
|
+
logger.success(`Pack '${asPack.id}' added.`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
throw new Error(`'${args.id}' not found as skill or pack in registry.`);
|
|
143
|
+
} finally {
|
|
144
|
+
await registry.unlock?.();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
export {
|
|
149
|
+
addCommand
|
|
150
|
+
};
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import {
|
|
2
|
+
contextConfigPath,
|
|
3
|
+
intervalElapsed,
|
|
4
|
+
loadContextConfig
|
|
5
|
+
} from "./chunk-NQ7IQ5XT.js";
|
|
6
|
+
import {
|
|
7
|
+
fileExists,
|
|
8
|
+
writeJson
|
|
9
|
+
} from "./chunk-77V75A7O.js";
|
|
10
|
+
|
|
11
|
+
// src/lifecycle/public-inbound-radar.ts
|
|
12
|
+
import { execFile } from "child_process";
|
|
13
|
+
import { access } from "fs/promises";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { promisify } from "util";
|
|
16
|
+
var execFileAsync = promisify(execFile);
|
|
17
|
+
var PUBLIC_INBOUND_REPO = "agent-kit-startup/agent-kit";
|
|
18
|
+
var DEFAULT_PREFS = {
|
|
19
|
+
enabled: false,
|
|
20
|
+
intervalDays: 7,
|
|
21
|
+
lastCheckedAt: null
|
|
22
|
+
};
|
|
23
|
+
function emptySummary() {
|
|
24
|
+
return { issues: 0, humanPullRequests: 0, dependabotPullRequests: 0, total: 0 };
|
|
25
|
+
}
|
|
26
|
+
function summarize(items) {
|
|
27
|
+
const summary = emptySummary();
|
|
28
|
+
for (const item of items) {
|
|
29
|
+
summary.total += 1;
|
|
30
|
+
if (item.class === "issue") summary.issues += 1;
|
|
31
|
+
else if (item.class === "dependabot") summary.dependabotPullRequests += 1;
|
|
32
|
+
else summary.humanPullRequests += 1;
|
|
33
|
+
}
|
|
34
|
+
return summary;
|
|
35
|
+
}
|
|
36
|
+
function labelNames(labels) {
|
|
37
|
+
if (!Array.isArray(labels)) return [];
|
|
38
|
+
return labels.map((entry) => typeof entry === "string" ? entry : entry?.name).filter((name) => typeof name === "string" && name.length > 0);
|
|
39
|
+
}
|
|
40
|
+
function isDependabotAuthor(login) {
|
|
41
|
+
if (!login) return false;
|
|
42
|
+
const normalized = login.toLowerCase();
|
|
43
|
+
return normalized === "dependabot" || normalized === "dependabot[bot]" || normalized === "app/dependabot" || normalized.startsWith("dependabot") || normalized === "renovate" || normalized === "renovate[bot]";
|
|
44
|
+
}
|
|
45
|
+
function classifyInbound(kind, authorLogin) {
|
|
46
|
+
if (kind === "issue") return "issue";
|
|
47
|
+
return isDependabotAuthor(authorLogin) ? "dependabot" : "human-pr";
|
|
48
|
+
}
|
|
49
|
+
function readPublicInboundCheckPrefs(config) {
|
|
50
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
51
|
+
return { ...DEFAULT_PREFS };
|
|
52
|
+
}
|
|
53
|
+
const raw = config.publicInboundCheck;
|
|
54
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
55
|
+
return { ...DEFAULT_PREFS };
|
|
56
|
+
}
|
|
57
|
+
const uc = raw;
|
|
58
|
+
const intervalDays = typeof uc.intervalDays === "number" && Number.isInteger(uc.intervalDays) && uc.intervalDays >= 1 ? uc.intervalDays : DEFAULT_PREFS.intervalDays;
|
|
59
|
+
return {
|
|
60
|
+
enabled: uc.enabled === true,
|
|
61
|
+
intervalDays,
|
|
62
|
+
lastCheckedAt: typeof uc.lastCheckedAt === "string" ? uc.lastCheckedAt : null
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async function stampPublicInboundCheck(cwd, checkedAt) {
|
|
66
|
+
const existing = await loadContextConfig(cwd) ?? {};
|
|
67
|
+
const prev = existing.publicInboundCheck && typeof existing.publicInboundCheck === "object" ? { ...existing.publicInboundCheck } : {};
|
|
68
|
+
existing.publicInboundCheck = {
|
|
69
|
+
...DEFAULT_PREFS,
|
|
70
|
+
...prev,
|
|
71
|
+
lastCheckedAt: (checkedAt ?? /* @__PURE__ */ new Date()).toISOString()
|
|
72
|
+
};
|
|
73
|
+
await writeJson(contextConfigPath(cwd), existing);
|
|
74
|
+
}
|
|
75
|
+
function mapRows(kind, rows) {
|
|
76
|
+
const items = [];
|
|
77
|
+
for (const row of rows) {
|
|
78
|
+
const number = typeof row.number === "number" ? row.number : Number(row.number);
|
|
79
|
+
if (!Number.isFinite(number) || number <= 0) continue;
|
|
80
|
+
const author = row.author?.login?.trim() || "unknown";
|
|
81
|
+
const title = typeof row.title === "string" && row.title.trim() ? row.title.trim() : "(no title)";
|
|
82
|
+
const updatedAt = typeof row.updatedAt === "string" && row.updatedAt.trim() ? row.updatedAt.trim() : "";
|
|
83
|
+
const url = typeof row.url === "string" && row.url.trim() ? row.url.trim() : `https://github.com/${PUBLIC_INBOUND_REPO}/${kind === "issue" ? "issues" : "pull"}/${number}`;
|
|
84
|
+
items.push({
|
|
85
|
+
kind,
|
|
86
|
+
class: classifyInbound(kind, author),
|
|
87
|
+
number,
|
|
88
|
+
title,
|
|
89
|
+
author,
|
|
90
|
+
updatedAt,
|
|
91
|
+
url,
|
|
92
|
+
labels: labelNames(row.labels),
|
|
93
|
+
cite: `${PUBLIC_INBOUND_REPO}#${number}`
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return items;
|
|
97
|
+
}
|
|
98
|
+
async function defaultRunGh(args, options) {
|
|
99
|
+
const { stdout } = await execFileAsync("gh", args, {
|
|
100
|
+
cwd: options?.cwd,
|
|
101
|
+
encoding: "utf8",
|
|
102
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
103
|
+
timeout: 3e4
|
|
104
|
+
});
|
|
105
|
+
return stdout;
|
|
106
|
+
}
|
|
107
|
+
async function ghAvailable(runGh, cwd) {
|
|
108
|
+
try {
|
|
109
|
+
await runGh(["--version"], { cwd });
|
|
110
|
+
return true;
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function detectFactoryCheckout(cwd) {
|
|
116
|
+
const root = path.resolve(cwd);
|
|
117
|
+
try {
|
|
118
|
+
const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], {
|
|
119
|
+
cwd: root,
|
|
120
|
+
encoding: "utf8",
|
|
121
|
+
timeout: 5e3
|
|
122
|
+
});
|
|
123
|
+
if (/agent-kit-dev/i.test(stdout)) return true;
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
return fileExists(path.join(root, "dogfood", "README.md"));
|
|
127
|
+
}
|
|
128
|
+
async function listJson(runGh, cwd, resource) {
|
|
129
|
+
const stdout = await runGh(
|
|
130
|
+
[
|
|
131
|
+
resource,
|
|
132
|
+
"list",
|
|
133
|
+
"--repo",
|
|
134
|
+
PUBLIC_INBOUND_REPO,
|
|
135
|
+
"--state",
|
|
136
|
+
"open",
|
|
137
|
+
"--limit",
|
|
138
|
+
"100",
|
|
139
|
+
"--json",
|
|
140
|
+
"number,title,author,updatedAt,labels,url"
|
|
141
|
+
],
|
|
142
|
+
{ cwd }
|
|
143
|
+
);
|
|
144
|
+
const trimmed = stdout.trim();
|
|
145
|
+
if (!trimmed) return [];
|
|
146
|
+
const parsed = JSON.parse(trimmed);
|
|
147
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
148
|
+
}
|
|
149
|
+
function resultBase(status, message, factory, now, items = []) {
|
|
150
|
+
return {
|
|
151
|
+
status,
|
|
152
|
+
repo: PUBLIC_INBOUND_REPO,
|
|
153
|
+
checkedAt: now.toISOString(),
|
|
154
|
+
factory,
|
|
155
|
+
items,
|
|
156
|
+
summary: summarize(items),
|
|
157
|
+
message,
|
|
158
|
+
mutateRecommended: false
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
async function checkPublicInbound(cwd, options = {}) {
|
|
162
|
+
const now = options.now?.() ?? /* @__PURE__ */ new Date();
|
|
163
|
+
const runGh = options.runGh ?? defaultRunGh;
|
|
164
|
+
const isFactory = options.isFactory ?? detectFactoryCheckout;
|
|
165
|
+
const root = path.resolve(cwd);
|
|
166
|
+
try {
|
|
167
|
+
await access(root);
|
|
168
|
+
} catch {
|
|
169
|
+
return resultBase("error", `cwd unreadable: ${root}`, false, now);
|
|
170
|
+
}
|
|
171
|
+
const factory = await isFactory(root);
|
|
172
|
+
if (!factory) {
|
|
173
|
+
return resultBase(
|
|
174
|
+
"skipped-non-factory",
|
|
175
|
+
"Factory-only check. Aborting outside agent-kit-dev / dogfood checkout.",
|
|
176
|
+
false,
|
|
177
|
+
now
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
if (options.respectPrefs) {
|
|
181
|
+
const prefs = readPublicInboundCheckPrefs(await loadContextConfig(root));
|
|
182
|
+
if (!prefs.enabled) {
|
|
183
|
+
return resultBase(
|
|
184
|
+
"skipped-disabled",
|
|
185
|
+
"publicInboundCheck.enabled is false (opt-in). Set true in .cursor/context/config.json to nudge.",
|
|
186
|
+
true,
|
|
187
|
+
now
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
if (!intervalElapsed(prefs.lastCheckedAt, prefs.intervalDays)) {
|
|
191
|
+
return resultBase(
|
|
192
|
+
"skipped-interval",
|
|
193
|
+
`Within publicInboundCheck.intervalDays (${prefs.intervalDays}); last check ${prefs.lastCheckedAt}.`,
|
|
194
|
+
true,
|
|
195
|
+
now
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (options.offline) {
|
|
200
|
+
return resultBase("skipped-offline", "Offline flag set; skipped GitHub fetch.", true, now);
|
|
201
|
+
}
|
|
202
|
+
if (!await ghAvailable(runGh, root)) {
|
|
203
|
+
return resultBase(
|
|
204
|
+
"skipped-gh-missing",
|
|
205
|
+
"gh CLI missing or not runnable; fail-open skip.",
|
|
206
|
+
true,
|
|
207
|
+
now
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
const [issueRows, prRows] = await Promise.all([
|
|
212
|
+
listJson(runGh, root, "issue"),
|
|
213
|
+
listJson(runGh, root, "pr")
|
|
214
|
+
]);
|
|
215
|
+
const items = [...mapRows("issue", issueRows), ...mapRows("pull_request", prRows)].sort(
|
|
216
|
+
(a, b) => b.number - a.number
|
|
217
|
+
);
|
|
218
|
+
const summary = summarize(items);
|
|
219
|
+
const message = summary.total === 0 ? `No open issues or pull requests on ${PUBLIC_INBOUND_REPO}.` : `Open inbound on ${PUBLIC_INBOUND_REPO}: ${summary.issues} issue(s), ${summary.humanPullRequests} human PR(s), ${summary.dependabotPullRequests} Dependabot PR(s).`;
|
|
220
|
+
const result = resultBase("ok", message, true, now, items);
|
|
221
|
+
if (options.stamp) {
|
|
222
|
+
await stampPublicInboundCheck(root, now);
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
} catch (err) {
|
|
226
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
227
|
+
if (/ENOTFOUND|ECONNREFUSED|ETIMEDOUT|network|offline|Could not resolve/i.test(detail)) {
|
|
228
|
+
return resultBase(
|
|
229
|
+
"skipped-offline",
|
|
230
|
+
`GitHub unreachable; fail-open skip (${detail}).`,
|
|
231
|
+
true,
|
|
232
|
+
now
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return resultBase("error", `Public inbound check failed: ${detail}`, true, now);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function shouldEmitPublicInboundNudge(result) {
|
|
239
|
+
if (!result || result.status !== "ok") return false;
|
|
240
|
+
if (result.mutateRecommended === true) return false;
|
|
241
|
+
const summary = result.summary;
|
|
242
|
+
if (!summary || typeof summary !== "object") return false;
|
|
243
|
+
const total = summary.total;
|
|
244
|
+
return typeof total === "number" && total > 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export {
|
|
248
|
+
PUBLIC_INBOUND_REPO,
|
|
249
|
+
stampPublicInboundCheck,
|
|
250
|
+
detectFactoryCheckout,
|
|
251
|
+
checkPublicInbound,
|
|
252
|
+
shouldEmitPublicInboundNudge
|
|
253
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
managedPairs
|
|
3
|
+
} from "./chunk-N3HTJVBR.js";
|
|
4
|
+
import {
|
|
5
|
+
isProtectedPath,
|
|
6
|
+
resolveContained,
|
|
7
|
+
resolveProtectedGlobs
|
|
8
|
+
} from "./chunk-AW74INUW.js";
|
|
9
|
+
|
|
10
|
+
// src/lifecycle/diff.ts
|
|
11
|
+
import { readFile } from "fs/promises";
|
|
12
|
+
import path from "path";
|
|
13
|
+
async function readIfExists(abs) {
|
|
14
|
+
try {
|
|
15
|
+
return await readFile(abs, "utf8");
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function comparePair(registryRoot, projectRoot, sourceRel, targetRel, protectedGlobs) {
|
|
21
|
+
const posixTarget = targetRel.split(path.sep).join("/");
|
|
22
|
+
if (isProtectedPath(posixTarget, protectedGlobs)) {
|
|
23
|
+
return { path: posixTarget, status: "protected" };
|
|
24
|
+
}
|
|
25
|
+
let sourceAbs;
|
|
26
|
+
try {
|
|
27
|
+
sourceAbs = resolveContained(registryRoot, sourceRel);
|
|
28
|
+
} catch {
|
|
29
|
+
return { path: posixTarget, status: "missing-registry" };
|
|
30
|
+
}
|
|
31
|
+
const registryContent = await readIfExists(sourceAbs);
|
|
32
|
+
if (registryContent === null) {
|
|
33
|
+
return { path: posixTarget, status: "missing-registry" };
|
|
34
|
+
}
|
|
35
|
+
let targetAbs;
|
|
36
|
+
try {
|
|
37
|
+
targetAbs = resolveContained(projectRoot, targetRel);
|
|
38
|
+
} catch {
|
|
39
|
+
return { path: posixTarget, status: "missing-local" };
|
|
40
|
+
}
|
|
41
|
+
const localContent = await readIfExists(targetAbs);
|
|
42
|
+
if (localContent === null) return { path: posixTarget, status: "missing-local" };
|
|
43
|
+
if (localContent === registryContent) return { path: posixTarget, status: "match" };
|
|
44
|
+
return { path: posixTarget, status: "drift" };
|
|
45
|
+
}
|
|
46
|
+
async function diffAgainstRegistry(registryRoot, projectRoot, manifest) {
|
|
47
|
+
const protectedGlobs = resolveProtectedGlobs(manifest);
|
|
48
|
+
const entries = [];
|
|
49
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50
|
+
const pushUnique = async (sourceRel, targetRel) => {
|
|
51
|
+
const key = targetRel.split(path.sep).join("/");
|
|
52
|
+
if (seen.has(key)) return;
|
|
53
|
+
seen.add(key);
|
|
54
|
+
entries.push(
|
|
55
|
+
await comparePair(registryRoot, projectRoot, sourceRel, targetRel, protectedGlobs)
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
const { pairs, missingSkills } = await managedPairs(registryRoot, manifest);
|
|
59
|
+
for (const { sourceRel, targetRel } of pairs) {
|
|
60
|
+
await pushUnique(sourceRel, targetRel);
|
|
61
|
+
}
|
|
62
|
+
for (const id of missingSkills) {
|
|
63
|
+
entries.push({ path: `skill:${id}`, status: "missing-registry" });
|
|
64
|
+
}
|
|
65
|
+
return entries;
|
|
66
|
+
}
|
|
67
|
+
function summarizeDiff(entries) {
|
|
68
|
+
const summary = {
|
|
69
|
+
match: 0,
|
|
70
|
+
drift: 0,
|
|
71
|
+
"missing-local": 0,
|
|
72
|
+
"missing-registry": 0,
|
|
73
|
+
protected: 0
|
|
74
|
+
};
|
|
75
|
+
for (const e of entries) summary[e.status] += 1;
|
|
76
|
+
return summary;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export {
|
|
80
|
+
diffAgainstRegistry,
|
|
81
|
+
summarizeDiff
|
|
82
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/invariants/handoff-schema.ts
|
|
2
|
+
var MACHINE_LIST_CHECKS = [
|
|
3
|
+
{
|
|
4
|
+
heading: "Backlog plans",
|
|
5
|
+
fieldLabels: ["Backlog plans", "Backlog"],
|
|
6
|
+
code: "heading-without-field-backlog"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
heading: "Parked plans",
|
|
10
|
+
fieldLabels: ["Parked plans"],
|
|
11
|
+
code: "heading-without-field-parked"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
heading: "Run queue",
|
|
15
|
+
fieldLabels: ["Run queue"],
|
|
16
|
+
code: "heading-without-field-run-queue"
|
|
17
|
+
}
|
|
18
|
+
];
|
|
19
|
+
var CITE = "agent-kit validate handoff (see .cursor/context/templates/handoff.md)";
|
|
20
|
+
function validateHandoffText(text) {
|
|
21
|
+
if (!text.trim()) return [];
|
|
22
|
+
const warnings = [];
|
|
23
|
+
for (const check of MACHINE_LIST_CHECKS) {
|
|
24
|
+
const headingRe = new RegExp(`^##\\s+${check.heading}\\s*$`, "m");
|
|
25
|
+
if (!headingRe.test(text)) continue;
|
|
26
|
+
const hasField = check.fieldLabels.some(
|
|
27
|
+
(label) => new RegExp(`^- \\*\\*${label}:\\*\\*`, "m").test(text)
|
|
28
|
+
);
|
|
29
|
+
if (!hasField) {
|
|
30
|
+
warnings.push({
|
|
31
|
+
code: check.code,
|
|
32
|
+
message: `\`## ${check.heading}\` found without \`- **${check.fieldLabels[0]}:**\` (Mission Control will miss this list; rewrite as a field bullet).`,
|
|
33
|
+
cite: CITE
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return warnings;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
validateHandoffText
|
|
42
|
+
};
|