Expose historical source import through CLI
This commit is contained in:
parent
77db2ecc1c
commit
fbe8ec1f13
|
|
@ -127,6 +127,7 @@ npx -y rea-agents doctor
|
|||
| Ask an agent to investigate an app and build a feature | Install the skill, then talk to your agent |
|
||||
| Inspect or decompile one part of an app from the Terminal | `rea analyze` or `rea decompile` |
|
||||
| Validate or canonicalize an Evidence v2 bundle | `rea evidence-import` or `rea evidence-export` |
|
||||
| Import source as historical reference | `rea import-reference-source` |
|
||||
|
||||
Filesystem evidence commands and MCP file tools are disabled until the operator approves absolute roots:
|
||||
|
||||
|
|
@ -136,6 +137,13 @@ rea evidence-import /absolute/path/to/evidence/bundle.json
|
|||
rea evidence-export /absolute/path/to/evidence/bundle.json /absolute/path/to/evidence/canonical.json
|
||||
```
|
||||
|
||||
Historical source import requires a separate allowlist and never treats source as current behavioral authority:
|
||||
|
||||
```bash
|
||||
export REA_REFERENCE_ROOTS_JSON='["/absolute/path/to/source"]'
|
||||
rea import-reference-source /absolute/path/to/source
|
||||
```
|
||||
|
||||
Exports never replace an existing file unless `--overwrite` is explicit. Imports are size/depth bounded, validate every Evidence v2 ID and manifest, and never execute bundle content.
|
||||
|
||||
Completion metadata is verifier-owned. Run `npm run completion:generate` after changing contracts, schemas, providers, scenarios, package metadata, verifier inputs, or the managed skill. CI runs `npm run completion:check`; it detects stale or tampered hashes and never rewrites a branch. Unsupported and unknown outcomes remain separate from passes, and a pass or failure requires indexed Evidence v2 IDs.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
},
|
||||
{
|
||||
"path": "scripts/verify-package.mjs",
|
||||
"sha256": "ffad65be3d5dde87c1e2d7b8886949066531e5b82933596b947507aab5f45b58"
|
||||
"sha256": "b3809e3b7593fcaf16c9f962fbfaea105caca168c2ed8fd07336804ebb581174"
|
||||
},
|
||||
{
|
||||
"path": "scripts/verify-real-hopper.mjs",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ const exec = promisify(execFile);
|
|||
const root = process.cwd();
|
||||
const workspace = await mkdtemp(join(tmpdir(), "rea-package-"));
|
||||
const evidenceRoot = join(workspace, "evidence");
|
||||
const referenceRoot = join(workspace, "reference-source");
|
||||
let tarball;
|
||||
|
||||
try {
|
||||
|
|
@ -44,7 +45,21 @@ try {
|
|||
const home = join(workspace, "home");
|
||||
const fakeBin = join(workspace, "bin");
|
||||
await mkdir(fakeBin, { recursive: true });
|
||||
await mkdir(evidenceRoot, { recursive: true });
|
||||
await Promise.all([
|
||||
mkdir(evidenceRoot, { recursive: true }),
|
||||
mkdir(join(referenceRoot, "src"), { recursive: true }),
|
||||
]);
|
||||
await Promise.all([
|
||||
writeFile(
|
||||
join(referenceRoot, "src", "main.ts"),
|
||||
'import "./dependency";\n',
|
||||
),
|
||||
writeFile(
|
||||
join(referenceRoot, "src", "dependency.ts"),
|
||||
"export const value = 1;\n",
|
||||
),
|
||||
writeFile(join(referenceRoot, ".env"), "PACKAGE_SECRET_SENTINEL=1\n"),
|
||||
]);
|
||||
const brew = join(fakeBin, "brew");
|
||||
const swVers = join(fakeBin, "sw_vers");
|
||||
const npx = join(fakeBin, "npx");
|
||||
|
|
@ -84,6 +99,8 @@ try {
|
|||
HOPPER_LAUNCHER_PATH: hopper,
|
||||
REA_NPX_LOG: npxLog,
|
||||
REA_EVIDENCE_ROOTS_JSON: JSON.stringify([evidenceRoot]),
|
||||
REA_REFERENCE_ROOTS_JSON: JSON.stringify([referenceRoot]),
|
||||
REA_REFERENCE_SECRET_PATTERNS_JSON: JSON.stringify([".env"]),
|
||||
};
|
||||
await exec(
|
||||
"npm",
|
||||
|
|
@ -99,6 +116,7 @@ try {
|
|||
!help.includes("setup") ||
|
||||
!help.includes("inventory-artifact") ||
|
||||
!help.includes("extract-artifact") ||
|
||||
!help.includes("import-reference-source") ||
|
||||
!llms.includes("decompile") ||
|
||||
!llms.includes("inventory-artifact") ||
|
||||
doctor.healthy !== expectedDoctorHealth ||
|
||||
|
|
@ -124,6 +142,20 @@ try {
|
|||
artifactInventory.normalized_result?.manifest?.root_format !== "zip"
|
||||
)
|
||||
throw new Error("packaged artifact inventory CLI failed");
|
||||
const referenceImport = json(
|
||||
await run(
|
||||
cli,
|
||||
["import-reference-source", referenceRoot, "--json"],
|
||||
environment,
|
||||
),
|
||||
);
|
||||
if (
|
||||
referenceImport.authority !== "historical-reference" ||
|
||||
referenceImport.root_alias !== "$REFERENCE_ROOT" ||
|
||||
referenceImport.relationships?.[0]?.resolution !== "internal" ||
|
||||
JSON.stringify(referenceImport).includes("PACKAGE_SECRET_SENTINEL")
|
||||
)
|
||||
throw new Error("packaged historical reference import CLI failed");
|
||||
const { createEvidence } = await import(
|
||||
new URL("../dist/domain/evidence.js", import.meta.url)
|
||||
);
|
||||
|
|
|
|||
32
src/cli.ts
32
src/cli.ts
|
|
@ -14,6 +14,7 @@ import {
|
|||
exportEvidenceBundleCommand,
|
||||
importEvidenceBundleCommand,
|
||||
} from "./application/EvidenceBundleCommands.js";
|
||||
import { importReferenceSource } from "./application/ReferenceSourceImport.js";
|
||||
|
||||
/**
|
||||
* Build the one-shot Incur CLI without starting Hopper at import time.
|
||||
|
|
@ -96,9 +97,40 @@ export const createCli = (): ReturnType<typeof Cli.create> => {
|
|||
registerNativeCommands(cli, logger);
|
||||
registerArtifactCommands(cli, logger);
|
||||
registerEvidenceCommands(cli, logger);
|
||||
registerReferenceSourceCommand(cli, logger);
|
||||
return cli;
|
||||
};
|
||||
|
||||
const registerReferenceSourceCommand = (
|
||||
cli: ReturnType<typeof Cli.create>,
|
||||
logger: Logger,
|
||||
): void => {
|
||||
cli.command("import-reference-source", {
|
||||
description: "Import a bounded source tree as historical reference only",
|
||||
args: z.object({
|
||||
root: z
|
||||
.string()
|
||||
.describe("Source root allowed by REA_REFERENCE_ROOTS_JSON"),
|
||||
}),
|
||||
run: ({ args }) =>
|
||||
logCliCommand(logger, "import-reference-source", async () => {
|
||||
const config = parseConfig(process.env);
|
||||
if (!config.ok)
|
||||
return { error: config.error._tag, message: config.error.message };
|
||||
const imported = await importReferenceSource({
|
||||
root: args.root,
|
||||
caller: "rea-cli",
|
||||
policy: config.value.referenceSourcePolicy,
|
||||
importer: PRODUCT_IDENTITY.packageName,
|
||||
importerVersion: null,
|
||||
});
|
||||
return imported.ok
|
||||
? imported.value
|
||||
: { error: imported.error.code, message: imported.error.message };
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
const registerArtifactCommands = (
|
||||
cli: ReturnType<typeof Cli.create>,
|
||||
logger: Logger,
|
||||
|
|
|
|||
Loading…
Reference in New Issue