Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [12.3.1] - 2026-02-15

### Added
- Installer trigger-check regression tests for adopted private debug skills (`systematic-debugging`, `parallel-debugging`, `gh-fix-ci`).
- Installer trigger-check regression tests for legacy private skills (`audit-pr-skills`, `rebuild-skill-index`) after schema modernization.

### Changed
- Aligned `src/VERSION` with root `VERSION` for release consistency.

## [12.3.0] - 2026-02-15

### Added
Expand Down
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,53 @@ It gives you one clean control plane for:
- running from CLI or a local-first dashboard
- using verified bootstrap installers and signed, reproducible releases

## Table of Contents

- [Agent Prompt: Bootstrap ICA for This Local Environment](#agent-prompt-bootstrap-ica-for-this-local-environment)
- [Install First (Verified Bootstrap)](#install-first-verified-bootstrap)
- [Multi-Source Skills (Clear + Explicit)](#multi-source-skills-clear--explicit)
- [Dashboard Preview](#dashboard-preview)
- [Build From Source](#build-from-source)
- [CLI Usage (`ica`)](#cli-usage-ica)
- [Skill Publishing and Official Contribution](#skill-publishing-and-official-contribution)
- [Dashboard](#dashboard)
- [Supported Targets](#supported-targets)
- [Install Modes](#install-modes)
- [Scope Modes](#scope-modes)
- [Managed State](#managed-state)
- [Release + Supply Chain](#release--supply-chain)
- [Documentation](#documentation)
- [Legacy Deployment Paths Removed](#legacy-deployment-paths-removed)

## Agent Prompt: Bootstrap ICA for This Local Environment

```text
Bootstrap ICA for this local environment.

Your task:
1) Download and install this skill file into your own native skill storage (using your runtime's normal skill conventions):
https://raw.githubusercontent.com/intelligentcode-ai/skills/master/skills/ica-bootstrap/SKILL.md
2) Immediately execute the installed `ica-bootstrap` skill.
3) Let `ica-bootstrap` complete end-to-end setup, including:
- ICA CLI installation
- skills source registration/refresh
- installation of `ica-cli`
- verification (`ica doctor`, `ica list`)

Behavior requirements:
- Do the work directly on this machine.
- Do not ask me where skill folders are.
- Do not ask me to confirm routine steps.
- Ask only if credentials, permissions, or security policy block execution.
- If a command fails, diagnose and retry with the safest fallback automatically.

Final output:
- What you installed
- What you executed
- Current ICA health/status
- Exact blocker only if setup is still not complete
```

## Install First (Verified Bootstrap)

macOS/Linux:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
12.3.0
12.3.1
2 changes: 1 addition & 1 deletion src/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
12.2.0
12.3.1
83 changes: 83 additions & 0 deletions tests/installer/adopted-debug-skills.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { execFileSync } from "node:child_process";

const repoRoot = process.cwd();
const checkerScript = path.join(repoRoot, "scripts", "skill-trigger-check.mjs");
const privateSkillsRoot = path.join(repoRoot, "private-skills", "skills");
const hasPrivateSkills = fs.existsSync(privateSkillsRoot);

function runChecker(skillPath: string): { ok: true; stdout: string } | { ok: false; stdout: string; stderr: string } {
try {
const stdout = execFileSync(process.execPath, [checkerScript, "--skill", skillPath], {
cwd: repoRoot,
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});
return { ok: true, stdout };
} catch (error) {
const err = error as { stdout?: string | Buffer; stderr?: string | Buffer };
return {
ok: false,
stdout: typeof err.stdout === "string" ? err.stdout : (err.stdout?.toString("utf8") ?? ""),
stderr: typeof err.stderr === "string" ? err.stderr : (err.stderr?.toString("utf8") ?? ""),
};
}
}

const adoptedSkills = [
{
name: "systematic-debugging",
path: path.join(repoRoot, "private-skills", "skills", "systematic-debugging", "SKILL.md"),
expectedPhrases: [
"NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST",
"## Acceptance Tests",
"Positive trigger",
"Negative trigger",
"Behavior",
],
},
{
name: "parallel-debugging",
path: path.join(repoRoot, "private-skills", "skills", "parallel-debugging", "SKILL.md"),
expectedPhrases: [
"Analysis of Competing Hypotheses",
"## Acceptance Tests",
"Positive trigger",
"Negative trigger",
"Behavior",
],
},
{
name: "gh-fix-ci",
path: path.join(repoRoot, "private-skills", "skills", "gh-fix-ci", "SKILL.md"),
expectedPhrases: [
"GitHub Actions",
"gh pr checks",
"## Acceptance Tests",
"Positive trigger",
"Negative trigger",
"Behavior",
],
},
];

for (const skill of adoptedSkills) {
test(`adopted skill exists: ${skill.name}`, { skip: !hasPrivateSkills }, () => {
assert.equal(fs.existsSync(skill.path), true, `${skill.name} should exist at ${skill.path}`);
});

test(`adopted skill passes trigger checks: ${skill.name}`, { skip: !hasPrivateSkills }, () => {
const result = runChecker(skill.path);
assert.equal(result.ok, true, `${skill.name} should pass skill-trigger-check`);
});

test(`adopted skill includes TDD acceptance coverage: ${skill.name}`, { skip: !hasPrivateSkills }, () => {
const text = fs.readFileSync(skill.path, "utf8");
for (const phrase of skill.expectedPhrases) {
assert.match(text, new RegExp(phrase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "i"));
}
});
}
41 changes: 41 additions & 0 deletions tests/installer/private-skills-legacy-trigger.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { execFileSync } from "node:child_process";

const repoRoot = process.cwd();
const checkerScript = path.join(repoRoot, "scripts", "skill-trigger-check.mjs");
const privateSkillsRoot = path.join(repoRoot, "private-skills", "skills");
const hasPrivateSkills = process.env.ICA_REQUIRE_PRIVATE_SKILLS === "1" || fs.existsSync(privateSkillsRoot);

function runChecker(skillPath: string): { ok: true; stdout: string } | { ok: false; stdout: string; stderr: string } {
try {
const stdout = execFileSync(process.execPath, [checkerScript, "--skill", skillPath], {
cwd: repoRoot,
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
});
return { ok: true, stdout };
} catch (error) {
const err = error as { stdout?: string | Buffer; stderr?: string | Buffer };
return {
ok: false,
stdout: typeof err.stdout === "string" ? err.stdout : (err.stdout?.toString("utf8") ?? ""),
stderr: typeof err.stderr === "string" ? err.stderr : (err.stderr?.toString("utf8") ?? ""),
};
}
}

const legacySkills = [
path.join(repoRoot, "private-skills", "skills", "audit-pr-skills", "SKILL.md"),
path.join(repoRoot, "private-skills", "skills", "rebuild-skill-index", "SKILL.md"),
];

for (const skillPath of legacySkills) {
const skillName = path.basename(path.dirname(skillPath));
test(`legacy private skill passes trigger check: ${skillName}`, { skip: !hasPrivateSkills }, () => {
const result = runChecker(skillPath);
assert.equal(result.ok, true, `${skillName} should pass skill-trigger-check`);
});
}