agentplane 0.3.13 → 0.3.14
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/assets/RUNNER.md +1 -1
- package/assets/agents/ORCHESTRATOR.json +1 -1
- package/assets/agents/SKILL_EXTRACTOR.json +31 -0
- package/assets/framework.manifest.json +7 -0
- package/assets/policy/incidents.md +5 -3
- package/assets/policy/workflow.branch_pr.md +10 -5
- package/dist/.build-manifest.json +278 -178
- package/dist/cli/output.d.ts +29 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +33 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/core.js +29 -87
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/lifecycle.js +4 -12
- package/dist/cli/run-cli/command-catalog/project.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/project.js +16 -38
- package/dist/cli/run-cli/command-catalog/shared.d.ts +9 -6
- package/dist/cli/run-cli/command-catalog/shared.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/shared.js +23 -6
- package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog/task.js +6 -18
- package/dist/cli/run-cli/command-catalog.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/recipes.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/recipes.js +1 -0
- package/dist/cli/run-cli.js +1 -1
- package/dist/cli/run-cli.test-helpers.d.ts +1 -74
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +1 -769
- package/dist/commands/branch/cleanup-merged.d.ts.map +1 -1
- package/dist/commands/branch/cleanup-merged.js +5 -9
- package/dist/commands/branch/work-start.command.d.ts.map +1 -1
- package/dist/commands/branch/work-start.command.js +1 -0
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +2 -0
- package/dist/commands/doctor/branch-pr.d.ts +1 -1
- package/dist/commands/doctor/branch-pr.d.ts.map +1 -1
- package/dist/commands/doctor/branch-pr.js +5 -2
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +4 -1
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +2 -1
- package/dist/commands/guard/impl/env.d.ts +6 -0
- package/dist/commands/guard/impl/env.d.ts.map +1 -1
- package/dist/commands/guard/impl/env.js +41 -0
- package/dist/commands/pr/internal/auto-commit.d.ts.map +1 -1
- package/dist/commands/pr/internal/auto-commit.js +2 -1
- package/dist/commands/pr/internal/sync-branch.d.ts +36 -0
- package/dist/commands/pr/internal/sync-branch.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-branch.js +113 -0
- package/dist/commands/pr/internal/sync-github.d.ts +28 -0
- package/dist/commands/pr/internal/sync-github.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-github.js +178 -0
- package/dist/commands/pr/internal/sync-model.d.ts +36 -0
- package/dist/commands/pr/internal/sync-model.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-model.js +1 -0
- package/dist/commands/pr/internal/sync-open-step.d.ts +10 -0
- package/dist/commands/pr/internal/sync-open-step.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-open-step.js +128 -0
- package/dist/commands/pr/internal/sync-support.d.ts +7 -0
- package/dist/commands/pr/internal/sync-support.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-support.js +29 -0
- package/dist/commands/pr/internal/sync-update-step.d.ts +6 -0
- package/dist/commands/pr/internal/sync-update-step.d.ts.map +1 -0
- package/dist/commands/pr/internal/sync-update-step.js +68 -0
- package/dist/commands/pr/internal/sync.d.ts +2 -6
- package/dist/commands/pr/internal/sync.d.ts.map +1 -1
- package/dist/commands/pr/internal/sync.js +83 -529
- package/dist/commands/pr/open.d.ts.map +1 -1
- package/dist/commands/pr/open.js +25 -8
- package/dist/commands/pr/pr.command.d.ts.map +1 -1
- package/dist/commands/pr/pr.command.js +7 -2
- package/dist/commands/recipes/impl/apply.d.ts +1 -1
- package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
- package/dist/commands/recipes/impl/apply.js +1 -2
- package/dist/commands/recipes/impl/commands/active.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/active.js +6 -5
- package/dist/commands/recipes/impl/commands/add.d.ts +1 -0
- package/dist/commands/recipes/impl/commands/add.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/add.js +32 -27
- package/dist/commands/recipes/impl/commands/detach.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/detach.js +35 -21
- package/dist/commands/recipes/impl/commands/disable.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/disable.js +5 -3
- package/dist/commands/recipes/impl/commands/enable.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/enable.js +5 -3
- package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/explain.js +57 -47
- package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/info.js +25 -21
- package/dist/commands/recipes/impl/commands/install.d.ts +1 -1
- package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/install.js +3 -13
- package/dist/commands/recipes/impl/commands/list-remote.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list-remote.js +2 -3
- package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list.js +7 -6
- package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/remove.js +12 -7
- package/dist/commands/recipes/impl/commands/update.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/update.js +38 -24
- package/dist/commands/recipes/impl/index.d.ts +1 -1
- package/dist/commands/recipes/impl/index.d.ts.map +1 -1
- package/dist/commands/recipes/impl/installed-recipes.d.ts +1 -1
- package/dist/commands/recipes/impl/installed-recipes.d.ts.map +1 -1
- package/dist/commands/recipes/impl/installed-recipes.js +1 -2
- package/dist/commands/recipes/impl/mutation-transaction.d.ts +7 -0
- package/dist/commands/recipes/impl/mutation-transaction.d.ts.map +1 -0
- package/dist/commands/recipes/impl/mutation-transaction.js +47 -0
- package/dist/commands/recipes/impl/overlay-project.d.ts +19 -3
- package/dist/commands/recipes/impl/overlay-project.d.ts.map +1 -1
- package/dist/commands/recipes/impl/overlay-project.js +76 -38
- package/dist/commands/recipes/impl/paths.d.ts +0 -3
- package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
- package/dist/commands/recipes/impl/paths.js +0 -3
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts +4 -1
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -1
- package/dist/commands/recipes/impl/project-installed-recipes.js +6 -4
- package/dist/commands/recipes/impl/project-recipe-state.d.ts +1 -1
- package/dist/commands/recipes/impl/project-recipe-state.d.ts.map +1 -1
- package/dist/commands/recipes/impl/project-registry.d.ts +5 -1
- package/dist/commands/recipes/impl/project-registry.d.ts.map +1 -1
- package/dist/commands/recipes/impl/project-registry.js +34 -14
- package/dist/commands/recipes/impl/resolver.d.ts +1 -1
- package/dist/commands/recipes/impl/resolver.d.ts.map +1 -1
- package/dist/commands/recipes/impl/resolver.js +1 -1
- package/dist/commands/recipes/impl/types.d.ts +1 -1
- package/dist/commands/recipes/impl/types.d.ts.map +1 -1
- package/dist/commands/recipes/impl/version.d.ts +5 -0
- package/dist/commands/recipes/impl/version.d.ts.map +1 -0
- package/dist/commands/recipes/impl/version.js +9 -0
- package/dist/commands/recipes.d.ts +5 -4
- package/dist/commands/recipes.d.ts.map +1 -1
- package/dist/commands/recipes.js +3 -3
- package/dist/commands/release/apply.command.d.ts +1 -1
- package/dist/commands/release/apply.command.d.ts.map +1 -1
- package/dist/commands/release/apply.command.js +15 -379
- package/dist/commands/release/apply.mutation.d.ts +1 -0
- package/dist/commands/release/apply.mutation.d.ts.map +1 -1
- package/dist/commands/release/apply.mutation.js +24 -1
- package/dist/commands/release/apply.pipeline.d.ts +22 -0
- package/dist/commands/release/apply.pipeline.d.ts.map +1 -0
- package/dist/commands/release/apply.pipeline.js +371 -0
- package/dist/commands/release/apply.preflight.d.ts +2 -0
- package/dist/commands/release/apply.preflight.d.ts.map +1 -1
- package/dist/commands/release/apply.preflight.js +13 -4
- package/dist/commands/release/apply.types.d.ts +27 -0
- package/dist/commands/release/apply.types.d.ts.map +1 -1
- package/dist/commands/release.test-helpers.d.ts +4 -0
- package/dist/commands/release.test-helpers.d.ts.map +1 -1
- package/dist/commands/release.test-helpers.js +7 -0
- package/dist/commands/shared/reconcile-check.d.ts.map +1 -1
- package/dist/commands/shared/reconcile-check.js +2 -2
- package/dist/commands/shared/task-backend.d.ts +6 -1
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +34 -2
- package/dist/commands/shared/task-mutation.d.ts.map +1 -1
- package/dist/commands/shared/task-mutation.js +4 -4
- package/dist/commands/shared/task-store/intents.d.ts +34 -0
- package/dist/commands/shared/task-store/intents.d.ts.map +1 -0
- package/dist/commands/shared/task-store/intents.js +265 -0
- package/dist/commands/shared/task-store/readme.d.ts +28 -0
- package/dist/commands/shared/task-store/readme.d.ts.map +1 -0
- package/dist/commands/shared/task-store/readme.js +125 -0
- package/dist/commands/shared/task-store/store.d.ts +26 -0
- package/dist/commands/shared/task-store/store.d.ts.map +1 -0
- package/dist/commands/shared/task-store/store.js +105 -0
- package/dist/commands/shared/task-store/types.d.ts +94 -0
- package/dist/commands/shared/task-store/types.d.ts.map +1 -0
- package/dist/commands/shared/task-store/types.js +1 -0
- package/dist/commands/shared/task-store.d.ts +3 -109
- package/dist/commands/shared/task-store.d.ts.map +1 -1
- package/dist/commands/shared/task-store.js +2 -493
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +7 -2
- package/dist/commands/task/comment.d.ts.map +1 -1
- package/dist/commands/task/comment.js +7 -2
- package/dist/commands/task/finish-shared.d.ts.map +1 -1
- package/dist/commands/task/finish-shared.js +3 -3
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +102 -15
- package/dist/commands/task/hosted-merge-sync.d.ts.map +1 -1
- package/dist/commands/task/hosted-merge-sync.js +9 -4
- package/dist/commands/task/list.run.d.ts.map +1 -1
- package/dist/commands/task/list.run.js +14 -4
- package/dist/commands/task/new.command.d.ts.map +1 -1
- package/dist/commands/task/new.command.js +16 -2
- package/dist/commands/task/new.js +2 -2
- package/dist/commands/task/show.d.ts.map +1 -1
- package/dist/commands/task/show.js +3 -3
- package/dist/commands/task/update.d.ts.map +1 -1
- package/dist/commands/task/update.js +11 -3
- package/dist/runner/adapters/codex.d.ts.map +1 -1
- package/dist/runner/adapters/codex.js +3 -33
- package/dist/runner/adapters/custom.d.ts.map +1 -1
- package/dist/runner/adapters/custom.js +3 -30
- package/dist/runner/adapters/runtime-shared.d.ts +14 -0
- package/dist/runner/adapters/runtime-shared.d.ts.map +1 -0
- package/dist/runner/adapters/runtime-shared.js +36 -0
- package/dist/runner/context/base-prompt-sources.d.ts +30 -0
- package/dist/runner/context/base-prompt-sources.d.ts.map +1 -0
- package/dist/runner/context/base-prompt-sources.js +144 -0
- package/dist/runner/context/base-prompts.d.ts +3 -22
- package/dist/runner/context/base-prompts.d.ts.map +1 -1
- package/dist/runner/context/base-prompts.js +6 -450
- package/dist/runner/context/overlay-prompt-blocks.d.ts +7 -0
- package/dist/runner/context/overlay-prompt-blocks.d.ts.map +1 -0
- package/dist/runner/context/overlay-prompt-blocks.js +72 -0
- package/dist/runner/context/prompt-block-shared.d.ts +54 -0
- package/dist/runner/context/prompt-block-shared.d.ts.map +1 -0
- package/dist/runner/context/prompt-block-shared.js +106 -0
- package/dist/runner/context/recipe-context.d.ts +2 -1
- package/dist/runner/context/recipe-context.d.ts.map +1 -1
- package/dist/runner/context/recipe-context.js +2 -1
- package/dist/runner/context/recipe-prompt-blocks.d.ts +6 -0
- package/dist/runner/context/recipe-prompt-blocks.d.ts.map +1 -0
- package/dist/runner/context/recipe-prompt-blocks.js +143 -0
- package/dist/runner/usecases/scenario-materialize-task.js +2 -2
- package/dist/runner/usecases/task-run-inspect.js +2 -2
- package/dist/runner/usecases/task-run-lifecycle-shared.js +2 -2
- package/dist/runner/usecases/task-run.d.ts.map +1 -1
- package/dist/runner/usecases/task-run.js +4 -2
- package/dist/runtime/capabilities/recipe.d.ts +1 -1
- package/dist/runtime/capabilities/recipe.d.ts.map +1 -1
- package/dist/runtime/execution-context.d.ts +63 -0
- package/dist/runtime/execution-context.d.ts.map +1 -0
- package/dist/{usecases/context/resolve-context.js → runtime/execution-context.js} +23 -26
- package/dist/runtime/incidents/advice-strategy.d.ts +15 -0
- package/dist/runtime/incidents/advice-strategy.d.ts.map +1 -0
- package/dist/runtime/incidents/advice-strategy.js +54 -0
- package/dist/runtime/incidents/plan-strategy.d.ts +9 -0
- package/dist/runtime/incidents/plan-strategy.d.ts.map +1 -0
- package/dist/runtime/incidents/plan-strategy.js +205 -0
- package/dist/runtime/incidents/registry-strategy.d.ts +6 -0
- package/dist/runtime/incidents/registry-strategy.d.ts.map +1 -0
- package/dist/runtime/incidents/registry-strategy.js +280 -0
- package/dist/runtime/incidents/resolve.d.ts +3 -25
- package/dist/runtime/incidents/resolve.d.ts.map +1 -1
- package/dist/runtime/incidents/resolve.js +3 -683
- package/dist/runtime/incidents/shared.d.ts +34 -0
- package/dist/runtime/incidents/shared.d.ts.map +1 -0
- package/dist/runtime/incidents/shared.js +171 -0
- package/dist/testing/cli-harness/recipe-archives.d.ts +28 -0
- package/dist/testing/cli-harness/recipe-archives.d.ts.map +1 -0
- package/dist/testing/cli-harness/recipe-archives.js +374 -0
- package/dist/testing/cli-harness/stdio.d.ts +26 -0
- package/dist/testing/cli-harness/stdio.d.ts.map +1 -0
- package/dist/testing/cli-harness/stdio.js +84 -0
- package/dist/testing/cli-harness.d.ts +25 -0
- package/dist/testing/cli-harness.d.ts.map +1 -0
- package/dist/testing/cli-harness.js +313 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +1 -0
- package/package.json +7 -4
- package/dist/commands/recipes/impl/manifest.d.ts +0 -4
- package/dist/commands/recipes/impl/manifest.d.ts.map +0 -1
- package/dist/commands/recipes/impl/manifest.js +0 -7
- package/dist/commands/recipes/impl/normalize.d.ts +0 -8
- package/dist/commands/recipes/impl/normalize.d.ts.map +0 -1
- package/dist/commands/recipes/impl/normalize.js +0 -54
- package/dist/commands/recipes/impl/scenario.d.ts +0 -16
- package/dist/commands/recipes/impl/scenario.d.ts.map +0 -1
- package/dist/commands/recipes/impl/scenario.js +0 -262
- package/dist/recipes/bundled-recipes.d.ts +0 -17
- package/dist/recipes/bundled-recipes.d.ts.map +0 -1
- package/dist/recipes/bundled-recipes.js +0 -15
- package/dist/usecases/context/resolve-context.d.ts +0 -68
- package/dist/usecases/context/resolve-context.d.ts.map +0 -1
- package/dist/usecases/task/task-list-usecase.d.ts +0 -9
- package/dist/usecases/task/task-list-usecase.d.ts.map +0 -1
- package/dist/usecases/task/task-list-usecase.js +0 -17
- package/dist/usecases/task/task-new-usecase.d.ts +0 -9
- package/dist/usecases/task/task-new-usecase.d.ts.map +0 -1
- package/dist/usecases/task/task-new-usecase.js +0 -17
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { IncidentAdviceMatch, IncidentRegistry, IncidentRegistryEntry, IncidentRegistryEntryState } from "./types.js";
|
|
2
|
+
export declare const STRUCTURED_INCIDENTS_HEADER: string;
|
|
3
|
+
export declare const COMPACT_INCIDENTS_HEADER: string;
|
|
4
|
+
export declare function normalizeLines(text: string): string[];
|
|
5
|
+
export declare function normalizeKey(key: string): string;
|
|
6
|
+
export declare function normalizeSearchText(text: string): string;
|
|
7
|
+
export declare function tokenize(text: string): string[];
|
|
8
|
+
export declare function dedupeCaseInsensitive(values: readonly string[]): string[];
|
|
9
|
+
export declare function parseCsvList(value: string | null | undefined): string[];
|
|
10
|
+
export declare function incidentField(key: string, value: string): [string, string];
|
|
11
|
+
export declare function parseBoolean(value: string | null | undefined): boolean;
|
|
12
|
+
export declare function parseFixability(value: string | null | undefined): "external" | "repo-fixable" | null;
|
|
13
|
+
export declare function parseEntryState(value: string | null | undefined): IncidentRegistryEntryState;
|
|
14
|
+
export declare function appendFieldValue(record: Record<string, string>, key: string, value: string, joiner?: string): void;
|
|
15
|
+
export declare function deriveSourceTask(explicitSourceTask: string | null | undefined, evidence: string | null | undefined): string | null;
|
|
16
|
+
export declare function buildIncidentSignature(entry: Pick<IncidentRegistryEntry, "scope" | "failure" | "rule">): string;
|
|
17
|
+
export declare function buildIncidentFingerprint(entry: Pick<IncidentRegistryEntry, "sourceTask" | "scope" | "failure" | "rule">): string;
|
|
18
|
+
export declare function buildMatchTerms(opts: {
|
|
19
|
+
scope: string;
|
|
20
|
+
tags: readonly string[];
|
|
21
|
+
explicitMatch: readonly string[];
|
|
22
|
+
extraText?: readonly string[];
|
|
23
|
+
}): string[];
|
|
24
|
+
export declare function occursWithinDays(date: string, now: Date, days: number): boolean;
|
|
25
|
+
export declare function entryStateRank(state: IncidentRegistryEntryState): number;
|
|
26
|
+
export declare function compareIncidentAdviceMatch(left: IncidentAdviceMatch, right: IncidentAdviceMatch): number;
|
|
27
|
+
export declare function summarizeTaskScope(scope: string | null | undefined, title: string): string;
|
|
28
|
+
export declare function buildDerivedIncidentRule(scope: string): string;
|
|
29
|
+
export declare function resolveIncidentState(opts: {
|
|
30
|
+
registry: IncidentRegistry;
|
|
31
|
+
entry: Pick<IncidentRegistryEntry, "scope" | "failure" | "rule">;
|
|
32
|
+
now: Date;
|
|
33
|
+
}): IncidentRegistryEntryState;
|
|
34
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/runtime/incidents/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
export const STRUCTURED_INCIDENTS_HEADER = [
|
|
2
|
+
"# Policy Incidents Log",
|
|
3
|
+
"",
|
|
4
|
+
"This is the single file for incident-derived and situational policy rules.",
|
|
5
|
+
].join("\n");
|
|
6
|
+
export const COMPACT_INCIDENTS_HEADER = [
|
|
7
|
+
"# Policy Incidents Log",
|
|
8
|
+
"- Append-only. Required fields: `id`, `date`, `scope`, `failure`, `rule`, `evidence`, `enforcement`, `state`; optional: `tags`, `match`, `advice`, `source_task`, `fixability`.",
|
|
9
|
+
].join("\n");
|
|
10
|
+
export function normalizeLines(text) {
|
|
11
|
+
return text.replaceAll("\r\n", "\n").split("\n");
|
|
12
|
+
}
|
|
13
|
+
export function normalizeKey(key) {
|
|
14
|
+
return key
|
|
15
|
+
.trim()
|
|
16
|
+
.toLowerCase()
|
|
17
|
+
.replaceAll(/[\s_-]+/g, "");
|
|
18
|
+
}
|
|
19
|
+
export function normalizeSearchText(text) {
|
|
20
|
+
return text
|
|
21
|
+
.toLowerCase()
|
|
22
|
+
.replaceAll(/[^a-z0-9]+/gi, " ")
|
|
23
|
+
.trim();
|
|
24
|
+
}
|
|
25
|
+
export function tokenize(text) {
|
|
26
|
+
const normalized = normalizeSearchText(text);
|
|
27
|
+
if (!normalized)
|
|
28
|
+
return [];
|
|
29
|
+
return normalized
|
|
30
|
+
.split(/\s+/)
|
|
31
|
+
.map((token) => token.trim())
|
|
32
|
+
.filter((token) => token.length >= 3);
|
|
33
|
+
}
|
|
34
|
+
export function dedupeCaseInsensitive(values) {
|
|
35
|
+
const seen = new Set();
|
|
36
|
+
const out = [];
|
|
37
|
+
for (const value of values) {
|
|
38
|
+
const trimmed = String(value ?? "").trim();
|
|
39
|
+
if (!trimmed)
|
|
40
|
+
continue;
|
|
41
|
+
const key = trimmed.toLowerCase();
|
|
42
|
+
if (seen.has(key))
|
|
43
|
+
continue;
|
|
44
|
+
seen.add(key);
|
|
45
|
+
out.push(trimmed);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
export function parseCsvList(value) {
|
|
50
|
+
if (!value)
|
|
51
|
+
return [];
|
|
52
|
+
return dedupeCaseInsensitive(value
|
|
53
|
+
.split(",")
|
|
54
|
+
.map((item) => item.trim())
|
|
55
|
+
.filter(Boolean));
|
|
56
|
+
}
|
|
57
|
+
export function incidentField(key, value) {
|
|
58
|
+
return [key, value];
|
|
59
|
+
}
|
|
60
|
+
export function parseBoolean(value) {
|
|
61
|
+
const normalized = String(value ?? "")
|
|
62
|
+
.trim()
|
|
63
|
+
.toLowerCase();
|
|
64
|
+
return normalized === "true" || normalized === "yes" || normalized === "y" || normalized === "1";
|
|
65
|
+
}
|
|
66
|
+
export function parseFixability(value) {
|
|
67
|
+
const normalized = String(value ?? "")
|
|
68
|
+
.trim()
|
|
69
|
+
.toLowerCase()
|
|
70
|
+
.replaceAll(/[\s_-]+/g, "");
|
|
71
|
+
if (normalized === "external")
|
|
72
|
+
return "external";
|
|
73
|
+
if (normalized === "repofixable" || normalized === "internal")
|
|
74
|
+
return "repo-fixable";
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
export function parseEntryState(value) {
|
|
78
|
+
return value === "open" || value === "promoted" ? value : "stabilized";
|
|
79
|
+
}
|
|
80
|
+
export function appendFieldValue(record, key, value, joiner = " ") {
|
|
81
|
+
if (!record[key]) {
|
|
82
|
+
record[key] = value.trim();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
record[key] = `${record[key]}${joiner}${value.trim()}`.trim();
|
|
86
|
+
}
|
|
87
|
+
export function deriveSourceTask(explicitSourceTask, evidence) {
|
|
88
|
+
const direct = String(explicitSourceTask ?? "").trim();
|
|
89
|
+
if (direct)
|
|
90
|
+
return direct;
|
|
91
|
+
const match = /\btasks?\s+([A-Za-z0-9-]+)/iu.exec(String(evidence ?? ""));
|
|
92
|
+
return match?.[1]?.trim() ?? null;
|
|
93
|
+
}
|
|
94
|
+
export function buildIncidentSignature(entry) {
|
|
95
|
+
return [
|
|
96
|
+
normalizeSearchText(entry.scope),
|
|
97
|
+
normalizeSearchText(entry.failure),
|
|
98
|
+
normalizeSearchText(entry.rule),
|
|
99
|
+
].join("|");
|
|
100
|
+
}
|
|
101
|
+
export function buildIncidentFingerprint(entry) {
|
|
102
|
+
return [entry.sourceTask ?? "", buildIncidentSignature(entry)].join("|");
|
|
103
|
+
}
|
|
104
|
+
export function buildMatchTerms(opts) {
|
|
105
|
+
const scopeTokens = tokenize(opts.scope);
|
|
106
|
+
const extraTokens = (opts.extraText ?? []).flatMap((value) => tokenize(value));
|
|
107
|
+
return dedupeCaseInsensitive([
|
|
108
|
+
...opts.explicitMatch,
|
|
109
|
+
...opts.tags,
|
|
110
|
+
...scopeTokens,
|
|
111
|
+
...extraTokens,
|
|
112
|
+
]).slice(0, 16);
|
|
113
|
+
}
|
|
114
|
+
function parseDateOnly(value) {
|
|
115
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
|
|
116
|
+
return null;
|
|
117
|
+
const parsed = Date.parse(`${value}T00:00:00.000Z`);
|
|
118
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
119
|
+
}
|
|
120
|
+
export function occursWithinDays(date, now, days) {
|
|
121
|
+
const timestamp = parseDateOnly(date);
|
|
122
|
+
if (timestamp === null)
|
|
123
|
+
return false;
|
|
124
|
+
const delta = now.getTime() - timestamp;
|
|
125
|
+
if (delta < 0)
|
|
126
|
+
return false;
|
|
127
|
+
return delta <= days * 24 * 60 * 60 * 1000;
|
|
128
|
+
}
|
|
129
|
+
export function entryStateRank(state) {
|
|
130
|
+
if (state === "promoted")
|
|
131
|
+
return 2;
|
|
132
|
+
if (state === "stabilized")
|
|
133
|
+
return 1;
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
export function compareIncidentAdviceMatch(left, right) {
|
|
137
|
+
if (right.score !== left.score)
|
|
138
|
+
return right.score - left.score;
|
|
139
|
+
const rightState = entryStateRank(right.entry.state);
|
|
140
|
+
const leftState = entryStateRank(left.entry.state);
|
|
141
|
+
if (rightState !== leftState)
|
|
142
|
+
return rightState - leftState;
|
|
143
|
+
return right.entry.date.localeCompare(left.entry.date);
|
|
144
|
+
}
|
|
145
|
+
export function summarizeTaskScope(scope, title) {
|
|
146
|
+
const lines = normalizeLines(scope ?? "");
|
|
147
|
+
for (const line of lines) {
|
|
148
|
+
const trimmed = line.trim();
|
|
149
|
+
if (!trimmed)
|
|
150
|
+
continue;
|
|
151
|
+
let candidate = trimmed.replace(/^-+\s*/, "");
|
|
152
|
+
candidate = candidate.replace(/^in scope:\s*/i, "").trim();
|
|
153
|
+
if (!candidate || /^out of scope:/i.test(candidate))
|
|
154
|
+
continue;
|
|
155
|
+
return candidate;
|
|
156
|
+
}
|
|
157
|
+
return title.trim();
|
|
158
|
+
}
|
|
159
|
+
export function buildDerivedIncidentRule(scope) {
|
|
160
|
+
return `Analogous ${scope} work MUST review and apply the recorded external incident advice before retrying.`;
|
|
161
|
+
}
|
|
162
|
+
export function resolveIncidentState(opts) {
|
|
163
|
+
const signature = buildIncidentSignature(opts.entry);
|
|
164
|
+
const similarEntries = opts.registry.entries.filter((candidate) => buildIncidentSignature(candidate) === signature);
|
|
165
|
+
if (similarEntries.some((candidate) => candidate.state === "promoted" ||
|
|
166
|
+
candidate.state === "stabilized" ||
|
|
167
|
+
occursWithinDays(candidate.date, opts.now, 30))) {
|
|
168
|
+
return "stabilized";
|
|
169
|
+
}
|
|
170
|
+
return "open";
|
|
171
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare function createRecipeArchive(opts?: {
|
|
2
|
+
id?: string;
|
|
3
|
+
version?: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
summary?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
tags?: string[];
|
|
8
|
+
format?: "tar" | "zip";
|
|
9
|
+
wrapDir?: boolean;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
archivePath: string;
|
|
12
|
+
manifest: Record<string, unknown>;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function createRecipeArchiveWithManifest(opts: {
|
|
15
|
+
manifest: Record<string, unknown>;
|
|
16
|
+
files?: Record<string, string>;
|
|
17
|
+
format?: "tar" | "zip";
|
|
18
|
+
wrapDir?: boolean;
|
|
19
|
+
}): Promise<string>;
|
|
20
|
+
export declare function createUnsafeRecipeArchive(opts: {
|
|
21
|
+
format: "tar" | "zip";
|
|
22
|
+
entryPath?: string;
|
|
23
|
+
}): Promise<string>;
|
|
24
|
+
export declare function createUpgradeBundle(files: Record<string, string>): Promise<{
|
|
25
|
+
bundlePath: string;
|
|
26
|
+
checksumPath: string;
|
|
27
|
+
}>;
|
|
28
|
+
//# sourceMappingURL=recipe-archives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe-archives.d.ts","sourceRoot":"","sources":["../../../src/testing/cli-harness/recipe-archives.ts"],"names":[],"mappings":"AAgBA,wBAAsB,mBAAmB,CAAC,IAAI,CAAC,EAAE;IAC/C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAsKtE;AAED,wBAAsB,+BAA+B,CAAC,IAAI,EAAE;IAC1D,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBlB;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE;IACpD,MAAM,EAAE,KAAK,GAAG,KAAK,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+GlB;AAyDD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAkDD"}
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
import { gzipSync } from "node:zlib";
|
|
9
|
+
const execFileAsync = promisify(execFile);
|
|
10
|
+
const recipeArchiveCache = new Map();
|
|
11
|
+
export async function createRecipeArchive(opts) {
|
|
12
|
+
const normalizedTags = opts?.tags ? [...opts.tags].toSorted() : undefined;
|
|
13
|
+
const cacheKey = JSON.stringify({
|
|
14
|
+
id: opts?.id ?? "viewer",
|
|
15
|
+
version: opts?.version ?? "1.2.3",
|
|
16
|
+
name: opts?.name ?? "Viewer",
|
|
17
|
+
summary: opts?.summary ?? "Preview task artifacts",
|
|
18
|
+
description: opts?.description ?? "Provides a local viewer for task artifacts.",
|
|
19
|
+
tags: normalizedTags,
|
|
20
|
+
format: opts?.format ?? "tar",
|
|
21
|
+
wrapDir: opts?.wrapDir ?? false,
|
|
22
|
+
});
|
|
23
|
+
const cached = recipeArchiveCache.get(cacheKey);
|
|
24
|
+
if (cached)
|
|
25
|
+
return cached;
|
|
26
|
+
const baseDir = await mkdtemp(path.join(os.tmpdir(), "agentplane-recipe-"));
|
|
27
|
+
const recipeDir = path.join(baseDir, opts?.wrapDir ? "bundle" : "recipe");
|
|
28
|
+
await mkdir(recipeDir, { recursive: true });
|
|
29
|
+
const manifest = {
|
|
30
|
+
schema_version: "1",
|
|
31
|
+
id: opts?.id ?? "viewer",
|
|
32
|
+
version: opts?.version ?? "1.2.3",
|
|
33
|
+
name: opts?.name ?? "Viewer",
|
|
34
|
+
summary: opts?.summary ?? "Preview task artifacts",
|
|
35
|
+
description: opts?.description ?? "Provides a local viewer for task artifacts.",
|
|
36
|
+
compatibility: {
|
|
37
|
+
min_agentplane_version: "0.3.5",
|
|
38
|
+
manifest_api_version: "1",
|
|
39
|
+
scenario_api_version: "1",
|
|
40
|
+
runtime_api_version: "1",
|
|
41
|
+
platforms: ["darwin", "linux"],
|
|
42
|
+
repo_types: ["generic"],
|
|
43
|
+
},
|
|
44
|
+
skills: [
|
|
45
|
+
{
|
|
46
|
+
id: "RECIPE_SKILL",
|
|
47
|
+
summary: "Recipe analysis skill",
|
|
48
|
+
file: "skills/analysis.md",
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
agents: [
|
|
52
|
+
{
|
|
53
|
+
id: "RECIPE_AGENT",
|
|
54
|
+
display_name: "Recipe Agent",
|
|
55
|
+
role: "executor",
|
|
56
|
+
summary: "Recipe agent",
|
|
57
|
+
skills: ["RECIPE_SKILL"],
|
|
58
|
+
tools: ["RECIPE_TOOL"],
|
|
59
|
+
file: "agents/recipe.md",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
tools: [
|
|
63
|
+
{ id: "RECIPE_TOOL", summary: "Recipe tool", runtime: "node", entrypoint: "tools/run.js" },
|
|
64
|
+
],
|
|
65
|
+
scenarios: [
|
|
66
|
+
{
|
|
67
|
+
id: "RECIPE_SCENARIO",
|
|
68
|
+
name: "Recipe Scenario",
|
|
69
|
+
summary: "Recipe scenario",
|
|
70
|
+
use_when: ["Task artifacts need local preview"],
|
|
71
|
+
required_inputs: ["task_id"],
|
|
72
|
+
outputs: ["report"],
|
|
73
|
+
permissions: ["filesystem-write"],
|
|
74
|
+
artifacts: ["artifact.txt"],
|
|
75
|
+
agents_involved: ["RECIPE_AGENT"],
|
|
76
|
+
skills_used: ["RECIPE_SKILL"],
|
|
77
|
+
tools_used: ["RECIPE_TOOL"],
|
|
78
|
+
run_profile: {
|
|
79
|
+
mode: "analysis",
|
|
80
|
+
sandbox: "workspace-write",
|
|
81
|
+
writes_artifacts_to: ["logs/", "reports/"],
|
|
82
|
+
},
|
|
83
|
+
file: "scenarios/recipe-scenario.json",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
if (normalizedTags) {
|
|
88
|
+
manifest.tags = normalizedTags;
|
|
89
|
+
}
|
|
90
|
+
await writeFile(path.join(recipeDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
91
|
+
const agentsDir = path.join(recipeDir, "agents");
|
|
92
|
+
await mkdir(agentsDir, { recursive: true });
|
|
93
|
+
await writeFile(path.join(agentsDir, "recipe.md"), [
|
|
94
|
+
"# Recipe Agent",
|
|
95
|
+
"",
|
|
96
|
+
"Role: executor",
|
|
97
|
+
"",
|
|
98
|
+
"Instructions:",
|
|
99
|
+
"- Use recipe local policy.",
|
|
100
|
+
"- Materialize the declared scenario artifacts.",
|
|
101
|
+
].join("\n"), "utf8");
|
|
102
|
+
const skillsDir = path.join(recipeDir, "skills");
|
|
103
|
+
await mkdir(skillsDir, { recursive: true });
|
|
104
|
+
await writeFile(path.join(skillsDir, "analysis.md"), [
|
|
105
|
+
"# Recipe Skill",
|
|
106
|
+
"",
|
|
107
|
+
"- Inspect the generated bundle before acting.",
|
|
108
|
+
"- Keep recipe-owned artifacts inside the declared output paths.",
|
|
109
|
+
].join("\n"), "utf8");
|
|
110
|
+
const toolsDir = path.join(recipeDir, "tools");
|
|
111
|
+
await mkdir(toolsDir, { recursive: true });
|
|
112
|
+
await writeFile(path.join(toolsDir, "run.js"), [
|
|
113
|
+
'const fs = require("node:fs");',
|
|
114
|
+
'fs.writeFileSync(process.env.AGENTPLANE_RUN_DIR + "/artifact.txt", "ok");',
|
|
115
|
+
].join("\n"), "utf8");
|
|
116
|
+
const scenariosDir = path.join(recipeDir, "scenarios");
|
|
117
|
+
await mkdir(scenariosDir, { recursive: true });
|
|
118
|
+
await writeFile(path.join(scenariosDir, "recipe-scenario.json"), JSON.stringify({
|
|
119
|
+
schema_version: "1",
|
|
120
|
+
id: "RECIPE_SCENARIO",
|
|
121
|
+
summary: "Recipe scenario",
|
|
122
|
+
goal: "Preview installed tasks.",
|
|
123
|
+
task_template: {
|
|
124
|
+
title: "Recipe scenario task",
|
|
125
|
+
description: "Materialize a task from the recipe scenario.",
|
|
126
|
+
owner: "CODER",
|
|
127
|
+
priority: "med",
|
|
128
|
+
tags: ["code", "recipes"],
|
|
129
|
+
verify: ["bunx vitest run packages/agentplane/src/commands/recipes.scenario.test.ts"],
|
|
130
|
+
doc: {
|
|
131
|
+
summary: "Recipe-backed task execution.",
|
|
132
|
+
scope: "Run the scenario without task materialization heuristics.",
|
|
133
|
+
plan: "1. Materialize the task. 2. Execute the shared runner.",
|
|
134
|
+
verify_steps: "1. Run scenario execution tests.",
|
|
135
|
+
rollback_plan: "Revert the generated task and runner artifacts.",
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
inputs: [{ name: "task_id", type: "string" }],
|
|
139
|
+
outputs: [{ name: "report", type: "html" }],
|
|
140
|
+
steps: [{ tool: "RECIPE_TOOL" }],
|
|
141
|
+
}, null, 2), "utf8");
|
|
142
|
+
const format = opts?.format ?? "tar";
|
|
143
|
+
const archivePath = format === "zip" ? path.join(baseDir, "recipe.zip") : path.join(baseDir, "recipe.tar.gz");
|
|
144
|
+
if (format === "zip") {
|
|
145
|
+
await (opts?.wrapDir
|
|
146
|
+
? execFileAsync("zip", ["-qr", archivePath, path.basename(recipeDir)], { cwd: baseDir })
|
|
147
|
+
: execFileAsync("zip", ["-qr", archivePath, "."], { cwd: recipeDir }));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
await (opts?.wrapDir
|
|
151
|
+
? execFileAsync("tar", ["-czf", archivePath, "-C", baseDir, path.basename(recipeDir)])
|
|
152
|
+
: execFileAsync("tar", ["-czf", archivePath, "-C", recipeDir, "."]));
|
|
153
|
+
}
|
|
154
|
+
const payload = { archivePath, manifest };
|
|
155
|
+
recipeArchiveCache.set(cacheKey, payload);
|
|
156
|
+
return payload;
|
|
157
|
+
}
|
|
158
|
+
export async function createRecipeArchiveWithManifest(opts) {
|
|
159
|
+
const baseDir = await mkdtemp(path.join(os.tmpdir(), "agentplane-recipe-bad-"));
|
|
160
|
+
const recipeDir = path.join(baseDir, opts.wrapDir ? "bundle" : "recipe");
|
|
161
|
+
await mkdir(recipeDir, { recursive: true });
|
|
162
|
+
await writeFile(path.join(recipeDir, "manifest.json"), JSON.stringify(opts.manifest, null, 2));
|
|
163
|
+
if (opts.files) {
|
|
164
|
+
for (const [relPath, content] of Object.entries(opts.files)) {
|
|
165
|
+
const fullPath = path.join(recipeDir, relPath);
|
|
166
|
+
await mkdir(path.dirname(fullPath), { recursive: true });
|
|
167
|
+
await writeFile(fullPath, content, "utf8");
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const format = opts.format ?? "tar";
|
|
171
|
+
const archivePath = format === "zip" ? path.join(baseDir, "recipe.zip") : path.join(baseDir, "recipe.tar.gz");
|
|
172
|
+
if (format === "zip") {
|
|
173
|
+
await (opts.wrapDir
|
|
174
|
+
? execFileAsync("zip", ["-qr", archivePath, path.basename(recipeDir)], { cwd: baseDir })
|
|
175
|
+
: execFileAsync("zip", ["-qr", archivePath, "."], { cwd: recipeDir }));
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
await (opts.wrapDir
|
|
179
|
+
? execFileAsync("tar", ["-czf", archivePath, "-C", baseDir, path.basename(recipeDir)])
|
|
180
|
+
: execFileAsync("tar", ["-czf", archivePath, "-C", recipeDir, "."]));
|
|
181
|
+
}
|
|
182
|
+
return archivePath;
|
|
183
|
+
}
|
|
184
|
+
export async function createUnsafeRecipeArchive(opts) {
|
|
185
|
+
const baseDir = await mkdtemp(path.join(os.tmpdir(), "agentplane-recipe-unsafe-"));
|
|
186
|
+
const recipeDir = path.join(baseDir, "recipe");
|
|
187
|
+
await mkdir(recipeDir, { recursive: true });
|
|
188
|
+
const manifest = {
|
|
189
|
+
schema_version: "1",
|
|
190
|
+
id: "unsafe",
|
|
191
|
+
version: "0.0.1",
|
|
192
|
+
name: "Unsafe",
|
|
193
|
+
summary: "Unsafe recipe",
|
|
194
|
+
description: "Used for archive validation tests.",
|
|
195
|
+
skills: [
|
|
196
|
+
{
|
|
197
|
+
id: "RECIPE_SKILL",
|
|
198
|
+
summary: "Recipe skill",
|
|
199
|
+
file: "skills/recipe.md",
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
agents: [
|
|
203
|
+
{
|
|
204
|
+
id: "RECIPE_AGENT",
|
|
205
|
+
display_name: "Recipe Agent",
|
|
206
|
+
role: "executor",
|
|
207
|
+
summary: "Recipe agent",
|
|
208
|
+
skills: ["RECIPE_SKILL"],
|
|
209
|
+
tools: ["RECIPE_TOOL"],
|
|
210
|
+
file: "agents/recipe.md",
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
tools: [
|
|
214
|
+
{ id: "RECIPE_TOOL", summary: "Recipe tool", runtime: "bash", entrypoint: "tools/run.sh" },
|
|
215
|
+
],
|
|
216
|
+
scenarios: [
|
|
217
|
+
{
|
|
218
|
+
id: "RECIPE_SCENARIO",
|
|
219
|
+
name: "Recipe Scenario",
|
|
220
|
+
summary: "Recipe scenario",
|
|
221
|
+
use_when: ["Unsafe validation fixture"],
|
|
222
|
+
required_inputs: [],
|
|
223
|
+
outputs: [],
|
|
224
|
+
permissions: [],
|
|
225
|
+
artifacts: [],
|
|
226
|
+
agents_involved: ["RECIPE_AGENT"],
|
|
227
|
+
skills_used: ["RECIPE_SKILL"],
|
|
228
|
+
tools_used: ["RECIPE_TOOL"],
|
|
229
|
+
run_profile: { mode: "analysis" },
|
|
230
|
+
file: "scenarios/recipe-scenario.json",
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
};
|
|
234
|
+
await writeFile(path.join(recipeDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
235
|
+
const agentsDir = path.join(recipeDir, "agents");
|
|
236
|
+
await mkdir(agentsDir, { recursive: true });
|
|
237
|
+
await writeFile(path.join(agentsDir, "recipe.md"), "# Recipe Agent\n\nFollow the unsafe archive validation path.\n", "utf8");
|
|
238
|
+
const skillsDir = path.join(recipeDir, "skills");
|
|
239
|
+
await mkdir(skillsDir, { recursive: true });
|
|
240
|
+
await writeFile(path.join(skillsDir, "recipe.md"), "# Recipe Skill\n\nInspect archive contents before materialization.\n", "utf8");
|
|
241
|
+
const toolsDir = path.join(recipeDir, "tools");
|
|
242
|
+
await mkdir(toolsDir, { recursive: true });
|
|
243
|
+
await writeFile(path.join(toolsDir, "run.sh"), "#!/usr/bin/env bash\n", "utf8");
|
|
244
|
+
const scenariosDir = path.join(recipeDir, "scenarios");
|
|
245
|
+
await mkdir(scenariosDir, { recursive: true });
|
|
246
|
+
await writeFile(path.join(scenariosDir, "recipe-scenario.json"), JSON.stringify({
|
|
247
|
+
schema_version: "1",
|
|
248
|
+
id: "RECIPE_SCENARIO",
|
|
249
|
+
summary: "Recipe scenario",
|
|
250
|
+
goal: "Exercise unsafe archive validation.",
|
|
251
|
+
task_template: {
|
|
252
|
+
title: "Unsafe archive task",
|
|
253
|
+
description: "Validate unsafe archive handling.",
|
|
254
|
+
owner: "CODER",
|
|
255
|
+
},
|
|
256
|
+
inputs: [],
|
|
257
|
+
outputs: [],
|
|
258
|
+
steps: [{ tool: "RECIPE_TOOL" }],
|
|
259
|
+
}, null, 2), "utf8");
|
|
260
|
+
const entryPath = opts.entryPath ?? "../evil.txt";
|
|
261
|
+
await writeFile(path.join(baseDir, "evil.txt"), "evil", "utf8");
|
|
262
|
+
const archivePath = opts.format === "zip" ? path.join(baseDir, "unsafe.zip") : path.join(baseDir, "unsafe.tar.gz");
|
|
263
|
+
if (opts.format === "zip") {
|
|
264
|
+
await execFileAsync("zip", ["-qr", archivePath, ".", entryPath], { cwd: recipeDir });
|
|
265
|
+
return archivePath;
|
|
266
|
+
}
|
|
267
|
+
const tar = buildTar([
|
|
268
|
+
{
|
|
269
|
+
name: "./manifest.json",
|
|
270
|
+
data: Buffer.from(JSON.stringify(manifest, null, 2) + "\n", "utf8"),
|
|
271
|
+
},
|
|
272
|
+
{ name: entryPath, data: Buffer.from("evil\n", "utf8") },
|
|
273
|
+
]);
|
|
274
|
+
const gz = gzipSync(tar);
|
|
275
|
+
await writeFile(archivePath, gz);
|
|
276
|
+
return archivePath;
|
|
277
|
+
}
|
|
278
|
+
function buildTar(entries) {
|
|
279
|
+
const out = [];
|
|
280
|
+
for (const ent of entries) {
|
|
281
|
+
const header = tarHeader({
|
|
282
|
+
name: ent.name,
|
|
283
|
+
size: ent.data.length,
|
|
284
|
+
mtime: 0,
|
|
285
|
+
typeflag: "0",
|
|
286
|
+
});
|
|
287
|
+
out.push(header, ent.data, zeroPadTo512(ent.data.length));
|
|
288
|
+
}
|
|
289
|
+
out.push(Buffer.alloc(1024, 0));
|
|
290
|
+
return Buffer.concat(out);
|
|
291
|
+
}
|
|
292
|
+
function zeroPadTo512(n) {
|
|
293
|
+
const rem = n % 512;
|
|
294
|
+
if (rem === 0)
|
|
295
|
+
return Buffer.alloc(0);
|
|
296
|
+
return Buffer.alloc(512 - rem, 0);
|
|
297
|
+
}
|
|
298
|
+
function tarHeader(opts) {
|
|
299
|
+
const buf = Buffer.alloc(512, 0);
|
|
300
|
+
writeTarString(buf, 0, 100, opts.name);
|
|
301
|
+
writeTarOctal(buf, 100, 8, 0o644);
|
|
302
|
+
writeTarOctal(buf, 108, 8, 0);
|
|
303
|
+
writeTarOctal(buf, 116, 8, 0);
|
|
304
|
+
writeTarOctal(buf, 124, 12, opts.size);
|
|
305
|
+
writeTarOctal(buf, 136, 12, opts.mtime);
|
|
306
|
+
buf.fill(0x20, 148, 156);
|
|
307
|
+
writeTarString(buf, 156, 1, opts.typeflag);
|
|
308
|
+
writeTarString(buf, 257, 6, "ustar");
|
|
309
|
+
writeTarString(buf, 263, 2, "00");
|
|
310
|
+
const sum = buf.reduce((acc, b) => acc + b, 0);
|
|
311
|
+
writeTarChecksum(buf, sum);
|
|
312
|
+
return buf;
|
|
313
|
+
}
|
|
314
|
+
function writeTarString(buf, offset, length, value) {
|
|
315
|
+
const b = Buffer.from(value, "utf8");
|
|
316
|
+
b.copy(buf, offset, 0, Math.min(length, b.length));
|
|
317
|
+
}
|
|
318
|
+
function writeTarOctal(buf, offset, length, value) {
|
|
319
|
+
const raw = Math.max(0, value).toString(8);
|
|
320
|
+
const padded = raw.padStart(length - 1, "0") + "\0";
|
|
321
|
+
writeTarString(buf, offset, length, padded);
|
|
322
|
+
}
|
|
323
|
+
function writeTarChecksum(buf, sum) {
|
|
324
|
+
const raw = Math.max(0, sum).toString(8).padStart(6, "0");
|
|
325
|
+
writeTarString(buf, 148, 8, `${raw}\0 `);
|
|
326
|
+
}
|
|
327
|
+
export async function createUpgradeBundle(files) {
|
|
328
|
+
const manifestUrl = new URL("../../../assets/framework.manifest.json", import.meta.url);
|
|
329
|
+
const manifestText = typeof files["framework.manifest.json"] === "string"
|
|
330
|
+
? files["framework.manifest.json"]
|
|
331
|
+
: await readFile(fileURLToPath(manifestUrl), "utf8");
|
|
332
|
+
const manifest = JSON.parse(manifestText);
|
|
333
|
+
const normalizedFiles = {};
|
|
334
|
+
for (const [relPath, content] of Object.entries(files)) {
|
|
335
|
+
const mapped = relPath.startsWith(".agentplane/agents/")
|
|
336
|
+
? relPath.replace(/^\.agentplane\/agents\//, "agents/")
|
|
337
|
+
: relPath;
|
|
338
|
+
normalizedFiles[mapped] = content;
|
|
339
|
+
}
|
|
340
|
+
normalizedFiles["framework.manifest.json"] ??= manifestText;
|
|
341
|
+
if (manifest.schema_version === 1 && Array.isArray(manifest.files)) {
|
|
342
|
+
for (const entry of manifest.files) {
|
|
343
|
+
if (!entry?.required)
|
|
344
|
+
continue;
|
|
345
|
+
const sourceRel = (entry.source_path ?? entry.path ?? "").trim();
|
|
346
|
+
if (!sourceRel)
|
|
347
|
+
continue;
|
|
348
|
+
if (normalizedFiles[sourceRel] !== undefined)
|
|
349
|
+
continue;
|
|
350
|
+
if (entry.type === "json")
|
|
351
|
+
normalizedFiles[sourceRel] = "{}\n";
|
|
352
|
+
else if (sourceRel.endsWith(".md"))
|
|
353
|
+
normalizedFiles[sourceRel] = "# AGENTS\n";
|
|
354
|
+
else
|
|
355
|
+
normalizedFiles[sourceRel] = "\n";
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const baseDir = await mkdtemp(path.join(os.tmpdir(), "agentplane-upgrade-bundle-"));
|
|
359
|
+
const bundleDir = path.join(baseDir, "bundle");
|
|
360
|
+
await mkdir(bundleDir, { recursive: true });
|
|
361
|
+
for (const [relPath, content] of Object.entries(normalizedFiles)) {
|
|
362
|
+
const fullPath = path.join(bundleDir, relPath);
|
|
363
|
+
await mkdir(path.dirname(fullPath), { recursive: true });
|
|
364
|
+
await writeFile(fullPath, content, "utf8");
|
|
365
|
+
}
|
|
366
|
+
const bundlePath = path.join(baseDir, "agentplane-upgrade.tar.gz");
|
|
367
|
+
await execFileAsync("tar", ["-czf", bundlePath, "-C", bundleDir, "."]);
|
|
368
|
+
const checksum = createHash("sha256")
|
|
369
|
+
.update(await readFile(bundlePath))
|
|
370
|
+
.digest("hex");
|
|
371
|
+
const checksumPath = `${bundlePath}.sha256`;
|
|
372
|
+
await writeFile(checksumPath, `${checksum} agentplane-upgrade.tar.gz\n`, "utf8");
|
|
373
|
+
return { bundlePath, checksumPath };
|
|
374
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type AgentJsonEnvelope = {
|
|
2
|
+
schema_version?: number;
|
|
3
|
+
mode?: string;
|
|
4
|
+
command?: string;
|
|
5
|
+
ok?: boolean;
|
|
6
|
+
exit_code?: number;
|
|
7
|
+
stdout?: string;
|
|
8
|
+
stderr?: string;
|
|
9
|
+
data?: unknown;
|
|
10
|
+
};
|
|
11
|
+
export declare function captureStdIO(): {
|
|
12
|
+
readonly stdout: string;
|
|
13
|
+
readonly stderr: string;
|
|
14
|
+
restore(): void;
|
|
15
|
+
};
|
|
16
|
+
export declare function splitOutputLines(text: string): string[];
|
|
17
|
+
export declare function parseAgentJsonEnvelope(stdout: string): AgentJsonEnvelope;
|
|
18
|
+
export declare function expectAgentJsonEnvelope(payload: AgentJsonEnvelope, opts: {
|
|
19
|
+
command: string;
|
|
20
|
+
ok: boolean;
|
|
21
|
+
exitCode: number;
|
|
22
|
+
hasData?: boolean;
|
|
23
|
+
}): void;
|
|
24
|
+
export declare function silenceStdIO(): () => void;
|
|
25
|
+
export declare function runCliSilent(args: string[]): Promise<number>;
|
|
26
|
+
//# sourceMappingURL=stdio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../src/testing/cli-harness/stdio.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,wBAAgB,YAAY;;;;EAgC3B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMvD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAExE;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE;IACJ,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GACA,IAAI,CAYN;AAED,wBAAgB,YAAY,IAAI,MAAM,IAAI,CAkBzC;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAOlE"}
|