specrails-core 5.6.0 → 6.0.1
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 +27 -145
- package/bin/specrails-core.mjs +12 -554
- package/dist/agent-runtime/capabilities.js +0 -1
- package/dist/agent-runtime/change-scope.d.ts +63 -0
- package/dist/agent-runtime/change-scope.js +297 -0
- package/dist/agent-runtime/cli-executor.d.ts +1 -1
- package/dist/agent-runtime/cli-executor.js +1 -2
- package/dist/agent-runtime/cli-process.js +0 -1
- package/dist/agent-runtime/cli.js +4 -5
- package/dist/agent-runtime/codex-schema.js +0 -1
- package/dist/agent-runtime/compact/architect.d.ts +3 -272
- package/dist/agent-runtime/compact/architect.js +8 -9
- package/dist/agent-runtime/compact/chat-client.d.ts +3 -3
- package/dist/agent-runtime/compact/chat-client.js +1 -2
- package/dist/agent-runtime/compact/developer.d.ts +3 -70
- package/dist/agent-runtime/compact/developer.js +13 -14
- package/dist/agent-runtime/compact/environment.d.ts +16 -5
- package/dist/agent-runtime/compact/environment.js +32 -3
- package/dist/agent-runtime/compact/exit-code-honesty.d.ts +2 -1
- package/dist/agent-runtime/compact/exit-code-honesty.js +0 -1
- package/dist/agent-runtime/compact/guarded-loop.d.ts +2 -18
- package/dist/agent-runtime/compact/guarded-loop.js +7 -8
- package/dist/agent-runtime/compact/prompt-inputs.d.ts +0 -2
- package/dist/agent-runtime/compact/prompt-inputs.js +1 -2
- package/dist/agent-runtime/compact/reviewer.d.ts +0 -13
- package/dist/agent-runtime/compact/reviewer.js +5 -6
- package/dist/agent-runtime/compact/step.d.ts +0 -1
- package/dist/agent-runtime/compact/step.js +1 -2
- package/dist/agent-runtime/compact/test-reachability.js +6 -3
- package/dist/agent-runtime/config.js +0 -1
- package/dist/agent-runtime/core-host.d.ts +2 -2
- package/dist/agent-runtime/core-host.js +2 -3
- package/dist/agent-runtime/durable-store.d.ts +0 -1
- package/dist/agent-runtime/durable-store.js +1 -2
- package/dist/agent-runtime/efficiency-summary.d.ts +2 -2
- package/dist/agent-runtime/efficiency-summary.js +1 -2
- package/dist/agent-runtime/efficiency-types.js +0 -1
- package/dist/agent-runtime/efficiency.js +0 -1
- package/dist/agent-runtime/evaluation-corpus.js +0 -1
- package/dist/agent-runtime/evaluation.d.ts +2 -1
- package/dist/agent-runtime/evaluation.js +1 -2
- package/dist/agent-runtime/executor-types.d.ts +1 -1
- package/dist/agent-runtime/executor-types.js +0 -1
- package/dist/agent-runtime/executors.js +0 -1
- package/dist/agent-runtime/gemini-policy.js +0 -1
- package/dist/agent-runtime/graph/artifacts.d.ts +1 -1
- package/dist/agent-runtime/graph/artifacts.js +5 -3
- package/dist/agent-runtime/graph/convergence.d.ts +26 -0
- package/dist/agent-runtime/graph/convergence.js +62 -0
- package/dist/agent-runtime/graph/nodes.d.ts +1 -1
- package/dist/agent-runtime/graph/nodes.js +170 -24
- package/dist/agent-runtime/graph/review-policy.js +0 -1
- package/dist/agent-runtime/graph/roles.d.ts +2 -5
- package/dist/agent-runtime/graph/roles.js +2 -8
- package/dist/agent-runtime/graph/state.d.ts +6 -1
- package/dist/agent-runtime/graph/state.js +2 -1
- package/dist/agent-runtime/graph-checkpointer.d.ts +2 -1
- package/dist/agent-runtime/graph-checkpointer.js +0 -1
- package/dist/agent-runtime/guardrails.d.ts +3 -3
- package/dist/agent-runtime/guardrails.js +1 -2
- package/dist/agent-runtime/index.d.ts +1 -1
- package/dist/agent-runtime/index.js +1 -2
- package/dist/agent-runtime/kimi-acp.js +1 -2
- package/dist/agent-runtime/kimi-model.d.ts +6 -0
- package/dist/agent-runtime/kimi-model.js +12 -0
- package/dist/agent-runtime/openai-executor.d.ts +0 -9
- package/dist/agent-runtime/openai-executor.js +6 -7
- package/dist/agent-runtime/openspec-tool-server.js +1 -2
- package/dist/agent-runtime/openspec.d.ts +0 -2
- package/dist/agent-runtime/openspec.js +1 -6
- package/dist/agent-runtime/prompts.d.ts +11 -5
- package/dist/agent-runtime/prompts.js +46 -17
- package/dist/agent-runtime/provider-diagnostic.js +1 -2
- package/dist/agent-runtime/recovery.js +1 -2
- package/dist/agent-runtime/repository-context.d.ts +1 -1
- package/dist/agent-runtime/repository-context.js +19 -1
- package/dist/agent-runtime/review-context.d.ts +1 -1
- package/dist/agent-runtime/review-context.js +0 -1
- package/dist/agent-runtime/role-routing.js +0 -1
- package/dist/agent-runtime/role-state.js +0 -1
- package/dist/agent-runtime/runtime-identity.js +1 -2
- package/dist/agent-runtime/tool-event.js +0 -1
- package/dist/agent-runtime/verification-plan.d.ts +5 -4
- package/dist/agent-runtime/verification-plan.js +9 -5
- package/dist/agent-runtime/workflow-types.js +0 -1
- package/dist/agent-runtime/workflow.js +0 -1
- package/dist/agent-runtime/workspace-tools.d.ts +2 -2
- package/dist/agent-runtime/workspace-tools.js +1 -2
- package/dist/installer/cli.d.ts +3 -32
- package/dist/installer/cli.js +26 -101
- package/dist/installer/commands/framework.d.ts +4 -3
- package/dist/installer/commands/framework.js +0 -1
- package/dist/installer/commands/init.d.ts +4 -25
- package/dist/installer/commands/init.js +5 -8
- package/dist/installer/phases/framework-lifecycle.d.ts +3 -17
- package/dist/installer/phases/framework-lifecycle.js +2 -3
- package/dist/installer/phases/install-config.d.ts +7 -8
- package/dist/installer/phases/install-config.js +2 -7
- package/dist/installer/phases/manifest.d.ts +6 -7
- package/dist/installer/phases/manifest.js +2 -7
- package/dist/installer/phases/prereqs.d.ts +6 -7
- package/dist/installer/phases/prereqs.js +4 -6
- package/dist/installer/phases/provider-detect.d.ts +6 -7
- package/dist/installer/phases/provider-detect.js +2 -4
- package/dist/installer/phases/scaffold.d.ts +9 -10
- package/dist/installer/phases/scaffold.js +82 -805
- package/dist/installer/util/errors.js +0 -1
- package/dist/installer/util/exec.d.ts +3 -2
- package/dist/installer/util/exec.js +0 -1
- package/dist/installer/util/fs.d.ts +0 -10
- package/dist/installer/util/fs.js +1 -2
- package/dist/installer/util/git.js +0 -1
- package/dist/installer/util/install-transaction.d.ts +2 -2
- package/dist/installer/util/install-transaction.js +1 -2
- package/dist/installer/util/logger.d.ts +1 -3
- package/dist/installer/util/logger.js +0 -1
- package/dist/installer/util/paths.js +0 -1
- package/dist/installer/util/registry.d.ts +4 -8
- package/dist/installer/util/registry.js +2 -3
- package/dist/{installer/runtime → pipeline}/pipeline-state.d.ts +11 -0
- package/dist/{installer/runtime → pipeline}/pipeline-state.js +56 -5
- package/dist/shared/args.d.ts +18 -0
- package/dist/shared/args.js +53 -0
- package/integration-contract.json +11 -47
- package/package.json +3 -10
- package/templates/agents/sr-architect.md +15 -310
- package/templates/agents/sr-developer.md +15 -269
- package/templates/agents/sr-reviewer.md +13 -367
- package/templates/codex-skills/rails/sr-architect/SKILL.md +14 -308
- package/templates/codex-skills/rails/sr-developer/SKILL.md +14 -201
- package/templates/codex-skills/rails/sr-reviewer/SKILL.md +15 -289
- package/templates/kimi/specrails/run-skill.mjs +91 -2173
- package/bin/tui-installer.mjs +0 -430
- package/commands/doctor.md +0 -62
- package/dist/agent-runtime/capabilities.js.map +0 -1
- package/dist/agent-runtime/cli-executor.js.map +0 -1
- package/dist/agent-runtime/cli-process.js.map +0 -1
- package/dist/agent-runtime/cli.js.map +0 -1
- package/dist/agent-runtime/codex-schema.js.map +0 -1
- package/dist/agent-runtime/compact/architect.js.map +0 -1
- package/dist/agent-runtime/compact/chat-client.js.map +0 -1
- package/dist/agent-runtime/compact/developer.js.map +0 -1
- package/dist/agent-runtime/compact/environment.js.map +0 -1
- package/dist/agent-runtime/compact/exit-code-honesty.js.map +0 -1
- package/dist/agent-runtime/compact/guarded-loop.js.map +0 -1
- package/dist/agent-runtime/compact/prompt-inputs.js.map +0 -1
- package/dist/agent-runtime/compact/reviewer.js.map +0 -1
- package/dist/agent-runtime/compact/step.js.map +0 -1
- package/dist/agent-runtime/compact/test-reachability.js.map +0 -1
- package/dist/agent-runtime/config.js.map +0 -1
- package/dist/agent-runtime/core-host.js.map +0 -1
- package/dist/agent-runtime/durable-store.js.map +0 -1
- package/dist/agent-runtime/efficiency-summary.js.map +0 -1
- package/dist/agent-runtime/efficiency-types.js.map +0 -1
- package/dist/agent-runtime/efficiency.js.map +0 -1
- package/dist/agent-runtime/evaluation-corpus.js.map +0 -1
- package/dist/agent-runtime/evaluation.js.map +0 -1
- package/dist/agent-runtime/executor-types.js.map +0 -1
- package/dist/agent-runtime/executors.js.map +0 -1
- package/dist/agent-runtime/gemini-policy.js.map +0 -1
- package/dist/agent-runtime/graph/artifacts.js.map +0 -1
- package/dist/agent-runtime/graph/nodes.js.map +0 -1
- package/dist/agent-runtime/graph/review-policy.js.map +0 -1
- package/dist/agent-runtime/graph/roles.js.map +0 -1
- package/dist/agent-runtime/graph/state.js.map +0 -1
- package/dist/agent-runtime/graph-checkpointer.js.map +0 -1
- package/dist/agent-runtime/guardrails.js.map +0 -1
- package/dist/agent-runtime/index.js.map +0 -1
- package/dist/agent-runtime/kimi-acp.js.map +0 -1
- package/dist/agent-runtime/openai-executor.js.map +0 -1
- package/dist/agent-runtime/openspec-tool-server.js.map +0 -1
- package/dist/agent-runtime/openspec.js.map +0 -1
- package/dist/agent-runtime/prompts.js.map +0 -1
- package/dist/agent-runtime/provider-diagnostic.js.map +0 -1
- package/dist/agent-runtime/recovery.js.map +0 -1
- package/dist/agent-runtime/repository-context.js.map +0 -1
- package/dist/agent-runtime/review-context.js.map +0 -1
- package/dist/agent-runtime/role-routing.js.map +0 -1
- package/dist/agent-runtime/role-state.js.map +0 -1
- package/dist/agent-runtime/runtime-identity.js.map +0 -1
- package/dist/agent-runtime/tool-event.js.map +0 -1
- package/dist/agent-runtime/verification-plan.js.map +0 -1
- package/dist/agent-runtime/workflow-types.js.map +0 -1
- package/dist/agent-runtime/workflow.js.map +0 -1
- package/dist/agent-runtime/workspace-tools.js.map +0 -1
- package/dist/installer/cli.js.map +0 -1
- package/dist/installer/commands/doctor.d.ts +0 -27
- package/dist/installer/commands/doctor.js +0 -615
- package/dist/installer/commands/doctor.js.map +0 -1
- package/dist/installer/commands/framework.js.map +0 -1
- package/dist/installer/commands/init.js.map +0 -1
- package/dist/installer/commands/update.d.ts +0 -56
- package/dist/installer/commands/update.js +0 -257
- package/dist/installer/commands/update.js.map +0 -1
- package/dist/installer/commands/v5-migration.d.ts +0 -32
- package/dist/installer/commands/v5-migration.js +0 -133
- package/dist/installer/commands/v5-migration.js.map +0 -1
- package/dist/installer/phases/framework-lifecycle.js.map +0 -1
- package/dist/installer/phases/install-config.js.map +0 -1
- package/dist/installer/phases/manifest.js.map +0 -1
- package/dist/installer/phases/prereqs.js.map +0 -1
- package/dist/installer/phases/provider-detect.js.map +0 -1
- package/dist/installer/phases/scaffold.js.map +0 -1
- package/dist/installer/runtime/kimi.d.ts +0 -84
- package/dist/installer/runtime/kimi.js +0 -255
- package/dist/installer/runtime/kimi.js.map +0 -1
- package/dist/installer/runtime/pipeline-state.js.map +0 -1
- package/dist/installer/util/errors.js.map +0 -1
- package/dist/installer/util/exec.js.map +0 -1
- package/dist/installer/util/fs.js.map +0 -1
- package/dist/installer/util/git.js.map +0 -1
- package/dist/installer/util/install-transaction.js.map +0 -1
- package/dist/installer/util/logger.js.map +0 -1
- package/dist/installer/util/paths.js.map +0 -1
- package/dist/installer/util/prompts.d.ts +0 -23
- package/dist/installer/util/prompts.js +0 -49
- package/dist/installer/util/prompts.js.map +0 -1
- package/dist/installer/util/registry.js.map +0 -1
- package/dist/installer/util/template.d.ts +0 -23
- package/dist/installer/util/template.js +0 -60
- package/dist/installer/util/template.js.map +0 -1
- package/docs/README.md +0 -40
- package/docs/agent-runtime-efficiency.md +0 -65
- package/docs/agent-runtime.md +0 -393
- package/docs/agents.md +0 -315
- package/docs/changelog.md +0 -168
- package/docs/ci-cd.md +0 -60
- package/docs/concepts.md +0 -183
- package/docs/customization.md +0 -363
- package/docs/deployment.md +0 -234
- package/docs/getting-started.md +0 -122
- package/docs/installation.md +0 -395
- package/docs/local-tickets.md +0 -191
- package/docs/migration-guide.md +0 -140
- package/docs/playbook-oss-maintainer.md +0 -112
- package/docs/playbook-parallel-dev.md +0 -124
- package/docs/playbook-product-discovery.md +0 -115
- package/docs/plugin-architecture.md +0 -144
- package/docs/research/codex-compatibility-analysis.md +0 -365
- package/docs/research/mcp-feasibility-analysis.md +0 -382
- package/docs/testing/test-matrix-codex.md +0 -130
- package/docs/updating.md +0 -89
- package/docs/user-docs/cli-reference.md +0 -428
- package/docs/user-docs/codex-vs-claude-code.md +0 -23
- package/docs/user-docs/core-updates.md +0 -70
- package/docs/user-docs/faq.md +0 -146
- package/docs/user-docs/getting-started-codex.md +0 -194
- package/docs/user-docs/getting-started-kimi.md +0 -423
- package/docs/user-docs/installation.md +0 -237
- package/docs/user-docs/provider-pipelines.md +0 -96
- package/docs/user-docs/quick-start.md +0 -161
- package/docs/windows.md +0 -78
- package/docs/workflows.md +0 -463
- package/schemas/profile.v1.json +0 -207
- package/templates/claude-md/CLAUDE-quickstart.md +0 -54
- package/templates/claude-md/root.md +0 -50
- package/templates/codex-skills/batch-implement/SKILL.md +0 -38
- package/templates/codex-skills/implement/SKILL.md +0 -38
- package/templates/codex-skills/retry/SKILL.md +0 -16
- package/templates/commands/specrails/compat-check.md +0 -271
- package/templates/commands/specrails/doctor.md +0 -62
- package/templates/commands/specrails/explore-spec.md +0 -173
- package/templates/commands/specrails/health-check.md +0 -527
- package/templates/commands/specrails/memory-inspect.md +0 -261
- package/templates/commands/specrails/opsx-diff.md +0 -419
- package/templates/commands/specrails/propose-spec.md +0 -102
- package/templates/commands/specrails/refactor-recommender.md +0 -169
- package/templates/commands/specrails/telemetry.md +0 -553
- package/templates/commands/specrails/why.md +0 -96
- package/templates/gemini-commands/batch-implement.toml +0 -37
- package/templates/gemini-commands/implement.toml +0 -37
- package/templates/gemini-commands/retry.toml +0 -15
- package/templates/profiles/default.json +0 -14
- package/templates/profiles/kimi-default.json +0 -15
- package/templates/rules/layer.md +0 -8
- package/templates/runtime/provider-pipeline.md +0 -113
- package/templates/security/security-exemptions.yaml +0 -20
- package/templates/settings/confidence-config.json +0 -17
- package/templates/settings/settings.json +0 -15
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
// The change a run makes, measured by the host from git rather than taken from
|
|
2
|
+
// a role's own summary, and the boundary it must stay inside.
|
|
3
|
+
//
|
|
4
|
+
// Observed (a monorepo app registered as the repository, busuu-courses inside
|
|
5
|
+
// busuu-web): the configured `yarn test` ran at the checkout root and fanned
|
|
6
|
+
// out to every workspace; the fixer then "repaired" .yarnrc.yml, the root
|
|
7
|
+
// package.json and two other apps, the reviewer rejected those unrelated
|
|
8
|
+
// edits, the fixer reverted them, verification failed again — a loop that
|
|
9
|
+
// never converged. A repository scope makes the boundary explicit: commands
|
|
10
|
+
// default to the package, reviews see the exact change set, and edits outside
|
|
11
|
+
// the scope are undone by the host before anyone verifies or reviews them.
|
|
12
|
+
import { spawnSync } from 'node:child_process';
|
|
13
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
14
|
+
import { lstatSync, mkdirSync, readFileSync, readlinkSync, renameSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
15
|
+
import path from 'node:path';
|
|
16
|
+
import { pipelineStateDirectory, withinRepositoryScope } from '../pipeline/pipeline-state.js';
|
|
17
|
+
/** Git's empty tree: the base of a repository without commits. */
|
|
18
|
+
const EMPTY_TREE = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
|
|
19
|
+
/** Files whose change inside the scope legitimately refreshes a lockfile of an enclosing workspace. */
|
|
20
|
+
const MANIFESTS = new Set(['package.json', 'Cargo.toml', 'go.mod', 'pyproject.toml', 'Pipfile', 'Gemfile', 'composer.json', 'requirements.txt']);
|
|
21
|
+
const LOCKFILES = new Set(['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lock', 'bun.lockb', 'Cargo.lock', 'go.sum', 'go.work.sum', 'poetry.lock', 'uv.lock', 'Pipfile.lock', 'Gemfile.lock', 'composer.lock', '.pnp.cjs', '.pnp.loader.mjs', '.pnp.data.json']);
|
|
22
|
+
const AGENT_MEMORY = ['.claude', '.codex', '.gemini', '.kimi-code'].map(root => root + '/agent-memory');
|
|
23
|
+
const GENERATED = new Set(['node_modules', 'coverage', '.nyc_output', '.jest-cache', '__pycache__', '.pytest_cache', '.mypy_cache', '.ruff_cache', '.venv', 'venv', '.tox', '.gradle', '.cache', '.turbo']);
|
|
24
|
+
/** Bounded memory for restoring a previous out-of-scope state byte for byte; beyond it the base is restored. */
|
|
25
|
+
const RESTORE_FILE_LIMIT = 8 * 1024 * 1024;
|
|
26
|
+
const RESTORE_TOTAL_LIMIT = 64 * 1024 * 1024;
|
|
27
|
+
/** Untracked files present when the run started are host/user state (overlays, local files), not the change. */
|
|
28
|
+
const PREEXISTING_LIMIT = 20_000;
|
|
29
|
+
function gitEnv() {
|
|
30
|
+
// An inherited GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE must not redirect the inspection.
|
|
31
|
+
const env = Object.fromEntries(Object.entries(process.env).filter(([key]) => !key.toUpperCase().startsWith('GIT_')));
|
|
32
|
+
return { ...env, GIT_OPTIONAL_LOCKS: '0', GIT_LITERAL_PATHSPECS: '1', GIT_TERMINAL_PROMPT: '0' };
|
|
33
|
+
}
|
|
34
|
+
function git(root, args, allowFailure = false) {
|
|
35
|
+
const result = spawnSync('git', ['-c', 'core.quotePath=false', '-c', 'core.fsmonitor=false', '-C', root, ...args], { env: gitEnv(), encoding: 'utf8', maxBuffer: 64 * 1024 * 1024, windowsHide: true });
|
|
36
|
+
const overflow = result.error?.code === 'ENOBUFS';
|
|
37
|
+
const ok = !result.error && result.status === 0;
|
|
38
|
+
if (!ok && !allowFailure)
|
|
39
|
+
throw new Error(`git ${args[0]} failed in ${root}: ${String(result.error?.message ?? result.stderr ?? '').trim().slice(0, 400)}`);
|
|
40
|
+
return { ok, stdout: result.stdout ?? '', overflow };
|
|
41
|
+
}
|
|
42
|
+
const posix = (file) => file.split(path.sep).join('/');
|
|
43
|
+
/** A command without `cwd` runs in its repository's scope directory, never at the root of a larger checkout. */
|
|
44
|
+
export function withScopeDefault(context, command) {
|
|
45
|
+
if (command.cwd !== undefined)
|
|
46
|
+
return command;
|
|
47
|
+
const scope = context.repositories.find(repo => repo.id === command.repositoryId)?.scope;
|
|
48
|
+
return scope?.length ? { ...command, cwd: scope[0] } : command;
|
|
49
|
+
}
|
|
50
|
+
/** Model-proposed checks stay inside the repository scope: they prove the change, not the whole checkout. */
|
|
51
|
+
export function assertProposalInScope(context, command, what = 'verification proposal') {
|
|
52
|
+
const repository = context.repositories.find(repo => repo.id === command.repositoryId);
|
|
53
|
+
if (!repository?.scope?.length || command.cwd === undefined)
|
|
54
|
+
return;
|
|
55
|
+
const relative = posix(path.relative(repository.path, path.resolve(repository.path, command.cwd)));
|
|
56
|
+
if (relative === '..' || relative.startsWith('../') || path.isAbsolute(relative) || !withinRepositoryScope(repository, relative)) {
|
|
57
|
+
throw new Error(`Invalid ${what} cwd ${JSON.stringify(command.cwd)}: it runs outside the repository scope (${repository.scope.join(', ')}). Omit cwd to run in ${repository.scope[0]}, or name a directory inside the scope.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Untracked, non-ignored paths; a checkout with an enormous untracked tree reports directories instead of files. */
|
|
61
|
+
function untracked(root) {
|
|
62
|
+
const files = git(root, ['ls-files', '--others', '--exclude-standard', '-z'], true);
|
|
63
|
+
if (files.ok)
|
|
64
|
+
return files.stdout.split('\0').filter(Boolean);
|
|
65
|
+
if (!files.overflow)
|
|
66
|
+
git(root, ['ls-files', '--others', '--exclude-standard', '-z']);
|
|
67
|
+
return git(root, ['ls-files', '--others', '--exclude-standard', '--directory', '-z']).stdout.split('\0').filter(Boolean);
|
|
68
|
+
}
|
|
69
|
+
function baseFile(context) { return path.join(pipelineStateDirectory(context), 'change-base.json'); }
|
|
70
|
+
/**
|
|
71
|
+
* The commit each repository's change is measured against — the host's frozen
|
|
72
|
+
* base when it declared one, otherwise HEAD the first time Core asks (before
|
|
73
|
+
* any role edits) — plus the untracked files that already existed then.
|
|
74
|
+
* Recorded once, so every later turn measures the same change.
|
|
75
|
+
*/
|
|
76
|
+
function baseRecords(context) {
|
|
77
|
+
const file = baseFile(context);
|
|
78
|
+
let recorded = {};
|
|
79
|
+
try {
|
|
80
|
+
const value = JSON.parse(readFileSync(file, 'utf8'));
|
|
81
|
+
if (value.schemaVersion === 1 && value.repositories && typeof value.repositories === 'object')
|
|
82
|
+
recorded = value.repositories;
|
|
83
|
+
}
|
|
84
|
+
catch { /* first use */ }
|
|
85
|
+
let changed = false;
|
|
86
|
+
for (const repository of context.repositories) {
|
|
87
|
+
const known = recorded[repository.id];
|
|
88
|
+
if (known && typeof known.base === 'string' && /^[a-f0-9]{40,64}$/.test(known.base))
|
|
89
|
+
continue;
|
|
90
|
+
let base = repository.baseSha;
|
|
91
|
+
if (!base) {
|
|
92
|
+
const head = git(repository.path, ['rev-parse', '--verify', '--quiet', 'HEAD^{commit}'], true);
|
|
93
|
+
base = head.ok && /^[a-f0-9]{40,64}$/.test(head.stdout.trim()) ? head.stdout.trim() : EMPTY_TREE;
|
|
94
|
+
}
|
|
95
|
+
let present;
|
|
96
|
+
try {
|
|
97
|
+
present = untracked(repository.path);
|
|
98
|
+
}
|
|
99
|
+
catch { /* not a git checkout: the change cannot be measured */ }
|
|
100
|
+
recorded[repository.id] = { base, ...(present && present.length <= PREEXISTING_LIMIT ? { preexisting: present } : {}) };
|
|
101
|
+
changed = true;
|
|
102
|
+
}
|
|
103
|
+
if (changed) {
|
|
104
|
+
mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
105
|
+
const temp = file + '.' + randomUUID() + '.tmp';
|
|
106
|
+
try {
|
|
107
|
+
writeFileSync(temp, JSON.stringify({ schemaVersion: 1, repositories: recorded }) + '\n', { flag: 'wx', mode: 0o600 });
|
|
108
|
+
renameSync(temp, file);
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
rmSync(temp, { force: true });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return recorded;
|
|
115
|
+
}
|
|
116
|
+
/** Base commit per repository id; the first call records it. */
|
|
117
|
+
export function changeBases(context) {
|
|
118
|
+
return Object.fromEntries(Object.entries(baseRecords(context)).map(([id, record]) => [id, record.base]));
|
|
119
|
+
}
|
|
120
|
+
/** Host and runtime state, the change's own OpenSpec artifacts and generated trees are never part of the code change. */
|
|
121
|
+
function ignored(context, repository, change, file, fresh) {
|
|
122
|
+
if (file === '.specrails' || file.startsWith('.specrails/'))
|
|
123
|
+
return true;
|
|
124
|
+
if (repository.id === context.artifactRepositoryId && change && (file === 'openspec/changes/' + change || file.startsWith('openspec/changes/' + change + '/')))
|
|
125
|
+
return true;
|
|
126
|
+
if (!fresh)
|
|
127
|
+
return false;
|
|
128
|
+
return AGENT_MEMORY.some(root => file === root || file.startsWith(root + '/')) || file.split('/').some(segment => GENERATED.has(segment));
|
|
129
|
+
}
|
|
130
|
+
/** Every path that differs from the base: tracked edits (staged or not), deletions and new untracked files. */
|
|
131
|
+
export function repositoryChanges(context, repository, base, change) {
|
|
132
|
+
const files = new Map();
|
|
133
|
+
const diff = git(repository.path, ['diff', '--name-status', '-z', '--no-renames', '--ignore-submodules=all', base, '--']).stdout.split('\0');
|
|
134
|
+
for (let i = 0; i + 1 < diff.length; i += 2) {
|
|
135
|
+
const status = diff[i], file = diff[i + 1];
|
|
136
|
+
if (!status || !file || ignored(context, repository, change, file, false))
|
|
137
|
+
continue;
|
|
138
|
+
files.set(file, status.startsWith('A') ? 'added' : status.startsWith('D') ? 'deleted' : 'modified');
|
|
139
|
+
}
|
|
140
|
+
for (const file of untracked(repository.path)) {
|
|
141
|
+
const relative = file.replace(/\/$/, '');
|
|
142
|
+
if (!files.has(relative) && !ignored(context, repository, change, relative, true))
|
|
143
|
+
files.set(file, 'added');
|
|
144
|
+
}
|
|
145
|
+
return [...files].map(([file, status]) => ({ path: file, status })).sort((a, b) => a.path.localeCompare(b.path));
|
|
146
|
+
}
|
|
147
|
+
/** What this run changed, per repository and bounded: untracked files that predate the run are not part of it. */
|
|
148
|
+
export function changeSet(context, change, limit = 5000) {
|
|
149
|
+
const records = baseRecords(context);
|
|
150
|
+
return context.repositories.map(repository => {
|
|
151
|
+
const record = records[repository.id];
|
|
152
|
+
const preexisting = new Set(record.preexisting ?? []);
|
|
153
|
+
const files = repositoryChanges(context, repository, record.base, change).filter(file => !(file.status === 'added' && preexisting.has(file.path)));
|
|
154
|
+
return { repositoryId: repository.id, ...(repository.scope ? { scope: repository.scope } : {}), files: files.slice(0, limit), truncated: files.length > limit };
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function dependencyFileForScope(repository, file) {
|
|
158
|
+
// A dependency change in the package legitimately refreshes the lockfile (or
|
|
159
|
+
// Yarn's install artifacts) of a workspace that encloses the scope.
|
|
160
|
+
const enclosing = (directory) => (repository.scope ?? []).some(scope => directory === '.' || directory === '' || scope === directory || scope.startsWith(directory + '/'));
|
|
161
|
+
if (LOCKFILES.has(path.posix.basename(file)))
|
|
162
|
+
return enclosing(path.posix.dirname(file));
|
|
163
|
+
const yarn = /^(?:(.*)\/)?\.yarn\/(?:cache\/|install-state\.gz$)/.exec(file);
|
|
164
|
+
return yarn !== null && enclosing(yarn[1] ?? '.');
|
|
165
|
+
}
|
|
166
|
+
/** Changes outside the repository scope (none when the whole checkout is the repository). */
|
|
167
|
+
export function outOfScope(repository, files) {
|
|
168
|
+
if (!repository.scope?.length)
|
|
169
|
+
return [];
|
|
170
|
+
const manifestChanged = files.some(file => withinRepositoryScope(repository, file.path) && MANIFESTS.has(path.posix.basename(file.path)));
|
|
171
|
+
return files.filter(file => !withinRepositoryScope(repository, file.path.replace(/\/$/, '')) && !(manifestChanged && dependencyFileForScope(repository, file.path)));
|
|
172
|
+
}
|
|
173
|
+
function fingerprintOf(file) {
|
|
174
|
+
const stat = lstatSync(file, { throwIfNoEntry: false });
|
|
175
|
+
if (!stat)
|
|
176
|
+
return { fingerprint: 'missing' };
|
|
177
|
+
if (stat.isSymbolicLink()) {
|
|
178
|
+
const link = readlinkSync(file);
|
|
179
|
+
return { fingerprint: 'link:' + link, link };
|
|
180
|
+
}
|
|
181
|
+
if (!stat.isFile())
|
|
182
|
+
return { fingerprint: 'other' };
|
|
183
|
+
const content = readFileSync(file);
|
|
184
|
+
return { fingerprint: `file:${stat.mode & 0o777}:${createHash('sha256').update(content).digest('hex')}`, content, mode: stat.mode & 0o777 };
|
|
185
|
+
}
|
|
186
|
+
export function captureOutOfScope(context, change) {
|
|
187
|
+
const scoped = context.repositories.filter(repository => repository.scope?.length);
|
|
188
|
+
if (!scoped.length)
|
|
189
|
+
return { change, repositories: [] };
|
|
190
|
+
const bases = changeBases(context);
|
|
191
|
+
let budget = 0;
|
|
192
|
+
return {
|
|
193
|
+
change,
|
|
194
|
+
repositories: scoped.map(repository => {
|
|
195
|
+
const base = bases[repository.id];
|
|
196
|
+
const before = new Map();
|
|
197
|
+
for (const file of outOfScope(repository, repositoryChanges(context, repository, base, change))) {
|
|
198
|
+
const { content, ...saved } = fingerprintOf(path.join(repository.path, file.path));
|
|
199
|
+
const keep = content && content.length <= RESTORE_FILE_LIMIT && budget + content.length <= RESTORE_TOTAL_LIMIT;
|
|
200
|
+
if (keep)
|
|
201
|
+
budget += content.length;
|
|
202
|
+
before.set(file.path, keep ? { ...saved, content } : saved);
|
|
203
|
+
}
|
|
204
|
+
return { id: repository.id, base, before };
|
|
205
|
+
}),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function restoreFromBase(repository, base, files) {
|
|
209
|
+
const restored = [];
|
|
210
|
+
for (let i = 0; i < files.length; i += 100) {
|
|
211
|
+
const batch = files.slice(i, i + 100);
|
|
212
|
+
const tracked = base === EMPTY_TREE ? new Set() : new Set(git(repository.path, ['ls-tree', '-r', '-z', '--name-only', '--full-tree', base, '--', ...batch.map(file => file.replace(/\/$/, ''))]).stdout.split('\0').filter(Boolean));
|
|
213
|
+
const existing = batch.filter(file => tracked.has(file));
|
|
214
|
+
if (existing.length)
|
|
215
|
+
git(repository.path, ['restore', '--source=' + base, '--staged', '--worktree', '--', ...existing]);
|
|
216
|
+
const added = batch.filter(file => !tracked.has(file));
|
|
217
|
+
if (added.length)
|
|
218
|
+
git(repository.path, ['rm', '-r', '-q', '--cached', '--ignore-unmatch', '--', ...added.map(file => file.replace(/\/$/, ''))], true);
|
|
219
|
+
for (const file of added)
|
|
220
|
+
rmSync(path.join(repository.path, file), { recursive: true, force: true });
|
|
221
|
+
restored.push(...existing.map(file => ({ repositoryId: repository.id, path: file, restored: 'base' })), ...added.map(file => ({ repositoryId: repository.id, path: file.replace(/\/$/, ''), restored: 'removed' })));
|
|
222
|
+
}
|
|
223
|
+
return restored;
|
|
224
|
+
}
|
|
225
|
+
function restorePrevious(repository, file, saved) {
|
|
226
|
+
const target = path.join(repository.path, file);
|
|
227
|
+
rmSync(target, { recursive: true, force: true });
|
|
228
|
+
if (saved.fingerprint === 'missing')
|
|
229
|
+
return;
|
|
230
|
+
mkdirSync(path.dirname(target), { recursive: true });
|
|
231
|
+
if (saved.link !== undefined)
|
|
232
|
+
symlinkSync(saved.link, target);
|
|
233
|
+
else
|
|
234
|
+
writeFileSync(target, saved.content, { mode: saved.mode ?? 0o644 });
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Undoes every out-of-scope edit made since `guard` was captured. A path the
|
|
238
|
+
* turn changed outside the scope returns to its state before the turn: its
|
|
239
|
+
* base content, its earlier out-of-scope content, or absence. In-scope work,
|
|
240
|
+
* ignored files and out-of-scope state that predates the turn stay untouched.
|
|
241
|
+
*/
|
|
242
|
+
export function discardOutOfScopeEdits(context, guard) {
|
|
243
|
+
const discarded = [];
|
|
244
|
+
for (const entry of guard.repositories) {
|
|
245
|
+
const repository = context.repositories.find(repo => repo.id === entry.id);
|
|
246
|
+
const now = outOfScope(repository, repositoryChanges(context, repository, entry.base, guard.change)).map(file => file.path);
|
|
247
|
+
const changedNow = new Set(now);
|
|
248
|
+
// A tracked file the turn returned to its base content leaves the change smaller: that clean-up stays.
|
|
249
|
+
const settled = [...entry.before.keys()].filter(file => !changedNow.has(file));
|
|
250
|
+
const tracked = settled.length && entry.base !== EMPTY_TREE ? new Set(git(repository.path, ['ls-tree', '-r', '-z', '--name-only', '--full-tree', entry.base, '--', ...settled]).stdout.split('\0').filter(Boolean)) : new Set();
|
|
251
|
+
const toBase = [];
|
|
252
|
+
for (const file of new Set([...now, ...entry.before.keys()])) {
|
|
253
|
+
const saved = entry.before.get(file);
|
|
254
|
+
if (!saved) {
|
|
255
|
+
toBase.push(file);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (saved.fingerprint === fingerprintOf(path.join(repository.path, file)).fingerprint)
|
|
259
|
+
continue;
|
|
260
|
+
if (!changedNow.has(file) && tracked.has(file))
|
|
261
|
+
continue;
|
|
262
|
+
if (saved.fingerprint === 'missing' || saved.link !== undefined || saved.content) {
|
|
263
|
+
restorePrevious(repository, file, saved);
|
|
264
|
+
discarded.push({ repositoryId: repository.id, path: file, restored: 'previous' });
|
|
265
|
+
}
|
|
266
|
+
else
|
|
267
|
+
toBase.push(file);
|
|
268
|
+
}
|
|
269
|
+
discarded.push(...restoreFromBase(repository, entry.base, toBase));
|
|
270
|
+
}
|
|
271
|
+
return discarded.sort((a, b) => a.repositoryId.localeCompare(b.repositoryId) || a.path.localeCompare(b.path));
|
|
272
|
+
}
|
|
273
|
+
/** Bounded prompt lines for a change set; repository ids prefix the paths only when several repositories are in scope. */
|
|
274
|
+
export function renderChangeSet(sets, limit = 150) {
|
|
275
|
+
const multiple = sets.length > 1;
|
|
276
|
+
const lines = [];
|
|
277
|
+
let hidden = 0;
|
|
278
|
+
for (const set of sets) {
|
|
279
|
+
for (const file of set.files) {
|
|
280
|
+
if (lines.length >= limit) {
|
|
281
|
+
hidden++;
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
lines.push(`- ${multiple ? '`' + set.repositoryId + '` ' : ''}\`${file.path}\` (${file.status})`);
|
|
285
|
+
}
|
|
286
|
+
if (set.truncated)
|
|
287
|
+
hidden++;
|
|
288
|
+
}
|
|
289
|
+
if (hidden)
|
|
290
|
+
lines.push(`- … ${hidden}${sets.some(set => set.truncated) ? '+' : ''} more not listed; compare against the base with git to see them.`);
|
|
291
|
+
return lines;
|
|
292
|
+
}
|
|
293
|
+
/** One human line naming discarded edits, bounded. */
|
|
294
|
+
export function describeDiscarded(edits, multiple, limit = 12) {
|
|
295
|
+
const names = edits.map(edit => (multiple ? edit.repositoryId + ':' : '') + edit.path);
|
|
296
|
+
return names.slice(0, limit).join(', ') + (names.length > limit ? ` and ${names.length - limit} more` : '');
|
|
297
|
+
}
|
|
@@ -7,7 +7,7 @@ import { existsSync, readFileSync, mkdtempSync, rmSync, writeFileSync } from 'no
|
|
|
7
7
|
import { tmpdir } from 'node:os';
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { sumCacheUsage } from './efficiency-types.js';
|
|
10
|
-
import { normalizeKimiCliModel } from '
|
|
10
|
+
import { normalizeKimiCliModel } from './kimi-model.js';
|
|
11
11
|
import { AgentExecutionError, unknownUsage, validateAgentRequest } from './executor-types.js';
|
|
12
12
|
import { runCliProcess } from './cli-process.js';
|
|
13
13
|
import { canonicalWorkspace } from './workspace-tools.js';
|
|
@@ -409,4 +409,3 @@ export class CliExecutor {
|
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
411
|
}
|
|
412
|
-
//# sourceMappingURL=cli-executor.js.map
|
|
@@ -5,8 +5,8 @@ import { rolePromptDefaults } from './prompts.js';
|
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { pathToFileURL } from 'node:url';
|
|
8
|
-
import { parseArgs } from '../
|
|
9
|
-
import { readVerificationEvidence, inspectPipeline, pipelineStateDirectory, validatePipelineContext } from '../
|
|
8
|
+
import { parseArgs } from '../shared/args.js';
|
|
9
|
+
import { readVerificationEvidence, inspectPipeline, pipelineStateDirectory, validatePipelineContext } from '../pipeline/pipeline-state.js';
|
|
10
10
|
import { normalizeRuntimeConfig, validateRuntimeConfig } from './config.js';
|
|
11
11
|
import { CORE_PACKAGE_VERSION, CORE_WORKFLOW_VERSION, RUNTIME_API_VERSION, coreRuntimeIdentity, preflightCoreWorkflow, runCoreWorkflow } from './core-host.js';
|
|
12
12
|
import { sameRuntimeIdentity } from './runtime-identity.js';
|
|
@@ -88,7 +88,7 @@ function invocationUsage(state, priorCount) {
|
|
|
88
88
|
return { costUsd: sum('costUsd'), inputTokens: sum('inputTokens'), outputTokens: sum('outputTokens') };
|
|
89
89
|
}
|
|
90
90
|
export async function runRuntimeCommand(flags, positionals, emit = value => process.stdout.write(JSON.stringify(value) + '\n')) {
|
|
91
|
-
const command = positionals[0] ?? 'help';
|
|
91
|
+
const command = flags.help === true ? 'help' : positionals[0] ?? 'help';
|
|
92
92
|
if (command === 'prompts') {
|
|
93
93
|
emit({ type: 'runtime-role-prompts', defaults: rolePromptDefaults() });
|
|
94
94
|
return 0;
|
|
@@ -126,7 +126,7 @@ export async function runRuntimeCommand(flags, positionals, emit = value => proc
|
|
|
126
126
|
return 0;
|
|
127
127
|
}
|
|
128
128
|
if (command === 'api') {
|
|
129
|
-
emit({ type: 'runtime-api', apiVersion: RUNTIME_API_VERSION, coreVersion: CORE_PACKAGE_VERSION, runtimeIdentity: coreRuntimeIdentity(), workflowVersions: [CORE_WORKFLOW_VERSION], capabilities: { scopedRecovery: 1, efficientRoleExecution: 1, reproducibleVerification: 1, implementationEfficiencyMetrics: 1, compactAgentLoop: 1, configurableGuardrails: 1, compactOutputBudget: 1, roleThinkingControl: 1 }, guardrails: GUARDRAIL_CATALOG });
|
|
129
|
+
emit({ type: 'runtime-api', apiVersion: RUNTIME_API_VERSION, coreVersion: CORE_PACKAGE_VERSION, runtimeIdentity: coreRuntimeIdentity(), workflowVersions: [CORE_WORKFLOW_VERSION], capabilities: { scopedRecovery: 1, efficientRoleExecution: 1, reproducibleVerification: 1, implementationEfficiencyMetrics: 1, compactAgentLoop: 1, configurableGuardrails: 1, compactOutputBudget: 1, roleThinkingControl: 1, repositoryScope: 1 }, guardrails: GUARDRAIL_CATALOG });
|
|
130
130
|
return 0;
|
|
131
131
|
}
|
|
132
132
|
if (command === 'validate') {
|
|
@@ -241,4 +241,3 @@ if (process.argv[1] && existsSync(process.argv[1]) && import.meta.url === pathTo
|
|
|
241
241
|
process.exitCode = 1;
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
|
-
//# sourceMappingURL=cli.js.map
|
|
@@ -28,4 +28,3 @@ export function restoreOptionalFields(value, schema) {
|
|
|
28
28
|
return Object.fromEntries(Object.entries(value).filter(([key, item]) => !(key in properties && item === null && !required.has(key)))
|
|
29
29
|
.map(([key, item]) => [key, properties[key] ? restoreOptionalFields(item, properties[key]) : item]));
|
|
30
30
|
}
|
|
31
|
-
//# sourceMappingURL=codex-schema.js.map
|
|
@@ -2,38 +2,7 @@ import type { AgentResult } from '../executor-types.js';
|
|
|
2
2
|
import { type CompactEnv } from './step.js';
|
|
3
3
|
/** The load-bearing tokens of a criterion: identifiers (`createGame`, `applyInput`, `tick`), numbers and hyphenated terms — never prose words. */
|
|
4
4
|
export declare function criterionTokens(text: string): string[];
|
|
5
|
-
|
|
6
|
-
greenfield: boolean;
|
|
7
|
-
languages: string[];
|
|
8
|
-
frameworks: string[];
|
|
9
|
-
keyFiles: string[];
|
|
10
|
-
tests: string[];
|
|
11
|
-
notes: string;
|
|
12
|
-
}
|
|
13
|
-
export interface Proposal {
|
|
14
|
-
why: string;
|
|
15
|
-
whatChanges: string[];
|
|
16
|
-
capabilities: {
|
|
17
|
-
new: string[];
|
|
18
|
-
modified: string[];
|
|
19
|
-
};
|
|
20
|
-
impact: string[];
|
|
21
|
-
}
|
|
22
|
-
export interface Design {
|
|
23
|
-
context: string;
|
|
24
|
-
goals: string[];
|
|
25
|
-
nonGoals: string[];
|
|
26
|
-
decisions: {
|
|
27
|
-
title: string;
|
|
28
|
-
choice: string;
|
|
29
|
-
why: string;
|
|
30
|
-
}[];
|
|
31
|
-
risks: {
|
|
32
|
-
risk: string;
|
|
33
|
-
mitigation: string;
|
|
34
|
-
}[];
|
|
35
|
-
}
|
|
36
|
-
export interface Spec {
|
|
5
|
+
interface Spec {
|
|
37
6
|
name: string;
|
|
38
7
|
requirements: {
|
|
39
8
|
name: string;
|
|
@@ -45,7 +14,7 @@ export interface Spec {
|
|
|
45
14
|
}[];
|
|
46
15
|
}[];
|
|
47
16
|
}
|
|
48
|
-
|
|
17
|
+
interface Tasks {
|
|
49
18
|
groups: {
|
|
50
19
|
title: string;
|
|
51
20
|
tasks: string[];
|
|
@@ -57,245 +26,6 @@ export interface Tasks {
|
|
|
57
26
|
}[];
|
|
58
27
|
blockingQuestion?: string;
|
|
59
28
|
}
|
|
60
|
-
export declare const INVENTORY_SCHEMA: {
|
|
61
|
-
type: string;
|
|
62
|
-
additionalProperties: boolean;
|
|
63
|
-
required: string[];
|
|
64
|
-
properties: {
|
|
65
|
-
greenfield: {
|
|
66
|
-
type: string;
|
|
67
|
-
};
|
|
68
|
-
languages: {
|
|
69
|
-
type: string;
|
|
70
|
-
items: {
|
|
71
|
-
type: string;
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
|
-
frameworks: {
|
|
75
|
-
type: string;
|
|
76
|
-
items: {
|
|
77
|
-
type: string;
|
|
78
|
-
};
|
|
79
|
-
};
|
|
80
|
-
keyFiles: {
|
|
81
|
-
type: string;
|
|
82
|
-
items: {
|
|
83
|
-
type: string;
|
|
84
|
-
};
|
|
85
|
-
};
|
|
86
|
-
tests: {
|
|
87
|
-
type: string;
|
|
88
|
-
items: {
|
|
89
|
-
type: string;
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
notes: {
|
|
93
|
-
type: string;
|
|
94
|
-
};
|
|
95
|
-
};
|
|
96
|
-
};
|
|
97
|
-
export declare const PROPOSAL_SCHEMA: {
|
|
98
|
-
type: string;
|
|
99
|
-
additionalProperties: boolean;
|
|
100
|
-
required: string[];
|
|
101
|
-
properties: {
|
|
102
|
-
why: {
|
|
103
|
-
type: string;
|
|
104
|
-
};
|
|
105
|
-
whatChanges: {
|
|
106
|
-
type: string;
|
|
107
|
-
items: {
|
|
108
|
-
type: string;
|
|
109
|
-
};
|
|
110
|
-
};
|
|
111
|
-
capabilities: {
|
|
112
|
-
type: string;
|
|
113
|
-
additionalProperties: boolean;
|
|
114
|
-
required: string[];
|
|
115
|
-
properties: {
|
|
116
|
-
new: {
|
|
117
|
-
type: string;
|
|
118
|
-
items: {
|
|
119
|
-
type: string;
|
|
120
|
-
};
|
|
121
|
-
};
|
|
122
|
-
modified: {
|
|
123
|
-
type: string;
|
|
124
|
-
items: {
|
|
125
|
-
type: string;
|
|
126
|
-
};
|
|
127
|
-
};
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
impact: {
|
|
131
|
-
type: string;
|
|
132
|
-
items: {
|
|
133
|
-
type: string;
|
|
134
|
-
};
|
|
135
|
-
};
|
|
136
|
-
};
|
|
137
|
-
};
|
|
138
|
-
export declare const DESIGN_SCHEMA: {
|
|
139
|
-
type: string;
|
|
140
|
-
additionalProperties: boolean;
|
|
141
|
-
required: string[];
|
|
142
|
-
properties: {
|
|
143
|
-
context: {
|
|
144
|
-
type: string;
|
|
145
|
-
};
|
|
146
|
-
goals: {
|
|
147
|
-
type: string;
|
|
148
|
-
items: {
|
|
149
|
-
type: string;
|
|
150
|
-
};
|
|
151
|
-
};
|
|
152
|
-
nonGoals: {
|
|
153
|
-
type: string;
|
|
154
|
-
items: {
|
|
155
|
-
type: string;
|
|
156
|
-
};
|
|
157
|
-
};
|
|
158
|
-
decisions: {
|
|
159
|
-
type: string;
|
|
160
|
-
items: {
|
|
161
|
-
type: string;
|
|
162
|
-
additionalProperties: boolean;
|
|
163
|
-
required: string[];
|
|
164
|
-
properties: {
|
|
165
|
-
title: {
|
|
166
|
-
type: string;
|
|
167
|
-
};
|
|
168
|
-
choice: {
|
|
169
|
-
type: string;
|
|
170
|
-
};
|
|
171
|
-
why: {
|
|
172
|
-
type: string;
|
|
173
|
-
};
|
|
174
|
-
};
|
|
175
|
-
};
|
|
176
|
-
};
|
|
177
|
-
risks: {
|
|
178
|
-
type: string;
|
|
179
|
-
items: {
|
|
180
|
-
type: string;
|
|
181
|
-
additionalProperties: boolean;
|
|
182
|
-
required: string[];
|
|
183
|
-
properties: {
|
|
184
|
-
risk: {
|
|
185
|
-
type: string;
|
|
186
|
-
};
|
|
187
|
-
mitigation: {
|
|
188
|
-
type: string;
|
|
189
|
-
};
|
|
190
|
-
};
|
|
191
|
-
};
|
|
192
|
-
};
|
|
193
|
-
};
|
|
194
|
-
};
|
|
195
|
-
export declare const SPEC_SCHEMA: {
|
|
196
|
-
type: string;
|
|
197
|
-
additionalProperties: boolean;
|
|
198
|
-
required: string[];
|
|
199
|
-
properties: {
|
|
200
|
-
name: {
|
|
201
|
-
type: string;
|
|
202
|
-
};
|
|
203
|
-
requirements: {
|
|
204
|
-
type: string;
|
|
205
|
-
items: {
|
|
206
|
-
type: string;
|
|
207
|
-
additionalProperties: boolean;
|
|
208
|
-
required: string[];
|
|
209
|
-
properties: {
|
|
210
|
-
name: {
|
|
211
|
-
type: string;
|
|
212
|
-
};
|
|
213
|
-
text: {
|
|
214
|
-
type: string;
|
|
215
|
-
};
|
|
216
|
-
scenarios: {
|
|
217
|
-
type: string;
|
|
218
|
-
items: {
|
|
219
|
-
type: string;
|
|
220
|
-
additionalProperties: boolean;
|
|
221
|
-
required: string[];
|
|
222
|
-
properties: {
|
|
223
|
-
name: {
|
|
224
|
-
type: string;
|
|
225
|
-
};
|
|
226
|
-
when: {
|
|
227
|
-
type: string;
|
|
228
|
-
};
|
|
229
|
-
then: {
|
|
230
|
-
type: string;
|
|
231
|
-
};
|
|
232
|
-
};
|
|
233
|
-
};
|
|
234
|
-
};
|
|
235
|
-
};
|
|
236
|
-
};
|
|
237
|
-
};
|
|
238
|
-
};
|
|
239
|
-
};
|
|
240
|
-
export declare const TASKS_SCHEMA: {
|
|
241
|
-
type: string;
|
|
242
|
-
additionalProperties: boolean;
|
|
243
|
-
required: string[];
|
|
244
|
-
properties: {
|
|
245
|
-
groups: {
|
|
246
|
-
type: string;
|
|
247
|
-
items: {
|
|
248
|
-
type: string;
|
|
249
|
-
additionalProperties: boolean;
|
|
250
|
-
required: string[];
|
|
251
|
-
properties: {
|
|
252
|
-
title: {
|
|
253
|
-
type: string;
|
|
254
|
-
};
|
|
255
|
-
tasks: {
|
|
256
|
-
type: string;
|
|
257
|
-
items: {
|
|
258
|
-
type: string;
|
|
259
|
-
};
|
|
260
|
-
};
|
|
261
|
-
};
|
|
262
|
-
};
|
|
263
|
-
};
|
|
264
|
-
verification: {
|
|
265
|
-
type: string;
|
|
266
|
-
items: {
|
|
267
|
-
type: string;
|
|
268
|
-
additionalProperties: boolean;
|
|
269
|
-
required: string[];
|
|
270
|
-
properties: {
|
|
271
|
-
repositoryId: {
|
|
272
|
-
type: string;
|
|
273
|
-
};
|
|
274
|
-
command: {
|
|
275
|
-
type: string;
|
|
276
|
-
};
|
|
277
|
-
args: {
|
|
278
|
-
type: string;
|
|
279
|
-
items: {
|
|
280
|
-
type: string;
|
|
281
|
-
};
|
|
282
|
-
};
|
|
283
|
-
};
|
|
284
|
-
};
|
|
285
|
-
};
|
|
286
|
-
blockingQuestion: {
|
|
287
|
-
type: string;
|
|
288
|
-
};
|
|
289
|
-
};
|
|
290
|
-
};
|
|
291
|
-
/** True when no repository holds anything but OpenSpec artifacts and repository boilerplate. */
|
|
292
|
-
export declare function hostGreenfield(roots: string[]): boolean;
|
|
293
|
-
/** Rendered with the exact headings `openspec instructions proposal` returns. */
|
|
294
|
-
export declare function renderProposal(proposal: Proposal, capabilityNames: {
|
|
295
|
-
new: string[];
|
|
296
|
-
modified: string[];
|
|
297
|
-
}): string;
|
|
298
|
-
export declare function renderDesign(design: Design, greenfield: boolean): string;
|
|
299
29
|
/** True when any media/font file exists under the roots (bounded walk, dot/dependency dirs skipped). */
|
|
300
30
|
export declare function hasBinaryAssets(roots: readonly string[], limit?: number): boolean;
|
|
301
31
|
/**
|
|
@@ -347,3 +77,4 @@ export declare function normalizeTasksForTest(raw: Record<string, unknown>, repo
|
|
|
347
77
|
* the graph's participation and completeness checks pass unchanged.
|
|
348
78
|
*/
|
|
349
79
|
export declare function runCompactArchitect(env: CompactEnv): Promise<AgentResult>;
|
|
80
|
+
export {};
|