mirror of
https://github.com/JuliusBrussee/caveman.git
synced 2026-09-14 18:02:35 +08:00
82864c8f4c
Single-commit port of the Caveman 2 tree onto the original repo history (candidate caveman-2@88878a4 applied over main@3098342). No unrelated-history merge; original history untouched. Preserved v1 surfaces: - skills/caveman/SKILL.md byte-for-byte, plus plugin mirror and caveman.skill zip - legacy CI (Node 18/20/22 installer + Python 3.11 suites) alongside engine-ci - cli/install.js compatibility shim forwarding to bin/install.js - .codex/config.toml ships both hooks and codex_hooks for older Codex (#617) - README Trendshift + Skills.sh badges and local star-history asset - v1.10.0-pinned curl installs; benchmarks/tmp-starcharts ignore rules Fixed for public same-repo release: - SECURITY.md vulnerability reporting points at this repository - release-binaries.yml publishes to this repo via job-scoped GITHUB_TOKEN (cross-repo PAT removed); binary-release environment still gates signing - packages/cli/PUBLISHING.md rewritten for packages/ layout and same-repo flow - profile-contract and provider-catalog lanes skip lane-scope gates on initial import so the launch PR can gate on their real validation steps - ANNOUNCEMENT.md network claim corrected: compression is local; requests still go to the provider you configured Caveman 2 stays opt-in: bin-v1.0.0 binaries and @caveman-ai/cli publish separately after this lands and soaks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BLvb5QniwYjmcawyssQNw9
58 lines
2.5 KiB
JavaScript
58 lines
2.5 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { isolatedCliEnv, runCli } from "./_cli.mjs";
|
|
|
|
test("learn implement launches a supported agent with the guarded learn prompt", async () => {
|
|
const isolated = isolatedCliEnv();
|
|
const cwd = mkdtempSync(join(tmpdir(), "caveman-learn-implement-"));
|
|
const argvPath = join(isolated.home, "agent-argv.json");
|
|
const claude = join(isolated.home, "bin", "claude");
|
|
writeFileSync(claude, `#!/usr/bin/env node
|
|
import { writeFileSync } from "node:fs";
|
|
writeFileSync(process.env.AGENT_ARGV_PATH, JSON.stringify(process.argv.slice(2)));
|
|
`, { mode: 0o755 });
|
|
mkdirSync(join(isolated.home, ".caveman-cloud"), { recursive: true });
|
|
writeFileSync(join(isolated.home, ".caveman-cloud", "config.json"), JSON.stringify({
|
|
wrap: { proxy: false, shrink: false, mcp: false, browse: false },
|
|
}));
|
|
isolated.env.PATH = `${join(isolated.home, "bin")}:${process.env.PATH}`;
|
|
isolated.env.AGENT_ARGV_PATH = argvPath;
|
|
|
|
try {
|
|
const out = await runCli(
|
|
["learn", "implement", "claude", "--prompt", "Focus on project instructions first."],
|
|
{ env: isolated.env, cwd },
|
|
);
|
|
assert.equal(out.code, 0, out.stderr);
|
|
const argv = JSON.parse(readFileSync(argvPath, "utf8"));
|
|
const prompt = argv.at(-1);
|
|
assert.match(prompt, /Use the caveman-learn skill/);
|
|
assert.match(prompt, /caveman learn report --json/);
|
|
assert.match(prompt, /Never edit load_bearing findings/);
|
|
assert.match(prompt, /ask before every edit/);
|
|
assert.match(prompt, /Focus on project instructions first/);
|
|
|
|
const skill = join(cwd, ".claude", "skills", "caveman-learn", "SKILL.md");
|
|
assert.equal(existsSync(skill), true, "agent handoff must install its safety guide");
|
|
assert.match(readFileSync(skill, "utf8"), /Consent per edit/);
|
|
assert.match(out.stderr, /learn guide installed/);
|
|
} finally {
|
|
isolated.cleanup();
|
|
}
|
|
});
|
|
|
|
test("learn implement help is short and does not launch an agent", async () => {
|
|
const isolated = isolatedCliEnv();
|
|
try {
|
|
const out = await runCli(["learn", "implement", "--help"], { env: isolated.env });
|
|
assert.equal(out.code, 0, out.stderr);
|
|
assert.match(out.stdout, /caveman learn implement \[claude\|codex\]/);
|
|
assert.match(out.stdout, /asks before every edit/);
|
|
} finally {
|
|
isolated.cleanup();
|
|
}
|
|
});
|