specrails-core 5.2.3 → 5.4.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 +3 -0
- package/bin/specrails-core.mjs +5 -0
- package/dist/agent-runtime/capabilities.d.ts +27 -0
- package/dist/agent-runtime/capabilities.js +73 -0
- package/dist/agent-runtime/capabilities.js.map +1 -0
- package/dist/agent-runtime/cli-executor.d.ts +43 -0
- package/dist/agent-runtime/cli-executor.js +405 -0
- package/dist/agent-runtime/cli-executor.js.map +1 -0
- package/dist/agent-runtime/cli-process.d.ts +32 -0
- package/dist/agent-runtime/cli-process.js +159 -0
- package/dist/agent-runtime/cli-process.js.map +1 -0
- package/dist/agent-runtime/cli.d.ts +39 -0
- package/dist/agent-runtime/cli.js +216 -0
- package/dist/agent-runtime/cli.js.map +1 -0
- package/dist/agent-runtime/codex-schema.d.ts +4 -0
- package/dist/agent-runtime/codex-schema.js +31 -0
- package/dist/agent-runtime/codex-schema.js.map +1 -0
- package/dist/agent-runtime/config.d.ts +11 -0
- package/dist/agent-runtime/config.js +263 -0
- package/dist/agent-runtime/config.js.map +1 -0
- package/dist/agent-runtime/core-host.d.ts +41 -0
- package/dist/agent-runtime/core-host.js +132 -0
- package/dist/agent-runtime/core-host.js.map +1 -0
- package/dist/agent-runtime/durable-store.d.ts +22 -0
- package/dist/agent-runtime/durable-store.js +205 -0
- package/dist/agent-runtime/durable-store.js.map +1 -0
- package/dist/agent-runtime/efficiency-summary.d.ts +67 -0
- package/dist/agent-runtime/efficiency-summary.js +52 -0
- package/dist/agent-runtime/efficiency-summary.js.map +1 -0
- package/dist/agent-runtime/efficiency-types.d.ts +60 -0
- package/dist/agent-runtime/efficiency-types.js +8 -0
- package/dist/agent-runtime/efficiency-types.js.map +1 -0
- package/dist/agent-runtime/efficiency.d.ts +5 -0
- package/dist/agent-runtime/efficiency.js +35 -0
- package/dist/agent-runtime/efficiency.js.map +1 -0
- package/dist/agent-runtime/evaluation-corpus.d.ts +13 -0
- package/dist/agent-runtime/evaluation-corpus.js +8 -0
- package/dist/agent-runtime/evaluation-corpus.js.map +1 -0
- package/dist/agent-runtime/evaluation.d.ts +43 -0
- package/dist/agent-runtime/evaluation.js +171 -0
- package/dist/agent-runtime/evaluation.js.map +1 -0
- package/dist/agent-runtime/executor-types.d.ts +125 -0
- package/dist/agent-runtime/executor-types.js +29 -0
- package/dist/agent-runtime/executor-types.js.map +1 -0
- package/dist/agent-runtime/executors.d.ts +23 -0
- package/dist/agent-runtime/executors.js +48 -0
- package/dist/agent-runtime/executors.js.map +1 -0
- package/dist/agent-runtime/gemini-policy.d.ts +8 -0
- package/dist/agent-runtime/gemini-policy.js +36 -0
- package/dist/agent-runtime/gemini-policy.js.map +1 -0
- package/dist/agent-runtime/graph/artifacts.d.ts +26 -0
- package/dist/agent-runtime/graph/artifacts.js +205 -0
- package/dist/agent-runtime/graph/artifacts.js.map +1 -0
- package/dist/agent-runtime/graph/nodes.d.ts +39 -0
- package/dist/agent-runtime/graph/nodes.js +321 -0
- package/dist/agent-runtime/graph/nodes.js.map +1 -0
- package/dist/agent-runtime/graph/review-policy.d.ts +18 -0
- package/dist/agent-runtime/graph/review-policy.js +32 -0
- package/dist/agent-runtime/graph/review-policy.js.map +1 -0
- package/dist/agent-runtime/graph/roles.d.ts +47 -0
- package/dist/agent-runtime/graph/roles.js +190 -0
- package/dist/agent-runtime/graph/roles.js.map +1 -0
- package/dist/agent-runtime/graph/state.d.ts +83 -0
- package/dist/agent-runtime/graph/state.js +23 -0
- package/dist/agent-runtime/graph/state.js.map +1 -0
- package/dist/agent-runtime/graph-checkpointer.d.ts +61 -0
- package/dist/agent-runtime/graph-checkpointer.js +137 -0
- package/dist/agent-runtime/graph-checkpointer.js.map +1 -0
- package/dist/agent-runtime/index.d.ts +20 -0
- package/dist/agent-runtime/index.js +21 -0
- package/dist/agent-runtime/index.js.map +1 -0
- package/dist/agent-runtime/kimi-acp.d.ts +11 -0
- package/dist/agent-runtime/kimi-acp.js +190 -0
- package/dist/agent-runtime/kimi-acp.js.map +1 -0
- package/dist/agent-runtime/openai-executor.d.ts +26 -0
- package/dist/agent-runtime/openai-executor.js +192 -0
- package/dist/agent-runtime/openai-executor.js.map +1 -0
- package/dist/agent-runtime/openspec-tool-server.d.ts +1 -0
- package/dist/agent-runtime/openspec-tool-server.js +37 -0
- package/dist/agent-runtime/openspec-tool-server.js.map +1 -0
- package/dist/agent-runtime/openspec.d.ts +123 -0
- package/dist/agent-runtime/openspec.js +263 -0
- package/dist/agent-runtime/openspec.js.map +1 -0
- package/dist/agent-runtime/prompts.d.ts +44 -0
- package/dist/agent-runtime/prompts.js +310 -0
- package/dist/agent-runtime/prompts.js.map +1 -0
- package/dist/agent-runtime/provider-diagnostic.d.ts +2 -0
- package/dist/agent-runtime/provider-diagnostic.js +25 -0
- package/dist/agent-runtime/provider-diagnostic.js.map +1 -0
- package/dist/agent-runtime/repository-context.d.ts +25 -0
- package/dist/agent-runtime/repository-context.js +100 -0
- package/dist/agent-runtime/repository-context.js.map +1 -0
- package/dist/agent-runtime/review-context.d.ts +14 -0
- package/dist/agent-runtime/review-context.js +41 -0
- package/dist/agent-runtime/review-context.js.map +1 -0
- package/dist/agent-runtime/role-routing.d.ts +10 -0
- package/dist/agent-runtime/role-routing.js +29 -0
- package/dist/agent-runtime/role-routing.js.map +1 -0
- package/dist/agent-runtime/role-state.d.ts +19 -0
- package/dist/agent-runtime/role-state.js +24 -0
- package/dist/agent-runtime/role-state.js.map +1 -0
- package/dist/agent-runtime/runtime-identity.d.ts +11 -0
- package/dist/agent-runtime/runtime-identity.js +33 -0
- package/dist/agent-runtime/runtime-identity.js.map +1 -0
- package/dist/agent-runtime/tool-event.d.ts +3 -0
- package/dist/agent-runtime/tool-event.js +24 -0
- package/dist/agent-runtime/tool-event.js.map +1 -0
- package/dist/agent-runtime/verification-plan.d.ts +55 -0
- package/dist/agent-runtime/verification-plan.js +206 -0
- package/dist/agent-runtime/verification-plan.js.map +1 -0
- package/dist/agent-runtime/workflow-types.d.ts +226 -0
- package/dist/agent-runtime/workflow-types.js +2 -0
- package/dist/agent-runtime/workflow-types.js.map +1 -0
- package/dist/agent-runtime/workflow.d.ts +17 -0
- package/dist/agent-runtime/workflow.js +636 -0
- package/dist/agent-runtime/workflow.js.map +1 -0
- package/dist/agent-runtime/workspace-tools.d.ts +29 -0
- package/dist/agent-runtime/workspace-tools.js +282 -0
- package/dist/agent-runtime/workspace-tools.js.map +1 -0
- package/dist/installer/cli.d.ts +35 -0
- package/dist/installer/cli.js +3 -0
- package/dist/installer/cli.js.map +1 -1
- package/dist/installer/commands/doctor.d.ts +27 -0
- package/dist/installer/commands/framework.d.ts +85 -0
- package/dist/installer/commands/init.d.ts +147 -0
- package/dist/installer/commands/update.d.ts +56 -0
- package/dist/installer/commands/v5-migration.d.ts +32 -0
- package/dist/installer/phases/framework-lifecycle.d.ts +53 -0
- package/dist/installer/phases/install-config.d.ts +64 -0
- package/dist/installer/phases/manifest.d.ts +45 -0
- package/dist/installer/phases/prereqs.d.ts +51 -0
- package/dist/installer/phases/provider-detect.d.ts +89 -0
- package/dist/installer/phases/scaffold.d.ts +211 -0
- package/dist/installer/phases/scaffold.js +39 -109
- package/dist/installer/phases/scaffold.js.map +1 -1
- package/dist/installer/runtime/kimi.d.ts +84 -0
- package/dist/installer/runtime/pipeline-state.d.ts +351 -0
- package/dist/installer/runtime/pipeline-state.js +514 -41
- package/dist/installer/runtime/pipeline-state.js.map +1 -1
- package/dist/installer/util/errors.d.ts +46 -0
- package/dist/installer/util/exec.d.ts +41 -0
- package/dist/installer/util/fs.d.ts +153 -0
- package/dist/installer/util/git.d.ts +44 -0
- package/dist/installer/util/install-transaction.d.ts +29 -0
- package/dist/installer/util/logger.d.ts +31 -0
- package/dist/installer/util/paths.d.ts +34 -0
- package/dist/installer/util/prompts.d.ts +23 -0
- package/dist/installer/util/registry.d.ts +174 -0
- package/dist/installer/util/template.d.ts +23 -0
- package/docs/README.md +1 -0
- package/docs/agent-runtime-efficiency.md +65 -0
- package/docs/agent-runtime.md +339 -0
- package/integration-contract.json +80 -7
- package/package.json +20 -2
- package/schemas/agent-runtime.schema.json +77 -0
- package/schemas/fixtures/runtime-efficiency-summary.v1.json +790 -0
- package/templates/codex-skills/batch-implement/SKILL.md +33 -58
- package/templates/codex-skills/implement/SKILL.md +21 -124
- package/templates/codex-skills/retry/SKILL.md +8 -34
- package/templates/commands/specrails/batch-implement.md +21 -16
- package/templates/commands/specrails/implement.md +17 -276
- package/templates/commands/specrails/retry.md +6 -34
- package/templates/gemini-commands/batch-implement.toml +34 -28
- package/templates/gemini-commands/implement.toml +34 -55
- package/templates/gemini-commands/retry.toml +10 -16
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { type Provider } from '../phases/install-config.js';
|
|
2
|
+
/**
|
|
3
|
+
* `npx specrails-core init` entry point.
|
|
4
|
+
*
|
|
5
|
+
* Flags consumed (must remain in sync with ALLOWED_FLAGS in
|
|
6
|
+
* bin/specrails-core.cjs until Phase 5):
|
|
7
|
+
* --root-dir <path> Target repo (default: cwd)
|
|
8
|
+
* --yes / -y Non-interactive; auto-init git + accept defaults
|
|
9
|
+
* --provider <name> Force provider (claude, codex, gemini, or kimi)
|
|
10
|
+
* --from-config [<p>] Read provider + agents from install-config.yaml
|
|
11
|
+
* --relocate Relocate artifacts to the $HOME workspace (symlinked
|
|
12
|
+
* from the bundled framework) instead of installing them
|
|
13
|
+
* IN-REPO. Default is in-repo so a standalone user's
|
|
14
|
+
* `claude`/`codex`/`gemini`/`kimi` finds its artifacts in
|
|
15
|
+
* their own repo. specrails-desktop pre-creates a registry
|
|
16
|
+
* entry (so it always relocates regardless of this flag);
|
|
17
|
+
* standalone users opt in with `--relocate` or
|
|
18
|
+
* `SPECRAILS_RELOCATE=1`.
|
|
19
|
+
*/
|
|
20
|
+
export interface InitFlags {
|
|
21
|
+
'root-dir'?: string | boolean;
|
|
22
|
+
yes?: boolean;
|
|
23
|
+
y?: boolean;
|
|
24
|
+
provider?: string | boolean;
|
|
25
|
+
'from-config'?: string | boolean;
|
|
26
|
+
relocate?: boolean;
|
|
27
|
+
'hub-json'?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface InitResult {
|
|
30
|
+
repoRoot: string;
|
|
31
|
+
provider: Provider;
|
|
32
|
+
}
|
|
33
|
+
export type WorkspaceProviderSelections = Partial<Record<Provider, string[]>>;
|
|
34
|
+
/**
|
|
35
|
+
* Snapshot the provider/role inventory exposed by one live workspace before a
|
|
36
|
+
* global framework version swap. This matters on Windows: directory junctions
|
|
37
|
+
* resolve their target when they are created, so a workspace link made through
|
|
38
|
+
* `framework/current` must be recreated after `current` moves. Keeping the
|
|
39
|
+
* exact visible `sr-*` set also avoids widening or narrowing a project's
|
|
40
|
+
* optional role selection during that refresh.
|
|
41
|
+
*/
|
|
42
|
+
export declare function snapshotWorkspaceProviderSelections(workspace: string): WorkspaceProviderSelections;
|
|
43
|
+
interface ReassembleWorkspaceProvidersInput {
|
|
44
|
+
workspace: string;
|
|
45
|
+
frameworkDir: string;
|
|
46
|
+
version: string;
|
|
47
|
+
codeRoot: string;
|
|
48
|
+
scriptDir: string;
|
|
49
|
+
selectedProvider: Provider;
|
|
50
|
+
selectedAgents?: string[];
|
|
51
|
+
previousSelections: WorkspaceProviderSelections;
|
|
52
|
+
copyStatics: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Refresh every provider already represented in the project plus the provider
|
|
56
|
+
* selected by the current operation. POSIX symlinks continue to follow
|
|
57
|
+
* `framework/current`; Windows junctions do not reliably preserve that
|
|
58
|
+
* indirection, so rebuilding all live links is required for true
|
|
59
|
+
* multi-provider version parity.
|
|
60
|
+
*/
|
|
61
|
+
export declare function reassembleWorkspaceProviders(input: ReassembleWorkspaceProvidersInput): Provider[];
|
|
62
|
+
/**
|
|
63
|
+
* Entry called by cli.ts. Returns a {@link InitResult} on success;
|
|
64
|
+
* throws a typed error (translated to an exit code by the outer CLI)
|
|
65
|
+
* on failure.
|
|
66
|
+
*/
|
|
67
|
+
export declare function runInit(flags: InitFlags): Promise<InitResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Warn (once per id) about `agents.selected` entries that have no shipped
|
|
70
|
+
* template — typically a pre-v5 install-config.yaml still listing removed
|
|
71
|
+
* agents. They are skipped at placement; the warning tells the user why and
|
|
72
|
+
* points at the v5 extension path.
|
|
73
|
+
*/
|
|
74
|
+
export declare function warnUnknownSelectedAgents(selected: string[] | undefined): void;
|
|
75
|
+
export interface EnsureFrameworkInput {
|
|
76
|
+
scriptDir: string;
|
|
77
|
+
frameworkDir: string;
|
|
78
|
+
provider: Provider;
|
|
79
|
+
providerDir: string;
|
|
80
|
+
version: string;
|
|
81
|
+
selectedAgents?: string[];
|
|
82
|
+
/**
|
|
83
|
+
* Additional providers that must remain available through the global
|
|
84
|
+
* `framework/current` pointer after this version transition.
|
|
85
|
+
*/
|
|
86
|
+
requiredProviders?: Provider[];
|
|
87
|
+
/** Registry home override used while computing the global provider union. */
|
|
88
|
+
registryHome?: string;
|
|
89
|
+
/**
|
|
90
|
+
* When false, MATERIALIZE the provider subtree but do NOT swap
|
|
91
|
+
* `<frameworkDir>/current` to point at `<version>`. The caller is responsible
|
|
92
|
+
* for the single `ensureCurrentSymlink(frameworkDir, version)` swap AFTER all
|
|
93
|
+
* providers have been materialized. This prevents a multi-provider install
|
|
94
|
+
* from leaving `current` pointed at a version dir that is missing a provider
|
|
95
|
+
* whose materialization later failed. Defaults to true (swap — the standalone
|
|
96
|
+
* single-provider `init` path is byte-identical to before).
|
|
97
|
+
*/
|
|
98
|
+
swapCurrent?: boolean;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Materialize the framework for `(version, provider)` if absent and (by default)
|
|
102
|
+
* point `<frameworkDir>/current` at that version. Idempotent — `installFramework`
|
|
103
|
+
* skips re-materialization when the providerDir already exists with a matching
|
|
104
|
+
* stamp, so a second project (or a repeat init) reuses the SAME framework copy.
|
|
105
|
+
* Shared by `runInit` and `runUpdate`.
|
|
106
|
+
*
|
|
107
|
+
* Pass `swapCurrent: false` to materialize WITHOUT swapping `current` — the
|
|
108
|
+
* multi-provider "materialize-all-then-swap-once" pattern desktop consumes:
|
|
109
|
+
* for (const p of providers) ensureFramework({ ..., provider: p, swapCurrent: false })
|
|
110
|
+
* ensureCurrentSymlink(frameworkDir, version) // single atomic swap at the end
|
|
111
|
+
*/
|
|
112
|
+
export declare function ensureFramework(input: EnsureFrameworkInput): void;
|
|
113
|
+
/**
|
|
114
|
+
* Resolve the `{bin, args}` to invoke `openspec init` for a project, honouring
|
|
115
|
+
* two optional env overrides (both default unset → `npx @fission-ai/openspec`):
|
|
116
|
+
*
|
|
117
|
+
* - `SPECRAILS_OPENSPEC_BIN` — path to the openspec CLI entry (a `.js` node
|
|
118
|
+
* script when bundled by the desktop app, OR a real executable in tests).
|
|
119
|
+
* - `SPECRAILS_OPENSPEC_NODE` — path to a node executable. Set ONLY by the
|
|
120
|
+
* desktop bundled-offline path: Tauri strips exec bits from bundled
|
|
121
|
+
* resources and the bundled openspec is a node CLI (not a runnable binary),
|
|
122
|
+
* so it must be invoked as `node <cli> init …` rather than executed directly.
|
|
123
|
+
*
|
|
124
|
+
* Three invocation forms:
|
|
125
|
+
* 1. NODE + BIN set → `runCommand(node, [cli, 'init', '--tools', provider, repoRoot])`
|
|
126
|
+
* (bundled offline — Tauri-stripped node CLI).
|
|
127
|
+
* 2. BIN set only → `runCommand(cli, ['init', '--tools', provider, repoRoot])`
|
|
128
|
+
* (a real executable: legacy override / test fake binary on PATH).
|
|
129
|
+
* 3. neither set → `runCommand('npx', ['--yes', '-p', '@fission-ai/openspec@<pinned>', '--', 'openspec', 'init', …])`
|
|
130
|
+
* (default online path — users never need a global install).
|
|
131
|
+
*/
|
|
132
|
+
export declare function buildOpenSpecInvocation(repoRoot: string, provider: Provider, env?: NodeJS.ProcessEnv, pinnedVersion?: string): {
|
|
133
|
+
bin: string;
|
|
134
|
+
args: string[];
|
|
135
|
+
};
|
|
136
|
+
export declare const KIMI_REQUIRED_OPENSPEC_SKILLS: readonly ["openspec-propose", "openspec-explore", "openspec-new-change", "openspec-continue-change", "openspec-apply-change", "openspec-ff-change", "openspec-sync-specs", "openspec-archive-change", "openspec-bulk-archive-change", "openspec-verify-change", "openspec-onboard"];
|
|
137
|
+
/**
|
|
138
|
+
* Move only OpenSpec-owned Kimi workflow directories from either upstream
|
|
139
|
+
* location into the artifact workspace. Every destination is copied to a
|
|
140
|
+
* sibling temporary directory and renamed, so readers never observe a partial
|
|
141
|
+
* skill. A distinct newly generated source refreshes the managed destination;
|
|
142
|
+
* an in-place corrected destination is retained as-is.
|
|
143
|
+
*/
|
|
144
|
+
export declare function normalizeKimiOpenSpecSkills(repoRoot: string, artifactRoot: string): string[];
|
|
145
|
+
export declare function normalizeGeminiOpenSpecSkills(repoRoot: string, artifactRoot: string): string[];
|
|
146
|
+
export declare function installOpenSpecProject(repoRoot: string, provider: Provider, artifactRoot?: string): Promise<void>;
|
|
147
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type Provider } from '../phases/provider-detect.js';
|
|
2
|
+
/**
|
|
3
|
+
* Components recognised by the `--only <component>` flag. Mirrors the
|
|
4
|
+
* retired bash installer's accepted values plus an explicit map of
|
|
5
|
+
* what each one actually does in the Node port.
|
|
6
|
+
*/
|
|
7
|
+
export type OnlyComponent = 'all' | 'core' | 'rules' | 'agents' | 'web-manager';
|
|
8
|
+
/**
|
|
9
|
+
* `npx specrails-core update` entry point.
|
|
10
|
+
*
|
|
11
|
+
* Re-runs the scaffolding layer so fresh templates overwrite the
|
|
12
|
+
* bundled commands and .specrails/setup-templates/ content. Reserved
|
|
13
|
+
* paths are respected by the shared isReservedPath gate inside
|
|
14
|
+
* fs utilities and scaffolding; the update never touches the user's
|
|
15
|
+
* profile JSON or custom-* agents.
|
|
16
|
+
*
|
|
17
|
+
* The retired update.sh computed a template-diff against the manifest
|
|
18
|
+
* and regenerated only changed files. We ship a simpler, stricter
|
|
19
|
+
* contract: always re-scaffold every specrails-managed artefact, then
|
|
20
|
+
* rewrite the manifest. The outcome is identical for the common case
|
|
21
|
+
* (upgrade bumps the core version → nearly every template changes)
|
|
22
|
+
* and is far easier to reason about than a bespoke diff algorithm.
|
|
23
|
+
*/
|
|
24
|
+
export interface UpdateFlags {
|
|
25
|
+
'root-dir'?: string | boolean;
|
|
26
|
+
only?: string | boolean;
|
|
27
|
+
'dry-run'?: boolean;
|
|
28
|
+
yes?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Force the provider to update. Without it, the provider is auto-detected
|
|
31
|
+
* from the existing install (`.claude` > `.codex` > `.gemini` > `.kimi-code`), which on a
|
|
32
|
+
* MULTI-PROVIDER workspace always picks `.claude` first — so codex/gemini/kimi
|
|
33
|
+
* could never be updated. specrails-desktop (and standalone users) pass
|
|
34
|
+
* `--provider <name>` to update one specific provider. Mirrors `init`.
|
|
35
|
+
*/
|
|
36
|
+
provider?: string | boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Relocate artifacts to the $HOME workspace (symlinked) instead of in-repo.
|
|
39
|
+
* Mirrors `init --relocate`: standalone updates resolve in-repo by default,
|
|
40
|
+
* desktop relocates (its registry entry already exists, so `allocate:false`
|
|
41
|
+
* still resolves the relocated entry). Also honoured via `SPECRAILS_RELOCATE=1`.
|
|
42
|
+
*/
|
|
43
|
+
relocate?: boolean;
|
|
44
|
+
}
|
|
45
|
+
export interface UpdateResult {
|
|
46
|
+
repoRoot: string;
|
|
47
|
+
previousVersion: string | null;
|
|
48
|
+
currentVersion: string;
|
|
49
|
+
provider: Provider;
|
|
50
|
+
dryRun: boolean;
|
|
51
|
+
/** Resolved scope of the update — what was actually re-applied. */
|
|
52
|
+
scope: OnlyComponent;
|
|
53
|
+
/** Framework version actually installed; partial updates retain the old version. */
|
|
54
|
+
installedVersion?: string | null;
|
|
55
|
+
}
|
|
56
|
+
export declare function runUpdate(flags: UpdateFlags): Promise<UpdateResult>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface V5MigrationInput {
|
|
2
|
+
/** Absolute artifact root (in-repo repoRoot, or the relocated $HOME workspace). */
|
|
3
|
+
artifactRoot: string;
|
|
4
|
+
/** Provider directory name (`.claude` / `.codex` / `.gemini`). */
|
|
5
|
+
providerDir: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Removes artefacts a pre-v5 install left behind so the fresh v5 template set
|
|
9
|
+
* places into a clean tree. Strictly subtractive and reserved-path-safe:
|
|
10
|
+
*
|
|
11
|
+
* - Removed agent files (`.claude/agents/sr-*.md`, `.gemini/agents/sr-*.md`)
|
|
12
|
+
* - Removed command files (`<providerDir>/commands/specrails/*.md`) and their
|
|
13
|
+
* codex skill dirs (`.codex/skills/<cmd>/`)
|
|
14
|
+
* - The generated top-level skills for removed commands (`.claude/skills/<id>/`)
|
|
15
|
+
* - Obsolete staging subtrees under `.specrails/setup-templates/`
|
|
16
|
+
* (`personas/`, `skills/enrich/`, and the removed command/agent templates)
|
|
17
|
+
* - VPC persona output dirs (`<providerDir>/agents/personas/`)
|
|
18
|
+
*
|
|
19
|
+
* `custom-*.md` agents and `.specrails/profiles/**` are protected by
|
|
20
|
+
* {@link isReservedPath}; files the installer never owned are not enumerated
|
|
21
|
+
* here, so they are untouched. When at least one path is removed a migration
|
|
22
|
+
* summary is printed so the user sees exactly what changed.
|
|
23
|
+
*/
|
|
24
|
+
export declare function migratePreV5Install(input: V5MigrationInput): void;
|
|
25
|
+
/**
|
|
26
|
+
* Test helper: enumerate removed agent/command ids so specs can assert the
|
|
27
|
+
* migration set stays in lock-step with the deleted templates.
|
|
28
|
+
*/
|
|
29
|
+
export declare const V5_REMOVED: {
|
|
30
|
+
readonly agents: readonly ["sr-product-manager", "sr-product-analyst", "sr-test-writer", "sr-doc-sync", "sr-merge-resolver", "sr-frontend-developer", "sr-backend-developer", "sr-frontend-reviewer", "sr-backend-reviewer", "sr-security-reviewer", "sr-performance-reviewer"];
|
|
31
|
+
readonly commands: readonly ["enrich", "reconfig", "vpc-drift", "auto-propose-backlog-specs", "get-backlog-specs", "merge-resolve", "test"];
|
|
32
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type Provider } from './provider-detect.js';
|
|
2
|
+
/**
|
|
3
|
+
* Stable provider order for the global framework store. `framework/current` is
|
|
4
|
+
* shared by every relocated workspace, so a version transition must carry
|
|
5
|
+
* forward every provider that can still have live links through that pointer.
|
|
6
|
+
*/
|
|
7
|
+
export declare const FRAMEWORK_PROVIDERS: readonly Provider[];
|
|
8
|
+
export interface ResolveRequiredFrameworkProvidersInput {
|
|
9
|
+
frameworkDir: string;
|
|
10
|
+
/** Providers requested by the lifecycle operation that is about to swap. */
|
|
11
|
+
requested?: readonly Provider[];
|
|
12
|
+
/** Registry home. Defaults to SPECRAILS_REGISTRY_HOME / the normal home. */
|
|
13
|
+
registryHome?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface MaterializeFrameworkVersionInput extends ResolveRequiredFrameworkProvidersInput {
|
|
16
|
+
scriptDir: string;
|
|
17
|
+
version: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Discover providers represented by a framework version.
|
|
21
|
+
*
|
|
22
|
+
* A provider is included when either its subtree or its stamp exists. For the
|
|
23
|
+
* current version this is deliberately conservative: an interrupted/legacy
|
|
24
|
+
* materialization without a stamp may still have live workspace symlinks, so
|
|
25
|
+
* the next version must carry that provider forward rather than dropping it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function discoverFrameworkProviders(frameworkDir: string, version: string): Provider[];
|
|
28
|
+
/**
|
|
29
|
+
* Compute the provider set that MUST exist in a destination version before the
|
|
30
|
+
* process may move the global `current` pointer:
|
|
31
|
+
*
|
|
32
|
+
* 1. providers requested by this operation;
|
|
33
|
+
* 2. every supported provider recorded by any project in registry.json;
|
|
34
|
+
* 3. every provider represented by the version currently serving workspaces.
|
|
35
|
+
*
|
|
36
|
+
* Taking the global registry union (not just the active project) is essential:
|
|
37
|
+
* `framework/current` is global, while provider inventories are per project.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveRequiredFrameworkProviders(input: ResolveRequiredFrameworkProvidersInput): Provider[];
|
|
40
|
+
/**
|
|
41
|
+
* Fail closed when a destination version is missing or only partially
|
|
42
|
+
* materialized. A valid provider requires BOTH its provider subtree and the
|
|
43
|
+
* final stamp written after scaffold completion, with matching version/provider
|
|
44
|
+
* fields. The caller may supply an empty requirement only for a first install;
|
|
45
|
+
* in that case at least one complete provider must be discoverable in target.
|
|
46
|
+
*/
|
|
47
|
+
export declare function assertFrameworkVersionComplete(frameworkDir: string, version: string, requiredProviders: readonly Provider[]): Provider[];
|
|
48
|
+
/**
|
|
49
|
+
* Materialize a complete destination version and expose it with ONE atomic
|
|
50
|
+
* pointer swap. No call in the provider loop can move `current`; if any provider
|
|
51
|
+
* fails, existing workspaces continue resolving through the previous version.
|
|
52
|
+
*/
|
|
53
|
+
export declare function materializeFrameworkVersion(input: MaterializeFrameworkVersionInput): Provider[];
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { InstallerError } from '../util/errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Provider identifier. Kept in lock-step with `provider-detect.ts` `Provider`.
|
|
4
|
+
*/
|
|
5
|
+
export type Provider = 'claude' | 'codex' | 'gemini' | 'kimi';
|
|
6
|
+
/** Cost / capability preset for the model picker. */
|
|
7
|
+
export type ModelPreset = 'balanced' | 'budget' | 'max';
|
|
8
|
+
/** Provider-native model selection retained verbatim in install-config.yaml. */
|
|
9
|
+
export interface InstallModelConfig {
|
|
10
|
+
preset: ModelPreset;
|
|
11
|
+
defaults: {
|
|
12
|
+
model: string;
|
|
13
|
+
};
|
|
14
|
+
overrides: Record<string, string>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Shape of the `.specrails/install-config.yaml` file — the single
|
|
18
|
+
* source of truth the TUI writes and the installer reads. Fields map
|
|
19
|
+
* 1:1 onto the grep-based parser in the retired install.sh.
|
|
20
|
+
*/
|
|
21
|
+
export interface InstallConfig {
|
|
22
|
+
version: 1;
|
|
23
|
+
provider: Provider;
|
|
24
|
+
agents: {
|
|
25
|
+
selected: string[];
|
|
26
|
+
excluded?: string[];
|
|
27
|
+
/** Legacy pre-models-section location, accepted for backward compatibility. */
|
|
28
|
+
preset?: ModelPreset;
|
|
29
|
+
};
|
|
30
|
+
models?: InstallModelConfig;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve a preset into provider-native identifiers. Kimi currently exposes no
|
|
34
|
+
* Core-defined cost/capability tier mapping, so every named preset resolves to
|
|
35
|
+
* its explicit `k3` default. User-supplied exact identifiers are handled later
|
|
36
|
+
* and are never interpreted as Claude aliases.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveProviderModelConfig(provider: Provider, preset?: ModelPreset): InstallModelConfig;
|
|
39
|
+
export declare class InvalidConfigError extends InstallerError {
|
|
40
|
+
readonly errors: string[];
|
|
41
|
+
constructor(errors: string[]);
|
|
42
|
+
}
|
|
43
|
+
export declare const CONFIG_RELATIVE_PATH = ".specrails/install-config.yaml";
|
|
44
|
+
/**
|
|
45
|
+
* Resolves the install-config path: explicit argument > repo-root default.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveConfigPath(repoRoot: string, explicit?: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Reads and parses the install-config. Returns `null` if the file is
|
|
50
|
+
* not present — caller decides whether that's an error or a fallback.
|
|
51
|
+
*/
|
|
52
|
+
export declare function loadInstallConfig(configPath: string): InstallConfig | null;
|
|
53
|
+
/**
|
|
54
|
+
* Validates an already-parsed YAML document. Collects every error
|
|
55
|
+
* before throwing so the user sees them all at once (matches the
|
|
56
|
+
* bash installer's `_config_errors` accumulator behaviour).
|
|
57
|
+
*/
|
|
58
|
+
export declare function validateInstallConfig(raw: unknown): InstallConfig;
|
|
59
|
+
/**
|
|
60
|
+
* Serialises an {@link InstallConfig} back to YAML and writes it with
|
|
61
|
+
* LF line endings. Used by `npx specrails-core update --reset-config`
|
|
62
|
+
* paths (not wired yet) and by tests.
|
|
63
|
+
*/
|
|
64
|
+
export declare function writeInstallConfig(configPath: string, config: InstallConfig): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape of the `.specrails/specrails-manifest.json` file the installer
|
|
3
|
+
* writes at install time. Consumers (specrails-desktop's compat check,
|
|
4
|
+
* the `doctor` command, update.sh) parse it to detect template drift.
|
|
5
|
+
*/
|
|
6
|
+
export interface SpecrailsManifest {
|
|
7
|
+
version: string;
|
|
8
|
+
installed_at: string;
|
|
9
|
+
/** Provider inventory is emitted only by provider-aware lifecycle callers. */
|
|
10
|
+
providers?: string[];
|
|
11
|
+
primary_provider?: string;
|
|
12
|
+
artifacts: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Computes a stable sha256 digest for a file, returned as `sha256:<hex>`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function sha256Of(filePath: string): string;
|
|
18
|
+
export interface BuildManifestInput {
|
|
19
|
+
/** Absolute path to the specrails-core source package directory. */
|
|
20
|
+
scriptDir: string;
|
|
21
|
+
/** Absolute path to the user's repo root where the manifest is written. */
|
|
22
|
+
repoRoot: string;
|
|
23
|
+
/** Version string from the specrails-core VERSION file. */
|
|
24
|
+
version: string;
|
|
25
|
+
/** Override "installed_at" — exposed for deterministic testing. */
|
|
26
|
+
installedAt?: string;
|
|
27
|
+
/** Provider(s) materialized by this lifecycle pass. Existing entries are unioned. */
|
|
28
|
+
providers?: string[];
|
|
29
|
+
primaryProvider?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Walks `templates/**` plus the bundled doctor command file and
|
|
33
|
+
* produces a stable-sorted manifest.
|
|
34
|
+
*
|
|
35
|
+
* Stable-sort rule: artifact keys are sorted ascending by POSIX path.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildManifest(input: BuildManifestInput): SpecrailsManifest;
|
|
38
|
+
/**
|
|
39
|
+
* Writes the manifest JSON and the companion version file under
|
|
40
|
+
* `.specrails/` in the user repo. Both files use LF terminators.
|
|
41
|
+
*/
|
|
42
|
+
export declare function writeManifestFiles(repoRoot: string, manifest: SpecrailsManifest): {
|
|
43
|
+
manifestPath: string;
|
|
44
|
+
versionPath: string;
|
|
45
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Provider, type ProviderAvailability } from './provider-detect.js';
|
|
2
|
+
/**
|
|
3
|
+
* OpenSpec 1.4.1, which the installer invokes during the default init/update
|
|
4
|
+
* flow, requires Node >=20.19.0. Keep this floor independent from Kimi's npm
|
|
5
|
+
* package requirement: SpecRails launches an externally installed Kimi CLI and
|
|
6
|
+
* does not require the Kimi npm distribution.
|
|
7
|
+
*/
|
|
8
|
+
export declare const MIN_NODE_VERSION = "20.19.0";
|
|
9
|
+
export declare function isSupportedNodeVersion(version: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Phase 1 prerequisite bundle. Mirrors install.sh's Phase 1 flow but
|
|
12
|
+
* with explicit options rather than a grab-bag of globals.
|
|
13
|
+
*
|
|
14
|
+
* Returns the resolved inputs later phases need — primarily the
|
|
15
|
+
* selected provider and the detected CLI availability.
|
|
16
|
+
*/
|
|
17
|
+
export interface PrereqOptions {
|
|
18
|
+
/** Absolute path to the target repository root. */
|
|
19
|
+
repoRoot: string;
|
|
20
|
+
/** --yes / -y equivalent — auto-init git, skip interactive prompts. */
|
|
21
|
+
autoYes: boolean;
|
|
22
|
+
/** Explicit --provider flag (if passed). */
|
|
23
|
+
explicitProvider?: Provider;
|
|
24
|
+
/** SPECRAILS_SKIP_PREREQS=1 equivalent — relax hard failures for CI. */
|
|
25
|
+
skipPrereqs: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface PrereqResult {
|
|
28
|
+
availability: ProviderAvailability;
|
|
29
|
+
provider: Provider;
|
|
30
|
+
/**
|
|
31
|
+
* OSS heuristics. Three signals must align for `isOss` to be true:
|
|
32
|
+
* a public GitHub repo (via `gh repo view`), at least one CI workflow
|
|
33
|
+
* file under `.github/workflows/`, and a `CONTRIBUTING.md` at the
|
|
34
|
+
* repo root or under `.github/`. Surfaced for downstream tooling that
|
|
35
|
+
* wants to tailor behaviour to open-source projects.
|
|
36
|
+
*/
|
|
37
|
+
ossSignals: OssSignals;
|
|
38
|
+
}
|
|
39
|
+
export interface OssSignals {
|
|
40
|
+
hasGh: boolean;
|
|
41
|
+
publicRepo: boolean;
|
|
42
|
+
hasCi: boolean;
|
|
43
|
+
hasContributing: boolean;
|
|
44
|
+
isOss: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Orchestrates every prerequisite check that must pass before the
|
|
48
|
+
* installer proceeds to Phase 3 (scaffolding). Emits ok/warn/info
|
|
49
|
+
* lines matching the retired bash output.
|
|
50
|
+
*/
|
|
51
|
+
export declare function checkPrerequisites(options: PrereqOptions): Promise<PrereqResult>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider detection + authentication checks. These mirror the Phase
|
|
3
|
+
* 1.2 / 1.3 branches of the retired install.sh.
|
|
4
|
+
*/
|
|
5
|
+
export type Provider = 'claude' | 'codex' | 'gemini' | 'kimi';
|
|
6
|
+
/** Oldest TypeScript Kimi Code CLI release covered by this integration. */
|
|
7
|
+
export declare const MIN_KIMI_VERSION = "0.27.0";
|
|
8
|
+
export interface ProviderAvailability {
|
|
9
|
+
claude: boolean;
|
|
10
|
+
codex: boolean;
|
|
11
|
+
/** Optional so callers/tests predating Gemini still typecheck; absent = false. */
|
|
12
|
+
gemini?: boolean;
|
|
13
|
+
/** Optional so callers/tests predating Kimi still typecheck; absent = false. */
|
|
14
|
+
kimi?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface ProviderDerivedPaths {
|
|
17
|
+
/** Root directory inside the user's repo: `.claude` / `.codex` / `.gemini` / `.kimi-code`. */
|
|
18
|
+
providerDir: string;
|
|
19
|
+
/** Instructions file relative to the artifact root. */
|
|
20
|
+
instructionsFile: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Detects which AI CLIs are on PATH. Runs `where` on Windows and
|
|
24
|
+
* `which` on POSIX via the cross-platform commandExists helper.
|
|
25
|
+
*/
|
|
26
|
+
export declare function detectAvailability(): Promise<ProviderAvailability>;
|
|
27
|
+
/**
|
|
28
|
+
* Returns the Claude CLI version string (stdout of `claude --version`)
|
|
29
|
+
* or 'unknown' if the CLI cannot be invoked.
|
|
30
|
+
*/
|
|
31
|
+
export declare function claudeVersion(): Promise<string>;
|
|
32
|
+
/** Returns the raw Kimi Code CLI version or `unknown` when it cannot be probed. */
|
|
33
|
+
export declare function kimiVersion(): Promise<string>;
|
|
34
|
+
/** Extracts a semver-like triple from version output such as `kimi-code 0.27.0`. */
|
|
35
|
+
export declare function parseCliVersion(raw: string): string | null;
|
|
36
|
+
/** True when `raw` identifies a Kimi CLI at or above {@link MIN_KIMI_VERSION}. */
|
|
37
|
+
export declare function isSupportedKimiVersion(raw: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Resolves which provider the installer should use. Priority:
|
|
40
|
+
* 1. Explicit `--provider claude` flag (already passed through args).
|
|
41
|
+
* 2. Config file (read upstream in install-config.ts).
|
|
42
|
+
* 3. Whichever CLI is installed.
|
|
43
|
+
*
|
|
44
|
+
* The caller may bypass prereq failures with `skipPrereqs: true`
|
|
45
|
+
* (env `SPECRAILS_SKIP_PREREQS=1`).
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveProvider(availability: ProviderAvailability, options?: {
|
|
48
|
+
explicit?: Provider;
|
|
49
|
+
skipPrereqs?: boolean;
|
|
50
|
+
}): Promise<Provider>;
|
|
51
|
+
/**
|
|
52
|
+
* Directory / filename conventions the provider dictates.
|
|
53
|
+
* - Claude Code: .claude/ + CLAUDE.md
|
|
54
|
+
* - Codex: .codex/ + AGENTS.md
|
|
55
|
+
* - Gemini CLI: .gemini/ + GEMINI.md
|
|
56
|
+
* - Kimi Code: .kimi-code/ + AGENTS.md
|
|
57
|
+
*/
|
|
58
|
+
export declare function derivedPaths(provider: Provider): ProviderDerivedPaths;
|
|
59
|
+
/**
|
|
60
|
+
* Asserts that Claude Code is authenticated. Matches the three-path
|
|
61
|
+
* check from install.sh: `claude config list` → ANTHROPIC_API_KEY env →
|
|
62
|
+
* ~/.claude.json OAuth.
|
|
63
|
+
*/
|
|
64
|
+
export declare function assertClaudeAuthenticated(options?: {
|
|
65
|
+
skipPrereqs?: boolean;
|
|
66
|
+
}): Promise<void>;
|
|
67
|
+
export type KimiAuthenticationStatus = 'authenticated' | 'unauthenticated' | 'unknown';
|
|
68
|
+
/**
|
|
69
|
+
* Bounded, non-billing Kimi authentication probe.
|
|
70
|
+
*
|
|
71
|
+
* Kimi 0.27 has no CLI command that proves managed OAuth readiness without
|
|
72
|
+
* starting a model request. We therefore recognise non-secret evidence (the
|
|
73
|
+
* managed credential file or a process-scoped model key), and honour explicit
|
|
74
|
+
* login failures emitted by `kimi doctor`. A successful `kimi doctor` only
|
|
75
|
+
* validates configuration, so it deliberately yields `unknown`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function probeKimiAuthentication(options?: {
|
|
78
|
+
kimiCodeHome?: string;
|
|
79
|
+
env?: NodeJS.ProcessEnv;
|
|
80
|
+
}): Promise<KimiAuthenticationStatus>;
|
|
81
|
+
/**
|
|
82
|
+
* Rejects only a conclusive login failure. `unknown` is allowed because setup
|
|
83
|
+
* must not spend quota merely to prove authentication.
|
|
84
|
+
*/
|
|
85
|
+
export declare function assertKimiAuthenticated(options?: {
|
|
86
|
+
skipPrereqs?: boolean;
|
|
87
|
+
kimiCodeHome?: string;
|
|
88
|
+
env?: NodeJS.ProcessEnv;
|
|
89
|
+
}): Promise<KimiAuthenticationStatus>;
|