@stsepelin/checktrail 0.1.0-alpha.1 → 0.1.0-alpha.2

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 CHANGED
@@ -4,18 +4,22 @@ Local code validation with a CLI, MCP tools, and evidence of what actually ran.
4
4
 
5
5
  Formerly Repo Verifier. See the [rename guide](docs/RENAMING.md) for existing source checkouts.
6
6
 
7
- **Experimental preview: 0.1.0-alpha.1.** Public source is available at
7
+ **Published preview: 0.1.0-alpha.1; alpha.2 is in preparation.** Public source is available at
8
8
  [stsepelin/checktrail](https://github.com/stsepelin/checktrail).
9
9
  See [implementation status](docs/STATUS.md), the [plan](docs/PLAN.md) and the
10
10
  [language matrix](docs/LANGUAGES.md) before relying on an adapter.
11
11
  [Installation](docs/INSTALLATION.md) covers the CLI, Claude Code and Codex.
12
+ [Agent skills](docs/SKILLS.md) provides setup, validation and review workflows
13
+ installable with `npx skills add stsepelin/checktrail`.
14
+ [Project setup](docs/ONBOARDING.md) covers the alpha.2 candidate's `init`, `doctor`
15
+ and MCP configuration generator.
12
16
  [Release preparation](docs/RELEASE.md) records publication and verification gates. The
13
17
  [milestone audit](docs/ACCEPTANCE.md) separates implemented profiles from open
14
18
  acceptance work; [client checks](docs/CLIENTS.md) record actual application coverage.
15
19
 
16
- The [13-job hosted matrix](https://github.com/stsepelin/checktrail/actions/runs/35573066804)
17
- passed at `52ba415` on Linux and macOS. This identifies a verified source revision;
18
- it does not imply that a later package version has been published.
20
+ The [hosted matrix](https://github.com/stsepelin/checktrail/actions/runs/35585998184)
21
+ passed at `bfc8cc4` on Linux and macOS. That result predates the alpha.2 candidate;
22
+ new release changes require their own CI run and package verification.
19
23
 
20
24
  Checktrail discovers projects, plans registered checks, invokes native tools
21
25
  when explicitly trusted, and reports results without turning skipped or empty
@@ -41,7 +45,7 @@ node dist/src/cli.js run --root examples/javascript --trust-project --detailed
41
45
  `--trust-project`: tests, compiler plugins and project configuration can execute
42
46
  code with your user privileges. This is not a sandbox.
43
47
 
44
- Commands always return JSON except help/version. Exit codes:
48
+ Successful commands return JSON except help/version; input errors use stderr. Exit codes:
45
49
 
46
50
  | Code | Meaning |
47
51
  | ---- | --------------------------------------------------------------------------------------- |
package/dist/src/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import path from "node:path";
3
+ import { initialize, diagnose, mcpConfiguration, mcpClients, } from "./onboarding.js";
3
4
  import { createReviewContext, projectReviewContext, receiveReview, projectReviewReceipt, } from "./review.js";
4
5
  import { fetchPolicyPack } from "./fetch-pack.js";
5
6
  import { externalReferencesSchema, loadExternalAdapters, } from "./external-adapter.js";
@@ -22,11 +23,15 @@ import { VERSION } from "./types.js";
22
23
  import { validateContracts, projectContractReport } from "./contracts.js";
23
24
  import { compareRuntimeInventories, projectRuntimeComparison, } from "./runtime-inventory.js";
24
25
  async function main() {
25
- const { values, positionals } = parseArgs({
26
+ const { values, positionals, tokens } = parseArgs({
27
+ tokens: true,
26
28
  allowPositionals: true,
27
29
  strict: true,
28
30
  options: {
29
31
  root: { type: "string", default: "." },
32
+ write: { type: "boolean", default: false },
33
+ check: { type: "string", multiple: true },
34
+ client: { type: "string" },
30
35
  "trust-project": { type: "boolean", default: false },
31
36
  "allow-execution": { type: "boolean", default: false },
32
37
  detailed: { type: "boolean", default: false },
@@ -58,12 +63,29 @@ async function main() {
58
63
  return;
59
64
  }
60
65
  if (values.help || positionals.length === 0) {
61
- process.stdout.write("checktrail <inspect|plan|run|serve|adapters|import-junit|export-sarif|create-baseline|compare-findings|compare-runtime|check-contracts|check-architecture|guidance|review-context|review-receipt|mutate|fetch-pack> [--root PATH] [--detailed] [--base REVISION] [--policy-overlay PATH] [--adapter PATH#sha256=DIGEST ...]\nRun: --trust-project [--timeout-ms 30000] [--allow-env NAME ...]\nServe: --allow-execution (optional; disabled by default) [--allow-env NAME ...]\nFetch-pack: --url HTTPS_URL --sha256 DIGEST --output RELATIVE_JSON_PATH\nExit: 0 passed/read-only success/completed advisory experiment, 1 failed checks, 2 incomplete/error\n");
66
+ process.stdout.write("checktrail <init|doctor|mcp-config|inspect|plan|run|serve|adapters|import-junit|export-sarif|create-baseline|compare-findings|compare-runtime|check-contracts|check-architecture|guidance|review-context|review-receipt|mutate|fetch-pack> [--root PATH] [--detailed] [--base REVISION] [--policy-overlay PATH] [--adapter PATH#sha256=DIGEST ...]\nInit: [--write] [--check PATH#CHECK_ID ...] (preview by default; preserves existing config)\nDoctor: [--detailed] [--policy-overlay PATH] [--allow-env NAME ...] [--adapter PATH#sha256=DIGEST ...] (no execution)\nMcp-config: --client codex|claude-code|claude-desktop|cursor|vscode (prints configuration only)\nRun: --trust-project [--timeout-ms 30000] [--allow-env NAME ...]\nServe: --allow-execution (optional; disabled by default) [--allow-env NAME ...]\nFetch-pack: --url HTTPS_URL --sha256 DIGEST --output RELATIVE_JSON_PATH\nExit: 0 passed/read-only success/completed advisory experiment, 1 failed checks, 2 incomplete/error\n");
62
67
  return;
63
68
  }
64
69
  if (positionals.length !== 1)
65
70
  throw new Error("Expected exactly one command");
66
71
  const command = positionals[0];
72
+ for (const token of tokens) {
73
+ if (token.kind !== "option")
74
+ continue;
75
+ if (["write", "check"].includes(token.name) && command !== "init")
76
+ throw new Error(`--${token.name} applies only to init`);
77
+ if (token.name === "client" && command !== "mcp-config")
78
+ throw new Error("--client applies only to mcp-config");
79
+ const allowed = command === "init"
80
+ ? ["root", "write", "check"]
81
+ : command === "doctor"
82
+ ? ["root", "detailed", "policy-overlay", "allow-env", "adapter"]
83
+ : command === "mcp-config"
84
+ ? ["root", "client"]
85
+ : undefined;
86
+ if (allowed && !allowed.includes(token.name))
87
+ throw new Error(`--${token.name} does not apply to ${command}`);
88
+ }
67
89
  if (values["allow-review-source"] &&
68
90
  (!values.detailed ||
69
91
  !["review-context", "review-receipt", "serve"].includes(command)))
@@ -85,7 +107,15 @@ async function main() {
85
107
  };
86
108
  }));
87
109
  if (externalAdapters.length &&
88
- !["inspect", "plan", "run", "serve", "adapters", "guidance"].includes(command))
110
+ ![
111
+ "inspect",
112
+ "plan",
113
+ "run",
114
+ "serve",
115
+ "adapters",
116
+ "guidance",
117
+ "doctor",
118
+ ].includes(command))
89
119
  throw new Error("External adapters apply only to inspection, planning, validation, serving and derived guidance");
90
120
  if (externalAdapters.length && command === "guidance" && values.input)
91
121
  throw new Error("External adapters require derived guidance, not an imported context");
@@ -103,7 +133,49 @@ async function main() {
103
133
  ]);
104
134
  return;
105
135
  }
136
+ if (command === "doctor") {
137
+ const result = await diagnose(values.root, {
138
+ detailed: values.detailed,
139
+ externalAdapters,
140
+ environment: inheritEnvironment(values["allow-env"] ?? []),
141
+ ...(values["policy-overlay"]
142
+ ? { policyOverlay: values["policy-overlay"] }
143
+ : {}),
144
+ });
145
+ print(result);
146
+ process.exitCode = result.status === "no-static-blockers" ? 0 : 2;
147
+ return;
148
+ }
106
149
  const root = await realpath(values.root);
150
+ if (command === "init") {
151
+ const selections = new Map();
152
+ for (const value of values.check ?? []) {
153
+ const split = value.lastIndexOf("#");
154
+ if (split <= 0 || split === value.length - 1)
155
+ throw new Error("Check selection requires PATH#CHECK_ID");
156
+ const selectedPath = value.slice(0, split);
157
+ selections.set(selectedPath, [
158
+ ...(selections.get(selectedPath) ?? []),
159
+ value.slice(split + 1),
160
+ ]);
161
+ }
162
+ const result = await initialize(root, {
163
+ write: values.write,
164
+ selections: [...selections].map(([selectedPath, checks]) => ({
165
+ path: selectedPath,
166
+ checks,
167
+ })),
168
+ });
169
+ print(result);
170
+ process.exitCode = result.status === "needs-selection" ? 2 : 0;
171
+ return;
172
+ }
173
+ if (command === "mcp-config") {
174
+ if (!mcpClients.includes(values.client))
175
+ throw new Error(`mcp-config requires --client ${mcpClients.join("|")}`);
176
+ print(await mcpConfiguration(root, values.client));
177
+ return;
178
+ }
107
179
  if (command === "fetch-pack") {
108
180
  if (!values.url || !values.sha256 || !values.output)
109
181
  throw new Error("fetch-pack requires --url HTTPS_URL --sha256 DIGEST --output RELATIVE_JSON_PATH");
@@ -3,6 +3,8 @@ export { validateContracts } from "./contracts.js";
3
3
  export type { ContractBundle, ContractReport } from "./contract-schema.js";
4
4
  export type { PlanOptions, ValidationOptions } from "./engine.js";
5
5
  export { adapters } from "./adapters.js";
6
+ export { initialize, diagnose, mcpConfiguration, mcpClients, } from "./onboarding.js";
7
+ export type { InitOptions, InitResult, DoctorIssue, DoctorResult, McpClient, } from "./onboarding.js";
6
8
  export type { PolicyPack, PackReference } from "./policy-pack.js";
7
9
  export { fetchPolicyPack } from "./fetch-pack.js";
8
10
  export type { FetchPackOptions, FetchedPack } from "./fetch-pack.js";
package/dist/src/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { createPlan, validate, aggregate } from "./engine.js";
2
2
  export { validateContracts } from "./contracts.js";
3
3
  export { adapters } from "./adapters.js";
4
+ export { initialize, diagnose, mcpConfiguration, mcpClients, } from "./onboarding.js";
4
5
  export { fetchPolicyPack } from "./fetch-pack.js";
5
6
  export { projectPlan, projectReport } from "./output.js";
6
7
  export { importJUnit } from "./junit.js";
@@ -0,0 +1,50 @@
1
+ import { type Config } from "./config.js";
2
+ import { type PlanOptions } from "./engine.js";
3
+ export interface InitOptions {
4
+ write?: boolean;
5
+ selections?: {
6
+ path: string;
7
+ checks: string[];
8
+ }[];
9
+ }
10
+ export interface InitResult {
11
+ schemaVersion: 1;
12
+ engineVersion: string;
13
+ status: "preview" | "created" | "preserved" | "needs-selection";
14
+ configuration: Config | null;
15
+ unresolved: {
16
+ path: string;
17
+ adapter: string;
18
+ choices: string[];
19
+ }[];
20
+ executionEnabled: false;
21
+ }
22
+ export declare function initialize(root: string, options?: InitOptions): Promise<InitResult>;
23
+ export interface DoctorIssue {
24
+ code: "configuration-error" | "empty-plan" | "unselected-project" | "unavailable-check" | "missing-executable" | "package-metadata" | "unsupported-platform";
25
+ check?: string;
26
+ adapter?: string;
27
+ project?: string;
28
+ detail?: string;
29
+ }
30
+ export interface DoctorResult {
31
+ schemaVersion: 1;
32
+ engineVersion: string;
33
+ status: "no-static-blockers" | "attention-required";
34
+ validationPerformed: false;
35
+ projects: number;
36
+ checks: number;
37
+ issues: DoctorIssue[];
38
+ unverified: string[];
39
+ }
40
+ export declare function diagnose(root: string, options?: Omit<PlanOptions, "base"> & {
41
+ detailed?: boolean;
42
+ }): Promise<DoctorResult>;
43
+ export declare const mcpClients: readonly ["codex", "claude-code", "claude-desktop", "cursor", "vscode"];
44
+ export type McpClient = (typeof mcpClients)[number];
45
+ export declare function mcpConfiguration(root: string, client: McpClient): Promise<{
46
+ client: McpClient;
47
+ format: "json" | "toml";
48
+ configuration: string;
49
+ executionEnabled: false;
50
+ }>;
@@ -0,0 +1,295 @@
1
+ import { constants } from "node:fs";
2
+ import { access, link, lstat, mkdtemp, realpath, rm, stat, writeFile, } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { adapters, checksFor } from "./adapters.js";
5
+ import { configSchema } from "./config.js";
6
+ import { createPlan } from "./engine.js";
7
+ import { inventory, readProjectFile } from "./inventory.js";
8
+ import { identifyTool } from "./tool-versions.js";
9
+ import { VERSION } from "./types.js";
10
+ async function configurationExists(root) {
11
+ try {
12
+ const entry = await lstat(path.join(root, "checktrail.json"));
13
+ if (!entry.isFile() || entry.isSymbolicLink())
14
+ throw new Error("checktrail.json must be a regular file, not a symlink or directory");
15
+ return true;
16
+ }
17
+ catch (error) {
18
+ if (error.code === "ENOENT")
19
+ return false;
20
+ throw error;
21
+ }
22
+ }
23
+ export async function initialize(root, options = {}) {
24
+ root = await realpath(root);
25
+ const exists = await configurationExists(root);
26
+ const { source, plan } = await createPlan(root);
27
+ const result = {
28
+ schemaVersion: 1,
29
+ engineVersion: VERSION,
30
+ status: "preview",
31
+ configuration: null,
32
+ unresolved: [],
33
+ executionEnabled: false,
34
+ };
35
+ if (exists) {
36
+ if (options.selections?.length)
37
+ throw new Error("Existing configuration is preserved; edit its policy explicitly to change checks");
38
+ return { ...result, status: "preserved" };
39
+ }
40
+ const selected = new Map();
41
+ for (const selection of options.selections ?? []) {
42
+ if (selected.has(selection.path))
43
+ throw new Error("Duplicate selection path");
44
+ if (!selection.checks.length ||
45
+ new Set(selection.checks).size !== selection.checks.length)
46
+ throw new Error("Selections require nonempty, unique check IDs");
47
+ selected.set(selection.path, selection.checks);
48
+ }
49
+ for (const selectedPath of selected.keys())
50
+ if (!plan.projects.some((project) => project.path === selectedPath))
51
+ throw new Error("Selection does not match a discovered project path");
52
+ const grouped = new Map();
53
+ for (const project of plan.projects) {
54
+ const registered = adapters.find((adapter) => adapter.id === project.adapter).checks;
55
+ const requested = selected.get(project.path);
56
+ let ids = requested?.filter((id) => registered.includes(id));
57
+ if (!requested) {
58
+ ids = plan.checks
59
+ .filter((check) => check.project === project.path &&
60
+ check.adapter === project.adapter &&
61
+ registered.includes(check.id))
62
+ .map((check) => check.id);
63
+ if (project.adapter === "python")
64
+ ids = [];
65
+ if (project.adapter === "javascript") {
66
+ const manifest = JSON.parse(await readProjectFile(root, path.posix.join(project.path, "package.json")));
67
+ const runners = {
68
+ "node --test": "javascript.node-test",
69
+ "vitest run": "javascript.vitest",
70
+ jest: "javascript.jest",
71
+ "playwright test": "javascript.playwright",
72
+ };
73
+ const script = manifest?.scripts?.test;
74
+ ids =
75
+ typeof script === "string" && Object.hasOwn(runners, script)
76
+ ? [runners[script]]
77
+ : [];
78
+ }
79
+ }
80
+ if (!ids?.length ||
81
+ plan.checks.some((check) => check.project === project.path &&
82
+ check.adapter === project.adapter &&
83
+ check.kind === "unsupported")) {
84
+ result.unresolved.push({
85
+ path: project.path,
86
+ adapter: project.adapter,
87
+ choices: [...registered],
88
+ });
89
+ continue;
90
+ }
91
+ const candidates = await checksFor(source, project, ids);
92
+ if (ids.some((id) => !candidates.some((check) => check.id === id)))
93
+ throw new Error("Selected check is inapplicable to the discovered project");
94
+ const checks = grouped.get(project.path) ?? new Set();
95
+ for (const id of ids)
96
+ checks.add(id);
97
+ grouped.set(project.path, checks);
98
+ }
99
+ for (const [selectedPath, ids] of selected)
100
+ if (ids.some((id) => !grouped.get(selectedPath)?.has(id)))
101
+ throw new Error("Selected check is unknown or inapplicable");
102
+ if (!plan.projects.length || result.unresolved.length)
103
+ return { ...result, status: "needs-selection" };
104
+ result.configuration = configSchema.parse({
105
+ schemaVersion: 1,
106
+ projects: [...grouped].map(([projectPath, checks]) => ({
107
+ path: projectPath,
108
+ checks: [...checks].sort(),
109
+ })),
110
+ });
111
+ if (!options.write)
112
+ return result;
113
+ if ((await inventory(root)).fingerprint !== source.fingerprint)
114
+ throw new Error("Project changed during setup; review a fresh preview");
115
+ const temporary = await mkdtemp(path.join(root, ".checktrail-init-"));
116
+ try {
117
+ const staged = path.join(temporary, "checktrail.json");
118
+ await writeFile(staged, `${JSON.stringify(result.configuration, null, 2)}\n`, { flag: "wx", mode: 0o600 });
119
+ // An exclusive link publishes complete bytes without replacing a concurrent writer.
120
+ await link(staged, path.join(root, "checktrail.json"));
121
+ }
122
+ finally {
123
+ await rm(temporary, { recursive: true, force: true });
124
+ }
125
+ return { ...result, status: "created" };
126
+ }
127
+ async function executableAvailable(executable, cwd, searchPath) {
128
+ const candidates = executable.includes("/") || path.isAbsolute(executable)
129
+ ? [path.resolve(cwd, executable)]
130
+ : searchPath
131
+ .split(path.delimiter)
132
+ .map((directory) => path.resolve(cwd, directory, executable));
133
+ for (const candidate of candidates) {
134
+ try {
135
+ if (!(await stat(candidate)).isFile())
136
+ continue;
137
+ await access(candidate, constants.X_OK);
138
+ return true;
139
+ }
140
+ catch {
141
+ /* Other PATH entries may provide the executable. */
142
+ }
143
+ }
144
+ return false;
145
+ }
146
+ export async function diagnose(root, options = {}) {
147
+ const issues = [];
148
+ const result = {
149
+ schemaVersion: 1,
150
+ engineVersion: VERSION,
151
+ status: "attention-required",
152
+ validationPerformed: false,
153
+ projects: 0,
154
+ checks: 0,
155
+ issues,
156
+ unverified: [
157
+ "Tool versions and runtime compatibility",
158
+ "Importable modules and runtime services",
159
+ "Validation results; run with explicit project trust",
160
+ ],
161
+ };
162
+ const add = (issue) => {
163
+ const summary = { ...issue };
164
+ delete summary.project;
165
+ delete summary.detail;
166
+ issues.push(options.detailed ? issue : summary);
167
+ };
168
+ if (process.platform === "win32")
169
+ add({ code: "unsupported-platform" });
170
+ try {
171
+ root = await realpath(root);
172
+ await configurationExists(root);
173
+ const { plan } = await createPlan(root, {
174
+ ...(options.externalAdapters
175
+ ? { externalAdapters: options.externalAdapters }
176
+ : {}),
177
+ ...(options.policyOverlay
178
+ ? { policyOverlay: options.policyOverlay }
179
+ : {}),
180
+ ...(options.environment ? { environment: options.environment } : {}),
181
+ });
182
+ result.projects = plan.projects.length;
183
+ result.checks = plan.checks.length;
184
+ if (!plan.checks.length)
185
+ add({ code: "empty-plan" });
186
+ for (const project of plan.projects)
187
+ if (!plan.checks.some((check) => check.project === project.path && check.adapter === project.adapter))
188
+ add({
189
+ code: "unselected-project",
190
+ project: project.path,
191
+ adapter: project.adapter,
192
+ });
193
+ for (const check of plan.checks) {
194
+ const context = {
195
+ check: check.id,
196
+ adapter: check.adapter,
197
+ project: check.project,
198
+ };
199
+ if (check.unavailableReason)
200
+ add({
201
+ ...context,
202
+ code: "unavailable-check",
203
+ detail: check.unavailableReason,
204
+ });
205
+ const commands = [...check.commands];
206
+ for (const tool of check.tools ?? []) {
207
+ if (tool.source === "version-command")
208
+ commands.push(tool.command);
209
+ else if (tool.source === "package-metadata") {
210
+ const identity = await identifyTool(root, tool, async () => {
211
+ throw new Error("Doctor must not execute version probes");
212
+ });
213
+ if (identity.status !== "identified")
214
+ add({
215
+ ...context,
216
+ code: "package-metadata",
217
+ detail: `Missing or invalid package metadata: ${tool.name}`,
218
+ });
219
+ }
220
+ }
221
+ const wrapped = check.adapter === "jvm"
222
+ ? ["java"]
223
+ : check.adapter === "dotnet"
224
+ ? ["dotnet"]
225
+ : check.id === "infrastructure.actionlint"
226
+ ? ["actionlint"]
227
+ : [];
228
+ for (const executable of wrapped)
229
+ commands.push({ executable, args: [], cwd: check.project });
230
+ const checked = new Set();
231
+ for (const command of commands) {
232
+ const searchPath = command.env?.PATH ??
233
+ (check.environment?.includes("PATH")
234
+ ? options.environment?.PATH
235
+ : undefined) ??
236
+ process.env.PATH ??
237
+ "/usr/bin:/bin";
238
+ const cwd = path.resolve(root, command.cwd);
239
+ const key = JSON.stringify([command.executable, cwd, searchPath]);
240
+ if (checked.has(key))
241
+ continue;
242
+ checked.add(key);
243
+ if (!(await executableAvailable(command.executable, cwd, searchPath)))
244
+ add({
245
+ ...context,
246
+ code: "missing-executable",
247
+ detail: `Executable unavailable or not executable: ${command.executable}`,
248
+ });
249
+ }
250
+ }
251
+ }
252
+ catch (error) {
253
+ add({
254
+ code: "configuration-error",
255
+ detail: error instanceof Error ? error.message : "Cannot inspect project",
256
+ });
257
+ }
258
+ result.status = issues.length ? "attention-required" : "no-static-blockers";
259
+ return result;
260
+ }
261
+ export const mcpClients = [
262
+ "codex",
263
+ "claude-code",
264
+ "claude-desktop",
265
+ "cursor",
266
+ "vscode",
267
+ ];
268
+ export async function mcpConfiguration(root, client) {
269
+ if (!mcpClients.includes(client))
270
+ throw new Error("Unknown MCP client");
271
+ root = await realpath(root);
272
+ if (!(await stat(root)).isDirectory())
273
+ throw new Error("MCP root must be a directory");
274
+ if (root.includes("${"))
275
+ throw new Error("MCP root contains client variable syntax; choose a path without ${");
276
+ const server = {
277
+ command: "npx",
278
+ args: [
279
+ "--yes",
280
+ "--ignore-scripts",
281
+ `@stsepelin/checktrail@${VERSION}`,
282
+ "serve",
283
+ "--root",
284
+ root,
285
+ ],
286
+ };
287
+ return {
288
+ client,
289
+ executionEnabled: false,
290
+ format: client === "codex" ? "toml" : "json",
291
+ configuration: client === "codex"
292
+ ? `[mcp_servers.checktrail]\ncommand = "npx"\nargs = ${JSON.stringify(server.args)}\n`
293
+ : `${JSON.stringify(client === "vscode" ? { servers: { checktrail: { type: "stdio", ...server } } } : { mcpServers: { checktrail: server } }, null, 2)}\n`,
294
+ };
295
+ }
@@ -1,6 +1,6 @@
1
1
  import type { ExternalIdentity } from "./external-adapter.js";
2
2
  import type { RuntimeInventory } from "./runtime-inventory.js";
3
- export declare const VERSION = "0.1.0-alpha.1";
3
+ export declare const VERSION = "0.1.0-alpha.2";
4
4
  export declare const PARSERS: readonly ["vue-router-json", "nuxt-json", "exit", "empty", "node-events", "unittest", "go-scope-test", "go-scope-analysis", "golangci-json", "staticcheck-json", "go-json", "typescript-build-json", "tsc-files", "eslint-json", "vitest-json", "playwright-json", "jest-json", "pytest-json", "fastapi-json", "django-json", "laravel-json", "rust-json", "clang-json", "java-json", "dotnet-json", "actionlint-json", "external-json", "ruby-syntax", "silent-syntax", "ruff-json", "mypy-json", "phpstan-json", "phpunit-junit", "pint-json"];
5
5
  export type Status = "passed" | "failed" | "unavailable" | "skipped" | "error" | "inconclusive";
6
6
  export type Outcome = "passed" | "failed" | "incomplete";
package/dist/src/types.js CHANGED
@@ -1,4 +1,4 @@
1
- export const VERSION = "0.1.0-alpha.1";
1
+ export const VERSION = "0.1.0-alpha.2";
2
2
  export const PARSERS = [
3
3
  "vue-router-json",
4
4
  "nuxt-json",
@@ -5,14 +5,14 @@ verification. It does not replace the plan or promote an unverified capability.
5
5
  Local implementation, local native evidence, hosted CI and publication are
6
6
  separate states. Follow the linked evidence for tested versions and limits.
7
7
 
8
- | Milestone | Implemented scope and evidence | Open acceptance work |
9
- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
10
- | M0: public contracts | Original public fixtures, MIT license, security/contribution guidance, schemas, explicit package allowlist, dependency notices and CI definitions. `STATUS.md`, `SECURITY.md`, `RELEASE.md`. | Public source is published and all hosted jobs passed at `52ba415`. The preview candidate still requires its own release commit, CI and publication verification. |
11
- | M1: executable foundation | Shared CLI/library/MCP engine, bounded inventory/runner, startup trust, native Node/Python/Go/PHP profiles, protocol and lifecycle regressions. `ARCHITECTURE.md`, `STATUS.md`, `MCP-COMPATIBILITY.md`. Fresh installed application-client profiles now have evidence in `CLIENTS.md`. | Application-client coverage beyond the named profiles. PHP remains unavailable when the consumer has no prepared runtime. |
12
- | M2: practical language validation | Explicit JS/TS, Python, Go and PHP native tool profiles, structured diagnostics/test evidence, versions, environments, workspace selection, scope accounting, SARIF/JUnit and finding ratchets. `LANGUAGES.md`, adapter documents, `WORKSPACES.md`, `FINDING-POLICY.md`, `NATIVE-CI.md`. | Hosted toolchain profiles passed at `52ba415`. Wider tool versions/framework configurations must be promoted separately; detection is not execution support. |
13
- | M3: framework/contracts | Native Laravel, Vue Router/Nuxt, Django/FastAPI assembly projections; imported runtime comparison, explicit architecture boundaries, producer/consumer schemas and a built package consumer. `RUNTIME-INVENTORY.md`, framework documents, `CONTRACTS.md`, `ARCHITECTURE-POLICY.md`, `examples/package-contract/README.md`. | Broader native semantics/import collection and live service integration are not implemented. Synthetic evidence does not establish equivalent results in a private application; private integration feedback must remain private. |
14
- | M4: ecosystem/distribution | Bounded Rust, Java, C#, Ruby, Swift, Clang and actionlint profiles; trusted external adapters, pinned data-only pack distribution, fresh offline package checks, production notice audit, measured performance and unpublished registry metadata. `LANGUAGES.md`, `EXTERNAL-ADAPTERS.md`, `PACK-DISTRIBUTION.md`, `PERFORMANCE.md`, `RELEASE.md`. | Concrete preview release authorization and verification. Windows execution and the unimplemented subsequent integrations in `LANGUAGES.md` remain unsupported. Runtime/container/development dependency provenance is broader than the production npm notice audit. |
15
- | M5: measured assistance | Advisory guidance, bounded Node mutation experiments, explicit-graph impact measurements, optional local/model review exchange, durable library task storage/worker, development evaluation and externally authored ESLint and Ruff integration cohorts. `GUIDANCE.md`, `MUTATIONS.md`, `IMPACT-MEASUREMENT.md`, `REVIEW-EXCHANGE.md`, `VALIDATION-TASKS.md`, `EVALUATION.md`, `EXTERNAL-EVALUATION.md`, `EXTERNAL-RUFF-EVALUATION.md`. | Standard MCP Tasks wire integration; wider held-out rule-family/review evidence, prior-workflow comparison and representative cost/latency measurement. No general equal-or-better review-quality claim is supported. |
8
+ | Milestone | Implemented scope and evidence | Open acceptance work |
9
+ | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
10
+ | M0: public contracts | Original public fixtures, MIT license, security/contribution guidance, schemas, explicit package allowlist, dependency notices and CI definitions. `STATUS.md`, `SECURITY.md`, `RELEASE.md`. | Public source and npm alpha.1 are published. Hosted CI passed at `bfc8cc4`; alpha.2 requires its own release commit, CI and publication verification. |
11
+ | M1: executable foundation | Shared CLI/library/MCP engine, bounded inventory/runner, startup trust, native Node/Python/Go/PHP profiles, protocol and lifecycle regressions. `ARCHITECTURE.md`, `STATUS.md`, `MCP-COMPATIBILITY.md`. Fresh installed application-client profiles now have evidence in `CLIENTS.md`. | Application-client coverage beyond the named profiles. PHP remains unavailable when the consumer has no prepared runtime. |
12
+ | M2: practical language validation | Explicit JS/TS, Python, Go and PHP native tool profiles, structured diagnostics/test evidence, versions, environments, workspace selection, scope accounting, SARIF/JUnit and finding ratchets. `LANGUAGES.md`, adapter documents, `WORKSPACES.md`, `FINDING-POLICY.md`, `NATIVE-CI.md`. | Hosted toolchain profiles passed at `52ba415`. Wider tool versions/framework configurations must be promoted separately; detection is not execution support. |
13
+ | M3: framework/contracts | Native Laravel, Vue Router/Nuxt, Django/FastAPI assembly projections; imported runtime comparison, explicit architecture boundaries, producer/consumer schemas and a built package consumer. `RUNTIME-INVENTORY.md`, framework documents, `CONTRACTS.md`, `ARCHITECTURE-POLICY.md`, `examples/package-contract/README.md`. | Broader native semantics/import collection and live service integration are not implemented. Synthetic evidence does not establish equivalent results in a private application; private integration feedback must remain private. |
14
+ | M4: ecosystem/distribution | Bounded Rust, Java, C#, Ruby, Swift, Clang and actionlint profiles; trusted external adapters, pinned data-only pack distribution, fresh offline package checks, production notice audit, measured performance and unpublished registry metadata. `LANGUAGES.md`, `EXTERNAL-ADAPTERS.md`, `PACK-DISTRIBUTION.md`, `PERFORMANCE.md`, `RELEASE.md`. | Alpha.2 release verification and MCP Registry registration. Windows execution and the unimplemented subsequent integrations in `LANGUAGES.md` remain unsupported. Runtime/container/development dependency provenance is broader than the production npm notice audit. |
15
+ | M5: measured assistance | Advisory guidance, bounded Node mutation experiments, explicit-graph impact measurements, optional local/model review exchange, durable library task storage/worker, development evaluation and externally authored ESLint and Ruff integration cohorts. `GUIDANCE.md`, `MUTATIONS.md`, `IMPACT-MEASUREMENT.md`, `REVIEW-EXCHANGE.md`, `VALIDATION-TASKS.md`, `EVALUATION.md`, `EXTERNAL-EVALUATION.md`, `EXTERNAL-RUFF-EVALUATION.md`. | Standard MCP Tasks wire integration; wider held-out rule-family/review evidence, prior-workflow comparison and representative cost/latency measurement. No general equal-or-better review-quality claim is supported. |
16
16
 
17
17
  ## Remaining work that can proceed locally
18
18
 
@@ -43,11 +43,12 @@ run. The local worker/store are available independently; standard Tasks must sta
43
43
  unadvertised until routing and the integrated wire/lifecycle suite pass. See
44
44
  `MCP-COMPATIBILITY.md` for the reproduction and upstream issue.
45
45
 
46
- The public repository and initial commit `60131d6` are available on `main`.
47
- All 13 hosted jobs passed at `52ba415`, recorded in `NATIVE-CI.md`.
48
- That result identifies the source baseline, not an unpublished preview package. Package publishing, GitHub releases and registry
49
- registration have not been performed. The repository's explicit-action
50
- requirements still apply. `RELEASE.md` defines the concrete
46
+ The public repository and npm preview `0.1.0-alpha.1` are published. The
47
+ [hosted run at bfc8cc4](https://github.com/stsepelin/checktrail/actions/runs/35585998184)
48
+ passed all jobs. Alpha.2 adds [setup commands](ONBOARDING.md); it requires its own
49
+ release CI and publication. GitHub releases and MCP Registry registration remain
50
+ pending. The repository's explicit-action requirements still apply.
51
+ `RELEASE.md` defines the concrete
51
52
  candidate checks and the authorization sequence; a local green run does not
52
53
  replace external acceptance.
53
54
 
@@ -58,7 +58,9 @@ pass by a parser. Source changes during execution invalidate a green result.
58
58
 
59
59
  Use bounded process output and timeouts, terminate the process group on supported
60
60
  POSIX hosts, and propagate cancellation. No automatic dependency installation,
61
- source rewriting, infrastructure startup, deployment or repository mutation.
61
+ source rewriting, infrastructure startup or deployment. The explicit `init --write`
62
+ setup command can create a new `checktrail.json`; it preserves existing
63
+ configuration and grants no execution. See [ONBOARDING.md](ONBOARDING.md).
62
64
  Executed project code still has the process user's privileges; this is not a
63
65
  sandbox. Tests may modify files or access networks and must be trusted accordingly.
64
66
 
@@ -1,14 +1,19 @@
1
1
  # Install the preview
2
2
 
3
- The first preview version is `0.1.0-alpha.1`, intended for npm's `next` tag.
4
- Check the [npm package page](https://www.npmjs.com/package/@stsepelin/checktrail)
5
- for availability. The registry commands below require that version to be published;
6
- before publication, use the source checkout or a reviewed local tarball.
3
+ The published preview is `0.1.0-alpha.1` on
4
+ [npm](https://www.npmjs.com/package/@stsepelin/checktrail).
5
+ Use the exact version below. The registry currently assigns both `next` and
6
+ `latest` to that preview; `latest` is not a stable-release guarantee.
7
+ The alpha.2 candidate adds [project setup and diagnosis](ONBOARDING.md) and is
8
+ available from source or a reviewed candidate tarball until published.
7
9
 
8
10
  Use Node.js 22 or newer on macOS or Linux. Windows execution is not supported.
9
11
  Install each project's compilers, linters and test runners separately; Checktrail
10
12
  does not download them. Missing tools produce incomplete results.
11
13
 
14
+ For agent workflows, see [installing skills with `npx skills`](SKILLS.md).
15
+ Skills install separately from the engine and MCP configuration.
16
+
12
17
  ## CLI
13
18
 
14
19
  Install the exact version once:
@@ -84,7 +89,7 @@ Validation uses asynchronous calls and supports cancellation. Standard MCP Tasks
84
89
  is not advertised; the durable worker is a separate library API. See
85
90
  [client coverage](CLIENTS.md) and [MCP compatibility](MCP-COMPATIBILITY.md).
86
91
 
87
- ## Before npm publication
92
+ ## Source checkout or unpublished candidate
88
93
 
89
94
  Build the public source checkout:
90
95
 
package/docs/LANGUAGES.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Language and ecosystem roadmap
2
2
 
3
+ The alpha.2 candidate's [setup guide](ONBOARDING.md) describes conservative
4
+ per-language configuration proposals and static tool diagnosis. Setup does not
5
+ extend the execution capabilities or native evidence listed below.
6
+
3
7
  Capability levels are discovery, planning, execution, structured evidence,
4
8
  semantic rules, and integration validation. None implies the next. This file's
5
9
  initial scope column describes the experimental implementation. Node, Python,
@@ -0,0 +1,128 @@
1
+ # Project setup
2
+
3
+ These commands are new in the unpublished `0.1.0-alpha.2` candidate. Use the
4
+ source checkout or a reviewed candidate tarball, with Node.js 22+ on macOS/Linux.
5
+
6
+ ## Preview and create a policy
7
+
8
+ ```sh
9
+ checktrail init --root "$PWD"
10
+ checktrail init --root "$PWD" --write
11
+ checktrail doctor --root "$PWD" --detailed
12
+ ```
13
+
14
+ `init` returns JSON with a proposed `configuration`. The preview changes nothing.
15
+ `--write` creates `checktrail.json` only when every discovered ecosystem has a
16
+ selected supported check, publishing complete contents without replacing an
17
+ existing file. A valid existing policy returns `preserved`, retaining its bytes,
18
+ packs, environment requirements and workspace graph. Invalid policies, directories
19
+ and symlinks are errors and remain untouched. There is no overwrite option.
20
+
21
+ The preview includes relative project paths, groups ecosystems sharing a directory
22
+ and preserves nested project boundaries. It does not infer workspace dependencies,
23
+ grant execution, install tools, run scripts or import project code. Use `doctor`
24
+ and the detailed plan to inspect prerequisites before running validation.
25
+
26
+ | Ecosystem | Initial selection |
27
+ | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
28
+ | JavaScript / TypeScript | Exact test scripts `node --test`, `vitest run`, `jest`, or `playwright test`; other commands need selection. Linters and type checks require explicit selection. |
29
+ | Python | Explicit runner/check selection required; a manifest cannot identify a test framework. |
30
+ | Go | Existing format, vet and test defaults. |
31
+ | PHP | Syntax only; tests and analysis require explicit selection. |
32
+ | Rust, Java, C#, Ruby, Swift, C/C++ | Existing bounded adapter defaults; profiles, tools and dependencies still need preparation. |
33
+ | Infrastructure | GitHub Actions checking where applicable; other infrastructure remains an unresolved gap. |
34
+
35
+ `needs-selection` exits `2`, returns no partial configuration and writes nothing.
36
+ Its `unresolved` entries list paths, ecosystems and registered choices; those
37
+ choices do not promise tools are installed or applicable to every source file.
38
+ Repeated `--check PATH#CHECK_ID` arguments select the complete check set for a path:
39
+
40
+ ```sh
41
+ checktrail init --root "$PWD" --check '.#python.pytest' --check '.#python.ruff'
42
+ checktrail init --root "$PWD" --check '.#python.pytest' --check '.#python.ruff' --write
43
+ ```
44
+
45
+ Paths must exactly match discovered roots. For a polyglot directory, include
46
+ checks for every discovered ecosystem there. Unmentioned paths keep defaults.
47
+ Unknown and duplicate IDs are errors. Setup never silently drops unsupported
48
+ ecosystems. External adapters and private overlays are supported by planning and
49
+ diagnosis but are not generated by `init`.
50
+
51
+ ## Diagnose setup without execution
52
+
53
+ `doctor` reuses the planner. It reports invalid configuration, unavailable checks,
54
+ missing/non-executable programs, invalid JS tool metadata, missing required
55
+ environment, empty plans, unsupported platforms and ecosystems omitted by policy.
56
+ An intentionally narrowed policy can therefore produce `unselected-project`.
57
+
58
+ Executable checks use the effective PATH and file permissions. Diagnosis never
59
+ runs version commands, imports modules, boots frameworks or runs tests. Prepare
60
+ native tools and activate Python environments on the PATH used for validation.
61
+
62
+ Output always includes `validationPerformed: false` and unverified runtime
63
+ properties. `no-static-blockers` exits `0`; `attention-required` exits `2`.
64
+ Neither means validation passed. Tool compatibility, importable modules, services
65
+ and execution results still need a trusted `run`.
66
+
67
+ Summary output omits paths and raw errors. `--detailed` adds paths and diagnostic
68
+ details that can contain absolute paths. Supported options include
69
+ `--policy-overlay`, pinned `--adapter` references and `--allow-env NAME`.
70
+ Environment values are not printed. Git selection and execution flags are rejected.
71
+
72
+ ## Generate MCP configuration
73
+
74
+ ```sh
75
+ checktrail mcp-config --root "$PWD" --client codex
76
+ checktrail mcp-config --root "$PWD" --client claude-code
77
+ checktrail mcp-config --root "$PWD" --client claude-desktop
78
+ checktrail mcp-config --root "$PWD" --client cursor
79
+ checktrail mcp-config --root "$PWD" --client vscode
80
+ ```
81
+
82
+ Output is JSON containing `format` and a `configuration` string. Merge the decoded
83
+ string's server entry into the appropriate client configuration. The generator
84
+ never opens or overwrites client files. Do not redirect the JSON envelope over
85
+ an existing configuration.
86
+
87
+ | Client | Generated format / location |
88
+ | -------------- | ------------------------------------------------------------- |
89
+ | Codex | TOML `mcp_servers.checktrail`; Codex `config.toml`. |
90
+ | Claude Code | JSON `mcpServers.checktrail`; project `.mcp.json`. |
91
+ | Claude Desktop | JSON `mcpServers.checktrail`; developer MCP configuration. |
92
+ | Cursor | JSON `mcpServers.checktrail`; `.cursor/mcp.json`. |
93
+ | VS Code | JSON `servers.checktrail`, `type: stdio`; `.vscode/mcp.json`. |
94
+
95
+ Snippets capture the canonical absolute root and pin the generating engine version
96
+ in `npx --yes --ignore-scripts @stsepelin/checktrail@VERSION serve`. Execution
97
+ and detailed output remain disabled; client trust settings still apply. Roots
98
+ containing `${` are rejected because client interpolation could change the root.
99
+
100
+ Generation needs no network; starting npx may download the pinned package. The
101
+ version must be published first. For an unpublished candidate, use its installed
102
+ absolute `checktrail` executable with `serve --root /absolute/project` instead.
103
+ After reviewing an update, regenerate/merge the entry and restart the client.
104
+ Updating a global CLI does not change an npx version pin.
105
+
106
+ Formats follow official [Codex](https://developers.openai.com/codex/mcp/),
107
+ [Claude Code](https://code.claude.com/docs/en/mcp),
108
+ [Cursor](https://cursor.com/docs/mcp), and
109
+ [VS Code](https://code.visualstudio.com/docs/agent-customization/mcp-servers)
110
+ documentation. Generation is not proof of a client connection; [CLIENTS.md](CLIENTS.md)
111
+ records tested application profiles and limits.
112
+
113
+ ## Upgrade and rollback verification
114
+
115
+ Build and prepare the npm cache for both reviewed artifacts, then run:
116
+
117
+ ```sh
118
+ node scripts/verify-package-upgrade.mjs /absolute/baseline.tgz /absolute/candidate.tgz
119
+ ```
120
+
121
+ The verifier installs baseline → candidate → baseline into one isolated consumer
122
+ offline with lifecycle scripts disabled. Each stage checks the CLI version,
123
+ planning, a native Node test, MCP planning and denied untrusted execution. Project
124
+ source, policy and existing client configuration must remain byte-identical.
125
+ The candidate must preserve the policy through `init --write`, diagnose it, and
126
+ import the baseline report through SARIF export. Output records artifact hashes
127
+ and measured stages. This exercises a synthetic Node workflow, not migration of
128
+ every language/tool profile.
package/docs/RELEASE.md CHANGED
@@ -1,12 +1,20 @@
1
1
  # Release preparation
2
2
 
3
3
  The source is public at [stsepelin/checktrail](https://github.com/stsepelin/checktrail);
4
- the first preview is `0.1.0-alpha.1`. `server.json` describes the
5
- intended `io.github.stsepelin/checktrail` MCP registry identity and the matching
6
- `@stsepelin/checktrail` npm package. The npm and registry names are proposed
7
- metadata, not evidence of a published package or registry entry. Package publishing
8
- is configured for public access on npm's `next` tag. No credentials or automatic
9
- publishing workflow are stored in this repository.
4
+ `@stsepelin/checktrail@0.1.0-alpha.1` is published on npm. Its downloaded artifact
5
+ matched the reviewed tarball with SHA-256
6
+ `84003e184805b6c5362c0801c702a72e415040ae5142fcd70f01eb9758637d04`.
7
+ Fresh registry installation, CLI and MCP startup were verified. The alpha.2
8
+ candidate adds [setup and diagnosis](ONBOARDING.md); it is not yet published.
9
+ `server.json` describes the intended `io.github.stsepelin/checktrail` MCP Registry
10
+ identity with the candidate's matching npm version. Registry registration remains
11
+ pending. No credentials or automatic publishing workflow are stored here.
12
+
13
+ Publication is configured for npm's `next` tag. After alpha.1 publication, the
14
+ registry assigned both `next` and `latest` to that preview; attempts to remove
15
+ `latest` returned HTTP 400. The cause is unresolved. Use exact versions and
16
+ resolve the tag policy before publishing another candidate; do not treat `latest`
17
+ as evidence of a stable release or republish an existing version.
10
18
 
11
19
  ## Prepared artifacts
12
20
 
@@ -24,8 +32,8 @@ publishing workflow are stored in this repository.
24
32
  loads the installed metadata and verifies its actual startup command.
25
33
  - CI definitions cover the host suite and prepared native profiles. Local
26
34
  containers and package checks are evidence only for the environments actually
27
- exercised. All 13 hosted jobs passed at source baseline `52ba415`; the preview
28
- release commit requires its own run. The local Claude Code health/discovery and
35
+ exercised. The [hosted run at bfc8cc4](https://github.com/stsepelin/checktrail/actions/runs/35585998184)
36
+ passed all jobs; the alpha.2 release commit requires its own run. The local Claude Code health/discovery and
29
37
  Codex direct app-server profiles have fresh-install evidence in `CLIENTS.md`.
30
38
 
31
39
  The metadata follows the official registry
@@ -61,7 +69,7 @@ After explicit approval and npm authentication for the `@stsepelin` scope, publi
61
69
  the approved file, not a newly packed working tree:
62
70
 
63
71
  ```sh
64
- npm publish /absolute/path/stsepelin-checktrail-0.1.0-alpha.1.tgz \
72
+ npm publish /absolute/path/stsepelin-checktrail-0.1.0-alpha.2.tgz \
65
73
  --tag next --access public --ignore-scripts --registry=https://registry.npmjs.org
66
74
  ```
67
75
 
@@ -93,6 +101,8 @@ GitHub private vulnerability reporting is enabled. Use the channel linked in
93
101
  Run the corresponding native verification helpers for every advertised profile.
94
102
  Record actual tool/platform results and explicit skips. Repeat registry schema
95
103
  validation against its pinned bytes.
104
+ Run `scripts/verify-package-upgrade.mjs` with the reviewed previous and candidate
105
+ tarballs to verify offline upgrade, policy/report compatibility and rollback.
96
106
  3. Inspect the exact tarball and its SHA-256, its source revision, dependency/notice
97
107
  report, package allowlist, public examples and documentation. The smoke helper
98
108
  compares repeated packing of the same checkout and tests a fresh offline install;
package/docs/SKILLS.md ADDED
@@ -0,0 +1,123 @@
1
+ # Install agent skills with npx skills
2
+
3
+ Checktrail provides portable workflows for setup, validation and review:
4
+
5
+ | Skill | Use it for |
6
+ | --------------------- | ------------------------------------------------------------------------------ |
7
+ | `checktrail-setup` | Configure project roots, select supported language checks and connect MCP |
8
+ | `checktrail-validate` | Run authorized checks and distinguish passed, failed and incomplete evidence |
9
+ | `checktrail-review` | Review code and test adequacy using validation evidence and advisory questions |
10
+
11
+ Each skill is self-contained in `skills/<name>/SKILL.md` and follows the
12
+ [Agent Skills format](https://agentskills.io/specification). The
13
+ [Vercel skills CLI](https://github.com/vercel-labs/skills) installs these folders
14
+ from GitHub. No Checktrail plugin or separate skills registry registration is
15
+ required for installation by repository URL.
16
+
17
+ ## Install
18
+
19
+ These GitHub commands require the `skills/` directory to be present on the public
20
+ repository's default branch. For an unpublished checkout, use the local command
21
+ below. Listing the remote source first verifies what is available:
22
+
23
+ ```sh
24
+ npx skills add stsepelin/checktrail --list
25
+ npx skills add stsepelin/checktrail
26
+ ```
27
+
28
+ The interactive installer lets you choose skills and target agents. For an
29
+ explicit project installation, run from the repository where you want to use
30
+ Checktrail:
31
+
32
+ ```sh
33
+ npx skills add stsepelin/checktrail \
34
+ --skill checktrail-setup checktrail-validate checktrail-review \
35
+ --agent codex claude-code cursor
36
+ ```
37
+
38
+ Choose only the agents you use. Add `--global` for a personal installation shared
39
+ across projects, or `--yes` when deliberately skipping installer prompts. The
40
+ default installation uses project directories; it does not configure an MCP server.
41
+ Use `--copy` if independent copies are preferable to the installer's default links.
42
+
43
+ To install from a local checkout before pushing, substitute its absolute path:
44
+
45
+ ```sh
46
+ npx skills add /absolute/path/to/checktrail --skill checktrail-validate --agent codex
47
+ ```
48
+
49
+ The CLI's agent target names are installer options, not evidence that Checktrail
50
+ has been tested end-to-end in every editor. See [client coverage](CLIENTS.md).
51
+ Reload skills or start a new session as required by the selected agent. Example
52
+ requests are "Set up Checktrail for this repository", "Validate these changes
53
+ with Checktrail", and "Review this diff using Checktrail evidence".
54
+
55
+ ## Install the engine separately
56
+
57
+ `npx skills` installs instructions. It does not install the npm engine, native
58
+ language tools, an MCP server, or execution permissions. The skills support an
59
+ existing MCP connection or the CLI, including the published preview:
60
+
61
+ ```sh
62
+ npx --yes --ignore-scripts @stsepelin/checktrail@0.1.0-alpha.1 plan --root /absolute/project
63
+ ```
64
+
65
+ Use Node.js 22+ on macOS or Linux. See [installation](INSTALLATION.md) for persistent
66
+ CLI installation, MCP registration and operator-controlled execution. Skills do
67
+ not expand native language coverage, grant trust, or replace required CI checks.
68
+
69
+ ## Update and remove
70
+
71
+ For GitHub-installed project skills, update just Checktrail's workflows:
72
+
73
+ ```sh
74
+ npx skills update checktrail-setup checktrail-validate checktrail-review --project
75
+ ```
76
+
77
+ Use `--global` instead of `--project` for a global installation. Updates replace
78
+ installed instructions; keep project-specific policy in your project's own files.
79
+ Retain and review the project installation's `skills-lock.json` and file changes.
80
+ For local-path installations, re-run `skills add` against the updated checkout.
81
+
82
+ The installer version used for local verification is `skills@1.7.0`. It aliases
83
+ `skills check` to `skills update`; do not use `check` as a read-only update probe.
84
+ Use `npx skills list` to inspect installed skills. Pin the installer itself with
85
+ `npx skills@1.7.0` when reproducing the installation checks.
86
+
87
+ Skill updates and engine updates are separate. The skills declare the Checktrail
88
+ version they target. To update the engine, deliberately select a compatible npm
89
+ version and restart the MCP process. Updating skills never changes its root,
90
+ execution grant or output disclosure settings. For a reproducible skill revision,
91
+ install from a reviewed GitHub tree URL containing a commit SHA and the selected
92
+ skill path; re-add that same revision to roll back. Do not treat following a branch
93
+ as an immutable pin.
94
+
95
+ Remove the project skills with:
96
+
97
+ ```sh
98
+ npx skills remove checktrail-setup checktrail-validate checktrail-review
99
+ ```
100
+
101
+ Add `--global` for a global removal. This removes skills, not the separately
102
+ installed engine or MCP configuration.
103
+
104
+ ## Verification boundaries
105
+
106
+ Local checks exercise discovery, selective installation, copy/link destinations,
107
+ file integrity, reinstallation from an updated local source and removal in
108
+ temporary projects. They do not modify personal agent installations. Skill format
109
+ validation does not prove model behavior or improved review quality. Installation
110
+ from the public GitHub source and remote update verification require the changes
111
+ to be pushed; a local installation is not evidence of either.
112
+
113
+ Reproduce the installation checks from the Checktrail checkout:
114
+
115
+ ```sh
116
+ npm install --prefix .checktrail/skills-tools --ignore-scripts --no-audit --no-fund \
117
+ --package-lock=false --save-exact skills@1.7.0
118
+ node scripts/verify-skills-install.mjs .checktrail/skills-tools/node_modules/skills/bin/cli.mjs
119
+ ```
120
+
121
+ The helper uses temporary project and installer-state directories, exercises the
122
+ real installer, and removes its fixtures afterward. It does not run a model,
123
+ register MCP, install global skills, or invoke remote skill updates.
package/docs/STATUS.md CHANGED
@@ -3,12 +3,19 @@
3
3
  This is an experimental foundation with public source at
4
4
  [stsepelin/checktrail](https://github.com/stsepelin/checktrail).
5
5
  Check the [installation guide](INSTALLATION.md) for package availability and setup.
6
- All 13 hosted jobs passed at `52ba415`; the exact run and earlier cache/path
7
- failures are recorded in `NATIVE-CI.md`. The `0.1.0-alpha.1` preview changes
8
- release metadata and documentation; its publication is a separate gate.
6
+ The `0.1.0-alpha.1` preview is published on npm. The newer
7
+ [hosted run at bfc8cc4](https://github.com/stsepelin/checktrail/actions/runs/35585998184)
8
+ passed all jobs; earlier toolchain evidence remains in `NATIVE-CI.md`.
9
+ The alpha.2 candidate adds setup commands and requires its own release CI and
10
+ publication. MCP Registry registration remains pending.
9
11
 
10
12
  ## Implemented
11
13
 
14
+ - Alpha.2 candidate: conservative multi-language `init`, execution-free `doctor`,
15
+ and version-pinned MCP configuration output for Codex, Claude Code/Desktop,
16
+ Cursor and VS Code. Existing files are preserved. See [ONBOARDING.md](ONBOARDING.md)
17
+ for scope, ambiguity handling and package upgrade/rollback verification.
18
+
12
19
  - Exact required-test accounting across prepared CI language profiles and native
13
20
  container helpers, including dedicated Ruby/Swift jobs. Skipped, missing,
14
21
  duplicate, TODO or failing cases cannot satisfy these profiles. Hosted profiles
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stsepelin/checktrail",
3
- "version": "0.1.0-alpha.1",
3
+ "version": "0.1.0-alpha.2",
4
4
  "mcpName": "io.github.stsepelin/checktrail",
5
5
  "description": "Local code validation with execution evidence, a CLI, and MCP tools.",
6
6
  "type": "module",
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.stsepelin/checktrail",
4
4
  "title": "Checktrail",
5
5
  "description": "Local code validation with explicit execution trust and evidence of what actually ran.",
6
- "version": "0.1.0-alpha.1",
6
+ "version": "0.1.0-alpha.2",
7
7
  "repository": {
8
8
  "url": "https://github.com/stsepelin/checktrail",
9
9
  "source": "github"
@@ -13,7 +13,7 @@
13
13
  "registryType": "npm",
14
14
  "registryBaseUrl": "https://registry.npmjs.org",
15
15
  "identifier": "@stsepelin/checktrail",
16
- "version": "0.1.0-alpha.1",
16
+ "version": "0.1.0-alpha.2",
17
17
  "runtimeHint": "npx",
18
18
  "transport": {
19
19
  "type": "stdio"