runcastle 0.2.0 → 1.0.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/README.md +47 -0
- package/bin/runcastle.js +5580 -0
- package/drizzle/0000_amused_bruce_banner.sql +74 -0
- package/drizzle/0001_mapped_feature_flag.sql +1 -0
- package/drizzle/0002_waypoints.sql +14 -0
- package/drizzle/0003_project_closed_at.sql +1 -0
- package/drizzle/0004_events_project_id.sql +28 -0
- package/drizzle/0005_project_setting_overrides.sql +2 -0
- package/drizzle/meta/0000_snapshot.json +466 -0
- package/drizzle/meta/0001_snapshot.json +474 -0
- package/drizzle/meta/0002_snapshot.json +568 -0
- package/drizzle/meta/0003_snapshot.json +575 -0
- package/drizzle/meta/0004_snapshot.json +582 -0
- package/drizzle/meta/0005_snapshot.json +596 -0
- package/drizzle/meta/_journal.json +48 -0
- package/hook-client.ts +67 -0
- package/index.js +5424 -0
- package/package.json +24 -30
- package/pty-host.cjs +186 -0
- package/sandcastle-template/Containerfile +33 -0
- package/sandcastle-template/Dockerfile +33 -0
- package/skills/burner/implement-ticket.md +42 -0
- package/skills/burner/research-waypoint.md +45 -0
- package/skills/packs/README.md +50 -0
- package/skills/packs/runcastle/.claude-plugin/plugin.json +6 -0
- package/skills/packs/runcastle/skills/converge/SKILL.md +51 -0
- package/skills/packs/runcastle/skills/ideate/SKILL.md +81 -0
- package/skills/packs/runcastle/skills/qa/SKILL.md +30 -0
- package/skills/packs/runcastle/skills/spec/SKILL.md +43 -0
- package/skills/packs/runcastle/skills/tickets/SKILL.md +52 -0
- package/skills/packs/runcastle/skills/waypoint/SKILL.md +54 -0
- package/web/assets/index-CKZ5Z7vc.css +1 -0
- package/web/assets/index-YBuT7tTz.js +108 -0
- package/web/index.html +13 -0
- package/dist/add-DD7G73HH.js +0 -315
- package/dist/add-DD7G73HH.js.map +0 -1
- package/dist/chunk-44KDPUYJ.js +0 -49
- package/dist/chunk-44KDPUYJ.js.map +0 -1
- package/dist/chunk-5VPKMXSV.js +0 -190
- package/dist/chunk-5VPKMXSV.js.map +0 -1
- package/dist/chunk-6CWCR5SO.js +0 -24
- package/dist/chunk-6CWCR5SO.js.map +0 -1
- package/dist/chunk-7CHGGMP7.js +0 -73
- package/dist/chunk-7CHGGMP7.js.map +0 -1
- package/dist/chunk-AHRTPV2C.js +0 -1082
- package/dist/chunk-AHRTPV2C.js.map +0 -1
- package/dist/chunk-GU4LRYYH.js +0 -41
- package/dist/chunk-GU4LRYYH.js.map +0 -1
- package/dist/chunk-LP5MV76P.js +0 -33
- package/dist/chunk-LP5MV76P.js.map +0 -1
- package/dist/chunk-OJ356IMJ.js +0 -136
- package/dist/chunk-OJ356IMJ.js.map +0 -1
- package/dist/chunk-PRNBOQHW.js +0 -32
- package/dist/chunk-PRNBOQHW.js.map +0 -1
- package/dist/chunk-QTC5Y3LU.js +0 -146
- package/dist/chunk-QTC5Y3LU.js.map +0 -1
- package/dist/chunk-SNUH2UT6.js +0 -95
- package/dist/chunk-SNUH2UT6.js.map +0 -1
- package/dist/chunk-UG25BZUN.js +0 -59
- package/dist/chunk-UG25BZUN.js.map +0 -1
- package/dist/chunk-VWAIXSB6.js +0 -78
- package/dist/chunk-VWAIXSB6.js.map +0 -1
- package/dist/index.js +0 -99
- package/dist/index.js.map +0 -1
- package/dist/info-3PW6A6JA.js +0 -80
- package/dist/info-3PW6A6JA.js.map +0 -1
- package/dist/init-MOJNLWXK.js +0 -212
- package/dist/init-MOJNLWXK.js.map +0 -1
- package/dist/logout-YPGZ6BB6.js +0 -27
- package/dist/logout-YPGZ6BB6.js.map +0 -1
- package/dist/publish-W37Y6TO6.js +0 -211
- package/dist/publish-W37Y6TO6.js.map +0 -1
- package/dist/run-M4XXNPGD.js +0 -291
- package/dist/run-M4XXNPGD.js.map +0 -1
- package/dist/search-2KNAXPM5.js +0 -55
- package/dist/search-2KNAXPM5.js.map +0 -1
- package/dist/update-UCT4K6IQ.js +0 -125
- package/dist/update-UCT4K6IQ.js.map +0 -1
- package/dist/validate-GFDSEVPV.js +0 -12
- package/dist/validate-GFDSEVPV.js.map +0 -1
package/dist/chunk-6CWCR5SO.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// src/lib/errors.ts
|
|
2
|
-
var CliError = class extends Error {
|
|
3
|
-
exitCode;
|
|
4
|
-
/** Optional stable machine code (e.g. a validation code or "E_CHECKSUM"). */
|
|
5
|
-
code;
|
|
6
|
-
/** Extra lines printed under the message (hints, URLs tried). */
|
|
7
|
-
details;
|
|
8
|
-
constructor(message, opts = {}) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.name = "CliError";
|
|
11
|
-
this.exitCode = opts.exitCode ?? 1;
|
|
12
|
-
this.code = opts.code;
|
|
13
|
-
this.details = opts.details ?? [];
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
function isCliError(e) {
|
|
17
|
-
return e instanceof CliError;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export {
|
|
21
|
-
CliError,
|
|
22
|
-
isCliError
|
|
23
|
-
};
|
|
24
|
-
//# sourceMappingURL=chunk-6CWCR5SO.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/errors.ts"],"sourcesContent":["// A typed error the top-level handler renders cleanly (no stack) and maps to a\n// process exit code. Everything the user should see as an actionable failure is\n// thrown as a CliError.\n\nexport class CliError extends Error {\n readonly exitCode: number;\n /** Optional stable machine code (e.g. a validation code or \"E_CHECKSUM\"). */\n readonly code: string | undefined;\n /** Extra lines printed under the message (hints, URLs tried). */\n readonly details: string[];\n\n constructor(\n message: string,\n opts: { exitCode?: number; code?: string; details?: string[] } = {},\n ) {\n super(message);\n this.name = \"CliError\";\n this.exitCode = opts.exitCode ?? 1;\n this.code = opts.code;\n this.details = opts.details ?? [];\n }\n}\n\n/** True for our own actionable errors (rendered without a stack trace). */\nexport function isCliError(e: unknown): e is CliError {\n return e instanceof CliError;\n}\n"],"mappings":";AAIO,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAET,YACE,SACA,OAAiE,CAAC,GAClE;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,WAAW,KAAK,YAAY;AACjC,SAAK,OAAO,KAAK;AACjB,SAAK,UAAU,KAAK,WAAW,CAAC;AAAA,EAClC;AACF;AAGO,SAAS,WAAW,GAA2B;AACpD,SAAO,aAAa;AACtB;","names":[]}
|
package/dist/chunk-7CHGGMP7.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
sha256Hex
|
|
3
|
-
} from "./chunk-QTC5Y3LU.js";
|
|
4
|
-
import {
|
|
5
|
-
doFetch
|
|
6
|
-
} from "./chunk-5VPKMXSV.js";
|
|
7
|
-
import {
|
|
8
|
-
USER_AGENT
|
|
9
|
-
} from "./chunk-LP5MV76P.js";
|
|
10
|
-
import {
|
|
11
|
-
CliError
|
|
12
|
-
} from "./chunk-6CWCR5SO.js";
|
|
13
|
-
|
|
14
|
-
// src/lib/download.ts
|
|
15
|
-
async function fetchFromRegistry(fetchImpl, url, filePath) {
|
|
16
|
-
const res = await doFetch(fetchImpl, url, { headers: { "user-agent": USER_AGENT } });
|
|
17
|
-
if (res.status === 410) {
|
|
18
|
-
throw new CliError(
|
|
19
|
-
`${filePath} has been withdrawn by the registry (410) \u2014 this workflow was blocked or removed for policy reasons; refusing to fall back to GitHub`,
|
|
20
|
-
{ code: "E_GONE", details: [url] }
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
if (!res.ok) return null;
|
|
24
|
-
return new Uint8Array(await res.arrayBuffer());
|
|
25
|
-
}
|
|
26
|
-
async function downloadFromRegistry(record, registry, github, fetchImpl) {
|
|
27
|
-
const [owner, repo] = record.repo.split("/");
|
|
28
|
-
const dirPrefix = record.directory ? `${record.directory.replace(/\/+$/, "")}/` : "";
|
|
29
|
-
const out = [];
|
|
30
|
-
for (const file of record.files) {
|
|
31
|
-
let bytes = null;
|
|
32
|
-
let source = "registry";
|
|
33
|
-
const urlsTried = [];
|
|
34
|
-
const cacheUrl = file.downloadUrl ?? registry.fileUrl(record.author, record.slug, record.version, file.path);
|
|
35
|
-
urlsTried.push(cacheUrl);
|
|
36
|
-
bytes = await fetchFromRegistry(fetchImpl, cacheUrl, file.path);
|
|
37
|
-
if (!bytes && owner && repo) {
|
|
38
|
-
source = "github";
|
|
39
|
-
try {
|
|
40
|
-
bytes = await github.fetchRawFile(owner, repo, record.commitSha, `${dirPrefix}${file.path}`);
|
|
41
|
-
} catch (e) {
|
|
42
|
-
urlsTried.push(e.message);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if (!bytes) {
|
|
46
|
-
throw new CliError(`could not download ${file.path} from any source`, {
|
|
47
|
-
code: "E_DOWNLOAD",
|
|
48
|
-
details: urlsTried
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
const digest = sha256Hex(bytes);
|
|
52
|
-
if (digest !== file.sha256) {
|
|
53
|
-
throw new CliError(
|
|
54
|
-
`checksum mismatch for ${file.path} \u2014 refusing to write (possible tampering)`,
|
|
55
|
-
{
|
|
56
|
-
code: "E_CHECKSUM",
|
|
57
|
-
details: [
|
|
58
|
-
`expected sha256: ${file.sha256}`,
|
|
59
|
-
`actual sha256: ${digest}`,
|
|
60
|
-
`source: ${source}`
|
|
61
|
-
]
|
|
62
|
-
}
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
out.push({ path: file.path, bytes, sha256: digest, source });
|
|
66
|
-
}
|
|
67
|
-
return out;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export {
|
|
71
|
-
downloadFromRegistry
|
|
72
|
-
};
|
|
73
|
-
//# sourceMappingURL=chunk-7CHGGMP7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/download.ts"],"sourcesContent":["// Download + verify (spec §5.4.2). Registry cache endpoint first, then\n// raw.githubusercontent.com fallback. EVERY file's SHA-256 is verified against\n// the registry's publish-time checksum; a mismatch is a security-flavored abort.\n\nimport {\n type FileChecksum,\n type WorkflowRecord,\n} from \"@castellan/schema\";\nimport { CliError } from \"./errors.js\";\nimport { sha256Hex } from \"./checksum.js\";\nimport { doFetch, type FetchLike } from \"./http.js\";\nimport { USER_AGENT } from \"./config.js\";\nimport type { RegistryClient } from \"./registry.js\";\nimport type { GitHubClient } from \"./github.js\";\n\n/** A downloaded file: raw bytes keyed later by its package-relative path. */\nexport interface DownloadedFile {\n path: string;\n bytes: Uint8Array;\n sha256: string;\n /** Where the bytes came from, for transparency. */\n source: \"registry\" | \"github\";\n}\n\n/**\n * Fetch bytes from the registry cache endpoint. A `410 Gone` is a MODERATION\n * signal (blocked/removed workflow, §8.7): it hard-aborts and must NOT fall\n * back to GitHub. Any other failure (404/5xx/network) returns null so the\n * caller can try the GitHub raw mirror.\n */\nasync function fetchFromRegistry(\n fetchImpl: FetchLike,\n url: string,\n filePath: string,\n): Promise<Uint8Array | null> {\n const res = await doFetch(fetchImpl, url, { headers: { \"user-agent\": USER_AGENT } });\n if (res.status === 410) {\n throw new CliError(\n `${filePath} has been withdrawn by the registry (410) — this workflow was blocked or removed for policy reasons; refusing to fall back to GitHub`,\n { code: \"E_GONE\", details: [url] },\n );\n }\n if (!res.ok) return null;\n return new Uint8Array(await res.arrayBuffer());\n}\n\n/**\n * Download and verify every file in a resolved registry record. Owner/repo are\n * parsed from `record.repo`. On any checksum mismatch, aborts immediately with a\n * security-flavored error naming the file and both digests.\n */\nexport async function downloadFromRegistry(\n record: WorkflowRecord,\n registry: RegistryClient,\n github: GitHubClient,\n fetchImpl: FetchLike,\n): Promise<DownloadedFile[]> {\n const [owner, repo] = record.repo.split(\"/\");\n const dirPrefix = record.directory ? `${record.directory.replace(/\\/+$/, \"\")}/` : \"\";\n const out: DownloadedFile[] = [];\n\n for (const file of record.files as FileChecksum[]) {\n let bytes: Uint8Array | null = null;\n let source: DownloadedFile[\"source\"] = \"registry\";\n const urlsTried: string[] = [];\n\n // 1) Registry cache endpoint (downloadUrl if provided, else constructed).\n const cacheUrl = file.downloadUrl ?? registry.fileUrl(record.author, record.slug, record.version, file.path);\n urlsTried.push(cacheUrl);\n bytes = await fetchFromRegistry(fetchImpl, cacheUrl, file.path);\n\n // 2) raw.githubusercontent.com fallback at the pinned SHA.\n if (!bytes && owner && repo) {\n source = \"github\";\n try {\n bytes = await github.fetchRawFile(owner, repo, record.commitSha, `${dirPrefix}${file.path}`);\n } catch (e) {\n urlsTried.push((e as CliError).message);\n }\n }\n\n if (!bytes) {\n throw new CliError(`could not download ${file.path} from any source`, {\n code: \"E_DOWNLOAD\",\n details: urlsTried,\n });\n }\n\n const digest = sha256Hex(bytes);\n if (digest !== file.sha256) {\n throw new CliError(\n `checksum mismatch for ${file.path} — refusing to write (possible tampering)`,\n {\n code: \"E_CHECKSUM\",\n details: [\n `expected sha256: ${file.sha256}`,\n `actual sha256: ${digest}`,\n `source: ${source}`,\n ],\n },\n );\n }\n\n out.push({ path: file.path, bytes, sha256: digest, source });\n }\n\n return out;\n}\n"],"mappings":";;;;;;;;;;;;;;AA8BA,eAAe,kBACb,WACA,KACA,UAC4B;AAC5B,QAAM,MAAM,MAAM,QAAQ,WAAW,KAAK,EAAE,SAAS,EAAE,cAAc,WAAW,EAAE,CAAC;AACnF,MAAI,IAAI,WAAW,KAAK;AACtB,UAAM,IAAI;AAAA,MACR,GAAG,QAAQ;AAAA,MACX,EAAE,MAAM,UAAU,SAAS,CAAC,GAAG,EAAE;AAAA,IACnC;AAAA,EACF;AACA,MAAI,CAAC,IAAI,GAAI,QAAO;AACpB,SAAO,IAAI,WAAW,MAAM,IAAI,YAAY,CAAC;AAC/C;AAOA,eAAsB,qBACpB,QACA,UACA,QACA,WAC2B;AAC3B,QAAM,CAAC,OAAO,IAAI,IAAI,OAAO,KAAK,MAAM,GAAG;AAC3C,QAAM,YAAY,OAAO,YAAY,GAAG,OAAO,UAAU,QAAQ,QAAQ,EAAE,CAAC,MAAM;AAClF,QAAM,MAAwB,CAAC;AAE/B,aAAW,QAAQ,OAAO,OAAyB;AACjD,QAAI,QAA2B;AAC/B,QAAI,SAAmC;AACvC,UAAM,YAAsB,CAAC;AAG7B,UAAM,WAAW,KAAK,eAAe,SAAS,QAAQ,OAAO,QAAQ,OAAO,MAAM,OAAO,SAAS,KAAK,IAAI;AAC3G,cAAU,KAAK,QAAQ;AACvB,YAAQ,MAAM,kBAAkB,WAAW,UAAU,KAAK,IAAI;AAG9D,QAAI,CAAC,SAAS,SAAS,MAAM;AAC3B,eAAS;AACT,UAAI;AACF,gBAAQ,MAAM,OAAO,aAAa,OAAO,MAAM,OAAO,WAAW,GAAG,SAAS,GAAG,KAAK,IAAI,EAAE;AAAA,MAC7F,SAAS,GAAG;AACV,kBAAU,KAAM,EAAe,OAAO;AAAA,MACxC;AAAA,IACF;AAEA,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,SAAS,sBAAsB,KAAK,IAAI,oBAAoB;AAAA,QACpE,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,UAAU,KAAK;AAC9B,QAAI,WAAW,KAAK,QAAQ;AAC1B,YAAM,IAAI;AAAA,QACR,yBAAyB,KAAK,IAAI;AAAA,QAClC;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,YACP,oBAAoB,KAAK,MAAM;AAAA,YAC/B,oBAAoB,MAAM;AAAA,YAC1B,WAAW,MAAM;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,EAAE,MAAM,KAAK,MAAM,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC7D;AAEA,SAAO;AACT;","names":[]}
|