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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@ jobs:

- name: Verify Packed CLI
run: pnpm verify:packed

- name: Kernel policy check
run: pnpm build && node dist/cli/index.js policy check --ci
185 changes: 9 additions & 176 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,188 +1,21 @@
# AGENTS.md
<!-- Generated by Kernel. Edit canonical source under .agent/ instead. -->

This repository builds **Kernel**, a repo-local quality system and portable operating layer for coding agents.
# AGENTS.md

Kernel's purpose is to make agent-written software work more reliable, reviewable, portable, and evidence-backed across Codex, Claude Code, Cursor, Kiro, GitHub Copilot, Gemini CLI, OpenCode, Windsurf, Junie, Zed, and future ADEs.
This repository uses **Kernel**, a repo-local quality system and portable operating layer for coding agents.

## Prime directive

No contract, no implementation. No evidence, no completion. No handoff, no continuity.

## Working rules for Codex

Before non-trivial implementation:
## Working rules

1. Read this `AGENTS.md`.
1. Read this `AGENTS.md` before non-trivial implementation.
2. Read `.agent/kernel.yaml` if present.
3. Create or update `.agent/state/current-task.md`.
4. Identify the relevant Kernel skill or skills.
5. Define goal, non-goals, assumptions, risk zones, verification, and done criteria.
6. Prefer minimal, testable changes.
7. Record verification evidence before claiming completion.
8. Create a handoff packet if work is incomplete, long-running, or likely to move to another ADE.

## Repository goals

Build a TypeScript CLI named `kernel` that can:

- Initialize Kernel in a repository.
- Generate `.agent/` canonical state.
- Create task contracts.
- Create evidence ledgers.
- Create handoff packets.
- Generate repository maps.
- Compile ADE-specific adapters.
- Validate Kernel installation and generated outputs.
- Lint skills and trigger descriptions.
- Run skill regression fixtures.

## Recommended stack

Use TypeScript and Node.js unless the repository is intentionally changed.

Recommended tools:

- `pnpm`
- `vitest`
- `zod`
- `commander` or `clipanion`
- `tsx`
- `eslint`
- `prettier`

## Expected commands

Prefer these commands when available:

```bash
pnpm install
pnpm typecheck
pnpm lint
pnpm test
pnpm build
```

If a command is missing, inspect `package.json` and update this file only if the durable command set is clear.

## Implementation priorities

Build in this order:

1. Project skeleton and CLI help.
2. Config schema and loader.
3. `kernel init`.
4. Task, evidence, and handoff templates.
5. Adapter compiler interface.
6. Codex adapter.
7. Claude Code adapter.
8. Cursor adapter.
9. Kiro adapter.
10. GitHub Copilot adapter.
11. `kernel validate`.
12. Skill linting and regression fixtures.

## Architecture requirements

Keep pure rendering logic separate from filesystem writes.

Recommended structure:

```txt
src/
cli/
core/
adapters/
validators/
templates/
utils/
tests/
fixtures/
snapshots/
```

## Adapter design

Kernel has one canonical source under `.agent/`. ADE-specific files are generated outputs.

Do not manually fork the content logic for every ADE. Implement adapters as renderers over shared Kernel data.
3. Create or update `.agent/state/current-task.md` before implementation.
4. Prefer minimal, testable changes.
5. Record verification evidence before claiming completion.
6. Create a handoff packet when work is incomplete, long-running, or likely to move to another ADE.

Generated outputs should include a header such as:

```txt
<!-- Generated by Kernel. Edit canonical source under .agent/ instead. -->
```

When practical, preserve manual sections between markers:

```txt
<!-- kernel:manual:start -->
<!-- kernel:manual:end -->
```

## Quality requirements

For any non-trivial code change:

- Add or update tests.
- Run targeted tests.
- Run typecheck when available.
- Record commands and results in evidence.
- Avoid unrelated formatting churn.
- Avoid broad rewrites for surgical fixes.
- Do not change public behavior unless the task contract says so.

## Risk policy

Treat these as high-risk:

- Adapter generation logic.
- File overwrite logic.
- Config migration logic.
- Shell command execution.
- Package publishing.
- CI workflows.
- User-authored instruction files.

Never silently overwrite user files. Prefer explicit `--force`, dry-run output, backups, or preserved manual sections.

## Testing policy

Use snapshot tests for generated adapter outputs.

Use unit tests for:

- Config parsing.
- Path resolution.
- Template rendering.
- Adapter output paths.
- Manual section preservation.
- Validation errors.

Use fixture repositories for:

- Empty repo.
- TypeScript package.
- Monorepo.
- Existing AGENTS.md.
- Existing ADE-specific files.

## Documentation policy

Keep docs Obsidian-friendly:

- Use Markdown.
- Use wikilinks for internal docs where useful.
- Avoid vendor lock-in in conceptual docs.
- Keep implementation docs precise enough for Codex to act on.

## Completion standard

A task is not complete until the response includes:

- What changed.
- What verification ran.
- What evidence exists.
- What risks remain.
- Any recommended next action.

If verification could not be run, say so explicitly and mark the work as unverified or partially verified.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ This project follows semantic versioning once public releases begin.
- GitHub CI workflow.
- npm release-readiness checklist and gated manual release workflow skeleton.
- Hardened npm trusted-publishing release workflow constraints and bootstrap documentation.
- Balanced-track product improvements: lint-ready skill doc fixes, 35-skill vault generation, MVP eval fixtures.
- `kernel task show` and `kernel evidence add-command` CLI commands.
- Canonical-skill-driven adapter compiler for priority ADEs.
- Gemini CLI adapter (`kernel compile gemini`) generating `GEMINI.md` and `.gemini/settings.json`.
- Zed, OpenCode, Windsurf, and Junie tier-2 adapters.
- `kernel init --adapters` for selective adapter enablement in generated config.
- Selective `kernel map --commands/--tests/--risk` flags.
- Adapter compile deduplication for shared output paths across ADEs.
- Expanded eval fixtures for context-router, risk-map, diff-surgeon, and repo-cartographer.
- Updated CLI Command Spec for implemented commands and flags.
- Repo intelligence (0.4): v2 map schemas, CODEOWNERS, monorepo workspaces, Makefile/justfile command detection, config-aware risk maps.
- Policy engine (0.5): `policy-gate.yaml`, `kernel policy check`, verification escalation, CI policy validation.
- `kernel init` seeds `.agent/policies/policy-gate.yaml`.

### Notes

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ kernel compile claude
kernel compile cursor
kernel compile kiro
kernel compile github-copilot
kernel compile gemini
kernel compile zed
kernel compile opencode
kernel compile windsurf
kernel compile junie
```

## Development Checks
Expand Down
75 changes: 75 additions & 0 deletions src/adapters/canonical-skills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { access, readdir, readFile } from 'node:fs/promises';
import { join } from 'node:path';

import type { KernelConfig } from '../core/config.js';

export interface CanonicalSkill {
name: string;
relativePath: string;
content: string;
}

export async function loadCanonicalSkills(rootDir: string, config: KernelConfig): Promise<CanonicalSkill[]> {
const skillsRoot = join(rootDir, config.canonical.skills_dir);

if (!(await pathExists(skillsRoot))) {
return [];
}

const entries = await readdir(skillsRoot, { withFileTypes: true });
const skills: CanonicalSkill[] = [];

for (const entry of entries.filter((item) => item.isDirectory()).sort((left, right) => left.name.localeCompare(right.name))) {
const skillPath = join(skillsRoot, entry.name, 'SKILL.md');
if (!(await pathExists(skillPath))) {
continue;
}

const content = await readFile(skillPath, 'utf8');
skills.push({
name: entry.name,
relativePath: join(config.canonical.skills_dir, entry.name, 'SKILL.md').replace(/\\/g, '/'),
content
});
}

return skills;
}

export function findCanonicalSkill(skills: CanonicalSkill[], name: string): CanonicalSkill | undefined {
return skills.find((skill) => skill.name === name);
}

export function skillBodyWithoutFrontmatter(content: string): string {
const match = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/u.exec(content);
return match ? content.slice(match[0].length).trimStart() : content;
}

export function renderCursorRuleFromSkill(skillName: string, content: string): string {
const body = skillBodyWithoutFrontmatter(content);
const title = body.match(/^#\s+(.+)$/m)?.[1] ?? skillName;
return [`# ${title}`, '', body.replace(/^#\s+.+\n?/m, '').trim()].join('\n');
}

export function resolveCursorRuleContent(
skills: CanonicalSkill[],
skillName: string,
fallback: string,
manualSectionLines: string[]
): string {
const skill = findCanonicalSkill(skills, skillName);
const core = skill ? renderCursorRuleFromSkill(skill.name, skill.content) : fallback;
return [...core.split('\n'), '', ...manualSectionLines, ''].join('\n');
}

async function pathExists(path: string): Promise<boolean> {
try {
await access(path);
return true;
} catch (error) {
if (error instanceof Error && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT') {
return false;
}
throw error;
}
}
32 changes: 24 additions & 8 deletions src/adapters/claude.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,31 @@ import { canonicalSourceList, kernelProcedure, manualSection, primeDirective, sk

export const claudeAdapter: KernelAdapter = {
name: 'claude',
render({ config }) {
render({ config, canonicalSkills }) {
const projectName = config.project.name;
return [
const outputs = [
{
path: 'CLAUDE.md',
content: renderClaudeMd(projectName),
generated: true,
generated: true as const,
preserveManualSections: true
},
}
];

if (canonicalSkills.length > 0) {
for (const skill of canonicalSkills) {
outputs.push({
path: `.claude/skills/${skill.name}/SKILL.md`,
content: skill.content,
generated: true as const,
preserveManualSections: true
});
}
return outputs;
}

return [
...outputs,
{
path: '.claude/skills/kernel-core/SKILL.md',
content: renderClaudeSkill(
Expand All @@ -20,7 +36,7 @@ export const claudeAdapter: KernelAdapter = {
projectName,
'Follow Kernel task contracts, verification evidence, and handoff rules.'
),
generated: true,
generated: true as const,
preserveManualSections: true
},
{
Expand All @@ -31,7 +47,7 @@ export const claudeAdapter: KernelAdapter = {
projectName,
'Review risk zones, evidence, generated files, and missing validation before approval.'
),
generated: true,
generated: true as const,
preserveManualSections: true
},
{
Expand All @@ -42,7 +58,7 @@ export const claudeAdapter: KernelAdapter = {
projectName,
'Capture reproduction steps, failing checks, and green verification in Kernel evidence.'
),
generated: true,
generated: true as const,
preserveManualSections: true
},
{
Expand All @@ -53,7 +69,7 @@ export const claudeAdapter: KernelAdapter = {
projectName,
'Write a concise handoff packet under `.agent/handoffs/` before context is lost.'
),
generated: true,
generated: true as const,
preserveManualSections: true
}
];
Expand Down
Loading