@peterxiaoyang/superspec 0.1.0
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/README.md +47 -0
- package/adapters/codex/agents/architect.toml +157 -0
- package/adapters/codex/agents/code-reviewer.toml +175 -0
- package/adapters/codex/agents/critic.toml +114 -0
- package/adapters/codex/agents/test-engineer.toml +163 -0
- package/adapters/codex/agents/verifier.toml +119 -0
- package/adapters/codex/install-map.json +81 -0
- package/bin/launch.js +37 -0
- package/bin/superspec-guard.js +4 -0
- package/bin/superspec-init.js +4 -0
- package/bin/superspec.js +4 -0
- package/dist/src/archive.d.ts +23 -0
- package/dist/src/archive.js +428 -0
- package/dist/src/cli.d.ts +1 -0
- package/dist/src/cli.js +20 -0
- package/dist/src/cli_args.d.ts +12 -0
- package/dist/src/cli_args.js +146 -0
- package/dist/src/core.d.ts +19 -0
- package/dist/src/core.js +357 -0
- package/dist/src/disclosure.d.ts +35 -0
- package/dist/src/disclosure.js +671 -0
- package/dist/src/evidence.d.ts +28 -0
- package/dist/src/evidence.js +849 -0
- package/dist/src/gates.d.ts +16 -0
- package/dist/src/gates.js +1470 -0
- package/dist/src/git.d.ts +8 -0
- package/dist/src/git.js +112 -0
- package/dist/src/init_cli.d.ts +2 -0
- package/dist/src/init_cli.js +145 -0
- package/dist/src/install_engine.d.ts +54 -0
- package/dist/src/install_engine.js +351 -0
- package/dist/src/invariants.d.ts +16 -0
- package/dist/src/invariants.js +363 -0
- package/dist/src/openspec.d.ts +18 -0
- package/dist/src/openspec.js +157 -0
- package/dist/src/paths.d.ts +22 -0
- package/dist/src/paths.js +203 -0
- package/dist/src/project_init.d.ts +4 -0
- package/dist/src/project_init.js +161 -0
- package/dist/src/state.d.ts +37 -0
- package/dist/src/state.js +464 -0
- package/dist/src/tasks.d.ts +23 -0
- package/dist/src/tasks.js +225 -0
- package/dist/src/util.d.ts +120 -0
- package/dist/src/util.js +442 -0
- package/dist/superspec.d.ts +4 -0
- package/dist/superspec.js +57 -0
- package/dist/superspec_guard.d.ts +4 -0
- package/dist/superspec_guard.js +19 -0
- package/dist/superspec_init.d.ts +2 -0
- package/dist/superspec_init.js +17 -0
- package/package.json +63 -0
- package/schemas/install-manifest.schema.json +80 -0
- package/templates/sidecar/archive-preservation.json +11 -0
- package/templates/sidecar/business-invariants.md +38 -0
- package/templates/sidecar/config.yaml +13 -0
- package/templates/sidecar/discovery.md +24 -0
- package/templates/sidecar/test-contract.md +26 -0
- package/templates/workflow/prompts/architect.md +113 -0
- package/templates/workflow/prompts/code-reviewer.md +141 -0
- package/templates/workflow/prompts/critic.md +80 -0
- package/templates/workflow/prompts/test-engineer.md +130 -0
- package/templates/workflow/prompts/verifier.md +85 -0
- package/templates/workflow/skills/superspec-apply/SKILL.md +72 -0
- package/templates/workflow/skills/superspec-archive/SKILL.md +41 -0
- package/templates/workflow/skills/superspec-explore/SKILL.md +70 -0
- package/templates/workflow/skills/superspec-propose/SKILL.md +79 -0
- package/templates/workflow/skills/superspec-review/SKILL.md +237 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { JsonMap, Reason, TaskInfo } from "./util.ts";
|
|
2
|
+
export declare function file_blob_sha(filePath: string): string;
|
|
3
|
+
export declare function git_lines(repoRoot: string, ...args: string[]): string[];
|
|
4
|
+
export declare function dirty_worktree_paths(repoRoot: string): string[];
|
|
5
|
+
export declare function dirty_worktree_reasons(repoRoot: string, changeRoot: string, evidences: JsonMap[]): Reason[];
|
|
6
|
+
export declare function dirty_write_scope_red_reasons(repoRoot: string, tasks: Record<string, TaskInfo>, evidences: JsonMap[]): Reason[];
|
|
7
|
+
export declare function review_diff_paths(repoRoot: string, baseRef: string, headRef: string): string[];
|
|
8
|
+
export declare function review_diff_coverage_reasons(repoRoot: string, ev: JsonMap): Reason[];
|
package/dist/src/git.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, relative } from "node:path";
|
|
3
|
+
import { GuardError, reason, renderList, runCommand, runtime } from "./util.js";
|
|
4
|
+
import { splitList, task_test_evidence } from "./tasks.js";
|
|
5
|
+
import { live_pass } from "./evidence.js";
|
|
6
|
+
export function file_blob_sha(filePath) {
|
|
7
|
+
if (!existsSync(filePath) || !statSync(filePath).isFile())
|
|
8
|
+
throw new GuardError(`git_blob_inspection_failure: reviewed target missing: ${filePath}`);
|
|
9
|
+
const proc = runCommand("git", ["hash-object", "--no-filters", filePath], { cwd: dirname(filePath), timeout: 30_000 });
|
|
10
|
+
if (proc.error || proc.status !== 0)
|
|
11
|
+
throw new GuardError(`git_blob_inspection_failure: git hash-object failed: ${proc.stderr.trim()}`);
|
|
12
|
+
return proc.stdout.trim();
|
|
13
|
+
}
|
|
14
|
+
export function git_lines(repoRoot, ...args) {
|
|
15
|
+
const proc = runCommand("git", args, { cwd: repoRoot, timeout: 30_000 });
|
|
16
|
+
if (proc.error || proc.status !== 0)
|
|
17
|
+
throw new GuardError(`git_blob_inspection_failure: git ${args.join(" ")} exit ${proc.status}: ${proc.stderr.trim()}`);
|
|
18
|
+
return proc.stdout.split(/\r?\n/).filter((line) => line.trim());
|
|
19
|
+
}
|
|
20
|
+
export function dirty_worktree_paths(repoRoot) {
|
|
21
|
+
const paths = new Set();
|
|
22
|
+
const proc = runCommand("git", ["status", "--porcelain=v1", "-z", "--no-renames"], { cwd: repoRoot, timeout: 30_000 });
|
|
23
|
+
if (proc.error || proc.status !== 0) {
|
|
24
|
+
throw new GuardError(`git_blob_inspection_failure: git status --porcelain=v1 -z --no-renames exit ${proc.status}: ${proc.stderr.trim()}`);
|
|
25
|
+
}
|
|
26
|
+
const entries = proc.stdout.split("\0").filter(Boolean);
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
if (entry.length < 4)
|
|
29
|
+
continue;
|
|
30
|
+
const item = entry.slice(3);
|
|
31
|
+
if (item)
|
|
32
|
+
paths.add(item);
|
|
33
|
+
}
|
|
34
|
+
return [...paths].sort();
|
|
35
|
+
}
|
|
36
|
+
export function dirty_worktree_reasons(repoRoot, changeRoot, evidences) {
|
|
37
|
+
let dirty;
|
|
38
|
+
try {
|
|
39
|
+
dirty = runtime.dirty_worktree_paths(repoRoot);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
return [reason("dirty_worktree_unavailable", `dirty worktree paths could not be inspected: ${String(err.message ?? err)}`)];
|
|
43
|
+
}
|
|
44
|
+
if (dirty.length === 0)
|
|
45
|
+
return [];
|
|
46
|
+
let changeRel = "";
|
|
47
|
+
const rel = relative(repoRoot, changeRoot);
|
|
48
|
+
if (rel && !rel.startsWith("..") && !isAbsolute(rel))
|
|
49
|
+
changeRel = rel;
|
|
50
|
+
const unknown = dirty.filter((item) => !(changeRel && item.startsWith(`${changeRel}/`)));
|
|
51
|
+
if (unknown.length === 0)
|
|
52
|
+
return [];
|
|
53
|
+
const confirmations = live_pass(evidences, { gate: "branch_handling", kind: "human_confirmation" });
|
|
54
|
+
const confirmedScopes = confirmations.flatMap((ev) => (Array.isArray(ev.confirmed_paths) ? ev.confirmed_paths.map((item) => String(item)).filter(Boolean) : []));
|
|
55
|
+
const unconfirmed = unknown.filter((item) => !confirmedScopes.some((scope) => pathInScope(item, scope)));
|
|
56
|
+
if (unconfirmed.length === 0)
|
|
57
|
+
return [];
|
|
58
|
+
return [reason("dirty_worktree_unattributed", `dirty/untracked files require branch/scope handling evidence with confirmed_paths before review_ready: ${renderList(unconfirmed.slice(0, 20))}`)];
|
|
59
|
+
}
|
|
60
|
+
function pathInScope(pathValue, scope) {
|
|
61
|
+
const normalized = scope.replace(/\/+$/, "");
|
|
62
|
+
return pathValue === normalized || pathValue.startsWith(`${normalized}/`);
|
|
63
|
+
}
|
|
64
|
+
export function dirty_write_scope_red_reasons(repoRoot, tasks, evidences) {
|
|
65
|
+
let dirty;
|
|
66
|
+
try {
|
|
67
|
+
dirty = runtime.dirty_worktree_paths(repoRoot);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
return [reason("dirty_worktree_unavailable", `dirty worktree paths could not be inspected: ${String(err.message ?? err)}`)];
|
|
71
|
+
}
|
|
72
|
+
const reasons = [];
|
|
73
|
+
for (const [taskId, task] of Object.entries(tasks)) {
|
|
74
|
+
const scopes = splitList(task.attrs.write_scope ?? "");
|
|
75
|
+
if (scopes.length === 0)
|
|
76
|
+
continue;
|
|
77
|
+
const touched = dirty.filter((item) => scopes.some((scope) => pathInScope(item, scope)));
|
|
78
|
+
if (touched.length === 0)
|
|
79
|
+
continue;
|
|
80
|
+
const tddRequired = (task.attrs.tdd_required ?? "true").toLowerCase() !== "false";
|
|
81
|
+
const tddMode = task.attrs.tdd_mode ?? "new-behavior";
|
|
82
|
+
if (!tddRequired || tddMode === "behavior-preserving-refactor")
|
|
83
|
+
continue;
|
|
84
|
+
if (task_test_evidence(evidences, taskId, "expected_failure", "task_edit").length === 0) {
|
|
85
|
+
reasons.push(reason("missing_red_evidence", `task ${taskId} write_scope changed without RED evidence: ${renderList(touched.slice(0, 20))}`, touched.slice(0, 20)));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return reasons;
|
|
89
|
+
}
|
|
90
|
+
export function review_diff_paths(repoRoot, baseRef, headRef) {
|
|
91
|
+
return runtime.git_lines(repoRoot, "diff", "--name-only", `${baseRef}..${headRef}`);
|
|
92
|
+
}
|
|
93
|
+
export function review_diff_coverage_reasons(repoRoot, ev) {
|
|
94
|
+
const { base_ref: baseRef, head_ref: headRef, reviewed_files: reviewedFiles } = ev;
|
|
95
|
+
if (typeof baseRef !== "string" || !baseRef || typeof headRef !== "string" || !headRef) {
|
|
96
|
+
return [reason("review_evidence_incomplete", `${ev._path}: base_ref and head_ref must be non-empty strings`)];
|
|
97
|
+
}
|
|
98
|
+
if (!Array.isArray(reviewedFiles) || reviewedFiles.length === 0)
|
|
99
|
+
return [];
|
|
100
|
+
let diffFiles;
|
|
101
|
+
try {
|
|
102
|
+
diffFiles = new Set(runtime.review_diff_paths(repoRoot, baseRef, headRef));
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return [reason("review_diff_unavailable", String(err.message ?? err))];
|
|
106
|
+
}
|
|
107
|
+
const reviewed = new Set(reviewedFiles.map((item) => String(item)));
|
|
108
|
+
const missing = [...diffFiles].filter((item) => !reviewed.has(item)).sort();
|
|
109
|
+
if (missing.length === 0)
|
|
110
|
+
return [];
|
|
111
|
+
return [reason("review_diff_not_covered", `${ev._path}: reviewed_files missing diff paths: ${renderList(missing.slice(0, 20))}`, missing.slice(0, 20))];
|
|
112
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { block, GuardError, printDecision, reason } from "./core.js";
|
|
2
|
+
import { project_init } from "./project_init.js";
|
|
3
|
+
import { install_workflow, uninstall_workflow, update_workflow } from "./install_engine.js";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { createInterface } from "node:readline/promises";
|
|
7
|
+
function usage() {
|
|
8
|
+
return "usage: superspec init [-h] [--scope {project,user}] [--path PATH] [--codex-home PATH] [--create] [--update] [--uninstall] [--dry-run] [--force]\n";
|
|
9
|
+
}
|
|
10
|
+
function help() {
|
|
11
|
+
return `${usage()}\noptional arguments:\n -h, --help show this help message and exit\n --scope {project,user} install into this project's .codex directory or into the Codex user home (default: project)\n --project shortcut for --scope project\n --user shortcut for --scope user\n --global compatibility alias for --user\n --path PATH project root for --scope project (default: current directory)\n --codex-home PATH Codex user home for --scope user (default: $CODEX_HOME or ~/.codex)\n --create accepted for compatibility; init creates missing surfaces by default\n --update manifest-driven update of managed SuperSpec surfaces (user-modified files kept, new version written to *.new)\n --uninstall manifest-driven removal of managed SuperSpec surfaces (.superspec data and preexisting/user-modified files are kept)\n --dry-run with --uninstall: print what would be removed without touching files\n --force with install: overwrite pre-existing different files (backs up *.bak)\n`;
|
|
12
|
+
}
|
|
13
|
+
function parse_init_argv(argv) {
|
|
14
|
+
const getValue = (flag) => {
|
|
15
|
+
const idx = argv.indexOf(flag);
|
|
16
|
+
if (idx === -1)
|
|
17
|
+
return undefined;
|
|
18
|
+
const value = argv[idx + 1];
|
|
19
|
+
if (value === undefined || value.startsWith("--"))
|
|
20
|
+
throw new GuardError(`${flag} requires a value`);
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
const update = argv.includes("--update");
|
|
24
|
+
const uninstall = argv.includes("--uninstall");
|
|
25
|
+
if (update && uninstall)
|
|
26
|
+
throw new GuardError("--update and --uninstall are mutually exclusive");
|
|
27
|
+
const scopeFlag = getValue("--scope");
|
|
28
|
+
if (scopeFlag !== undefined && !["project", "user", "global"].includes(scopeFlag))
|
|
29
|
+
throw new GuardError("--scope must be project or user");
|
|
30
|
+
const userShortcut = argv.includes("--user") || argv.includes("--global");
|
|
31
|
+
if (userShortcut && argv.includes("--project"))
|
|
32
|
+
throw new GuardError("--user/--global and --project are mutually exclusive");
|
|
33
|
+
let scope = scopeFlag === "global" ? "user" : scopeFlag ?? null;
|
|
34
|
+
if (userShortcut)
|
|
35
|
+
scope = "user";
|
|
36
|
+
if (argv.includes("--project"))
|
|
37
|
+
scope = "project";
|
|
38
|
+
return {
|
|
39
|
+
path: resolve(getValue("--path") ?? process.cwd()),
|
|
40
|
+
codexHome: resolve(getValue("--codex-home") ?? process.env.CODEX_HOME ?? joinHomeCodex()),
|
|
41
|
+
mode: uninstall ? "uninstall" : update ? "update" : "install",
|
|
42
|
+
scope,
|
|
43
|
+
dryRun: argv.includes("--dry-run"),
|
|
44
|
+
force: argv.includes("--force"),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function joinHomeCodex() {
|
|
48
|
+
return `${homedir()}/.codex`;
|
|
49
|
+
}
|
|
50
|
+
function engineDecision(gate, projectRoot, result, nextActions) {
|
|
51
|
+
if (result.problems.length > 0) {
|
|
52
|
+
const decision = block("project", gate, result.problems.map((item) => reason(`${gate}_failed`, item)));
|
|
53
|
+
return { ...decision, project_root: projectRoot, actions: result.actions, next_allowed_actions: [`fix ${gate}_failed reasons, then rerun`] };
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
allowed: true,
|
|
57
|
+
decision: "allow",
|
|
58
|
+
change_id: null,
|
|
59
|
+
gate,
|
|
60
|
+
project_root: projectRoot,
|
|
61
|
+
actions: result.actions,
|
|
62
|
+
block_reasons: [],
|
|
63
|
+
next_allowed_actions: nextActions,
|
|
64
|
+
trust_warnings: [".superspec runtime data is never touched by install/update/uninstall; only manifest-managed files are"],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async function promptInstallScope() {
|
|
68
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
69
|
+
try {
|
|
70
|
+
for (;;) {
|
|
71
|
+
const answer = (await rl.question("Install SuperSpec Codex surfaces to project or user? [project] ")).trim().toLowerCase();
|
|
72
|
+
if (answer === "" || answer === "project" || answer === "p" || answer === "1")
|
|
73
|
+
return "project";
|
|
74
|
+
if (answer === "user" || answer === "u" || answer === "2" || answer === "global" || answer === "g")
|
|
75
|
+
return "user";
|
|
76
|
+
process.stderr.write("Please answer project or user.\n");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
rl.close();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function canPrompt() {
|
|
84
|
+
return Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
85
|
+
}
|
|
86
|
+
function run_init(args, scope) {
|
|
87
|
+
const targetRoot = scope === "user" ? args.codexHome : args.path;
|
|
88
|
+
const gatePrefix = scope === "user" ? "user" : "project";
|
|
89
|
+
let summary;
|
|
90
|
+
if (args.mode === "uninstall") {
|
|
91
|
+
summary = engineDecision(`${gatePrefix}_uninstall`, targetRoot, uninstall_workflow(targetRoot, { dryRun: args.dryRun, scope }), [
|
|
92
|
+
`managed SuperSpec surfaces removed; run superspec init --scope ${scope} to reinstall`,
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
else if (args.mode === "update") {
|
|
96
|
+
summary = engineDecision(`${gatePrefix}_update`, targetRoot, update_workflow(targetRoot, { scope }), [
|
|
97
|
+
scope === "project" ? "review *.new files for user-modified surfaces, then rerun superspec guard check-init" : "review *.new files for user-modified user-level surfaces",
|
|
98
|
+
]);
|
|
99
|
+
}
|
|
100
|
+
else if (scope === "user") {
|
|
101
|
+
summary = engineDecision("user_install", targetRoot, install_workflow(targetRoot, { force: args.force, scope: "user" }), [
|
|
102
|
+
"user-level SuperSpec Codex surfaces installed; use superspec init --scope project inside a repo when project-local surfaces are needed",
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
summary = project_init(args.path, { force: args.force });
|
|
107
|
+
}
|
|
108
|
+
summary.install_scope = scope;
|
|
109
|
+
summary.install_root = targetRoot;
|
|
110
|
+
printDecision(summary);
|
|
111
|
+
return summary.allowed ? 0 : 1;
|
|
112
|
+
}
|
|
113
|
+
export function main_init(argv = process.argv.slice(2)) {
|
|
114
|
+
try {
|
|
115
|
+
if (argv.includes("-h") || argv.includes("--help")) {
|
|
116
|
+
process.stdout.write(help());
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
const args = parse_init_argv(argv);
|
|
120
|
+
return run_init(args, args.scope ?? "project");
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
const change = "project";
|
|
124
|
+
const errReason = err instanceof GuardError ? reason("guard_error", err.message) : reason("guard_internal_error", `${err.name}: ${err.message}`);
|
|
125
|
+
printDecision(block(change, "guard_error", [errReason]));
|
|
126
|
+
return 2;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export async function main_init_async(argv = process.argv.slice(2)) {
|
|
130
|
+
try {
|
|
131
|
+
if (argv.includes("-h") || argv.includes("--help")) {
|
|
132
|
+
process.stdout.write(help());
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
const args = parse_init_argv(argv);
|
|
136
|
+
const scope = args.scope ?? (canPrompt() ? await promptInstallScope() : "project");
|
|
137
|
+
return run_init(args, scope);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
const change = "project";
|
|
141
|
+
const errReason = err instanceof GuardError ? reason("guard_error", err.message) : reason("guard_internal_error", `${err.name}: ${err.message}`);
|
|
142
|
+
printDecision(block(change, "guard_error", [errReason]));
|
|
143
|
+
return 2;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type JsonMap } from "./util.ts";
|
|
2
|
+
export declare const INSTALL_MAP_REL: string;
|
|
3
|
+
export declare const PACKAGE_ROOT: string;
|
|
4
|
+
export declare const PROJECT_INSTALL_MANIFEST_REL: string;
|
|
5
|
+
export declare const USER_INSTALL_MANIFEST_REL: string;
|
|
6
|
+
export declare const INSTALL_MANIFEST_REL: string;
|
|
7
|
+
export type InstallMapping = {
|
|
8
|
+
kind: string;
|
|
9
|
+
source: string;
|
|
10
|
+
target: string;
|
|
11
|
+
};
|
|
12
|
+
export type InstallScope = "project" | "user";
|
|
13
|
+
export type ManifestFileEntry = {
|
|
14
|
+
path: string;
|
|
15
|
+
sha256: string;
|
|
16
|
+
managed: boolean;
|
|
17
|
+
preexisting: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type EngineAction = {
|
|
20
|
+
action: string;
|
|
21
|
+
status: "ok" | "created" | "updated" | "skipped" | "removed" | "would_remove" | "failed";
|
|
22
|
+
refs?: string[];
|
|
23
|
+
detail?: string;
|
|
24
|
+
};
|
|
25
|
+
export type EngineResult = {
|
|
26
|
+
actions: EngineAction[];
|
|
27
|
+
problems: string[];
|
|
28
|
+
manifest: JsonMap | null;
|
|
29
|
+
};
|
|
30
|
+
export declare function load_install_map(packageRoot?: string): {
|
|
31
|
+
mappings: InstallMapping[];
|
|
32
|
+
problems: string[];
|
|
33
|
+
};
|
|
34
|
+
export declare function manifest_shape_problems(manifest: any): string[];
|
|
35
|
+
export declare function read_install_manifest(repoRoot: string, opts?: {
|
|
36
|
+
scope?: InstallScope;
|
|
37
|
+
}): {
|
|
38
|
+
manifest: JsonMap | null;
|
|
39
|
+
problems: string[];
|
|
40
|
+
};
|
|
41
|
+
export declare function install_manifest_rel(scope?: InstallScope): string;
|
|
42
|
+
export declare function install_workflow(repoRoot: string, opts?: {
|
|
43
|
+
force?: boolean;
|
|
44
|
+
packageRoot?: string;
|
|
45
|
+
scope?: InstallScope;
|
|
46
|
+
}): EngineResult;
|
|
47
|
+
export declare function update_workflow(repoRoot: string, opts?: {
|
|
48
|
+
packageRoot?: string;
|
|
49
|
+
scope?: InstallScope;
|
|
50
|
+
}): EngineResult;
|
|
51
|
+
export declare function uninstall_workflow(repoRoot: string, opts?: {
|
|
52
|
+
dryRun?: boolean;
|
|
53
|
+
scope?: InstallScope;
|
|
54
|
+
}): EngineResult;
|