@open-agent-toolkit/cli 0.2.59 → 0.2.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agents/oat-phase-implementer.md +27 -4
- package/assets/agents/oat-reviewer.md +25 -14
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/config-and-local-state.md +1 -0
- package/assets/docs/cli-utilities/configuration.md +10 -8
- package/assets/docs/cli-utilities/project-log.md +16 -0
- package/assets/docs/cli-utilities/workflow-gates.md +127 -19
- package/assets/docs/provider-sync/commands.md +3 -0
- package/assets/docs/provider-sync/instruction-sync.md +107 -0
- package/assets/docs/reference/cli-reference.md +26 -9
- package/assets/docs/reference/oat-directory-structure.md +33 -31
- package/assets/docs/workflows/ideas/index.md +1 -1
- package/assets/docs/workflows/index.md +1 -0
- package/assets/docs/workflows/projects/artifacts.md +24 -3
- package/assets/docs/workflows/projects/hill-checkpoints.md +21 -0
- package/assets/docs/workflows/projects/implementation-execution.md +5 -0
- package/assets/docs/workflows/projects/lifecycle.md +169 -7
- package/assets/docs/workflows/projects/picking-up-projects.md +14 -0
- package/assets/docs/workflows/projects/pr-flow.md +2 -0
- package/assets/docs/workflows/projects/reviews.md +1 -1
- package/assets/docs/workflows/projects/state-machine.md +20 -0
- package/assets/docs/workflows/skills/explainer-kit.md +10 -4
- package/assets/docs/workflows/skills/index.md +2 -1
- package/assets/docs/workflows/skills/repo-improve.md +15 -1
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-brainstorm/SKILL.md +61 -12
- package/assets/skills/oat-docs/SKILL.md +13 -8
- package/assets/skills/oat-doctor/SKILL.md +3 -3
- package/assets/skills/oat-explainer-kit/SKILL.md +14 -1
- package/assets/skills/oat-explainer-kit/references/config-contract.md +12 -0
- package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +57 -10
- package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +28 -5
- package/assets/skills/oat-explainer-kit/scripts/probe-recap-seams.mjs +371 -0
- package/assets/skills/oat-explainer-kit/scripts/resolve-intent.mjs +123 -1
- package/assets/skills/oat-pjm-review-backlog/SKILL.md +2 -2
- package/assets/skills/oat-project-autonomous/SKILL.md +23 -9
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +164 -150
- package/assets/skills/oat-project-capture/SKILL.md +2 -2
- package/assets/skills/oat-project-complete/SKILL.md +134 -4
- package/assets/skills/oat-project-discover/SKILL.md +6 -5
- package/assets/skills/oat-project-document/SKILL.md +11 -1
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +164 -150
- package/assets/skills/oat-project-implement/SKILL.md +3 -3
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +144 -21
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +164 -150
- package/assets/skills/oat-project-implement/references/phase-execution.md +16 -1
- package/assets/skills/oat-project-implement/references/plan-and-resume.md +19 -1
- package/assets/skills/oat-project-import-plan/SKILL.md +47 -3
- package/assets/skills/oat-project-lite/SKILL.md +467 -0
- package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +331 -0
- package/assets/skills/oat-project-next/SKILL.md +75 -16
- package/assets/skills/oat-project-plan/SKILL.md +44 -6
- package/assets/skills/oat-project-plan-writing/SKILL.md +6 -3
- package/assets/skills/oat-project-pr-final/SKILL.md +33 -7
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +164 -150
- package/assets/skills/oat-project-pr-progress/SKILL.md +3 -3
- package/assets/skills/oat-project-progress/SKILL.md +27 -5
- package/assets/skills/oat-project-promote-spec-driven/SKILL.md +3 -1
- package/assets/skills/oat-project-quick-start/SKILL.md +264 -4
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +164 -150
- package/assets/skills/oat-project-review-provide/SKILL.md +25 -6
- package/assets/skills/oat-project-summary/SKILL.md +61 -26
- package/assets/skills/oat-repo-improve/SKILL.md +40 -5
- package/assets/skills/oat-repo-improve/references/plan-template.md +84 -7
- package/assets/templates/plan-lite.md +165 -0
- package/assets/templates/plan.md +1 -1
- package/assets/templates/state.md +1 -1
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +401 -18
- package/dist/commands/gate/index.d.ts +3 -1
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +699 -211
- package/dist/commands/init/tools/shared/skill-script-references.d.ts +126 -0
- package/dist/commands/init/tools/shared/skill-script-references.d.ts.map +1 -0
- package/dist/commands/init/tools/shared/skill-script-references.js +311 -0
- package/dist/commands/instructions/instructions.types.d.ts +63 -0
- package/dist/commands/instructions/instructions.types.d.ts.map +1 -1
- package/dist/commands/instructions/instructions.utils.d.ts +51 -2
- package/dist/commands/instructions/instructions.utils.d.ts.map +1 -1
- package/dist/commands/instructions/instructions.utils.js +201 -4
- package/dist/commands/instructions/sync/sync.d.ts.map +1 -1
- package/dist/commands/instructions/sync/sync.js +12 -1
- package/dist/commands/instructions/validate/validate.d.ts.map +1 -1
- package/dist/commands/instructions/validate/validate.js +12 -1
- package/dist/commands/project/index.d.ts.map +1 -1
- package/dist/commands/project/index.js +2 -0
- package/dist/commands/project/log/append.d.ts +195 -0
- package/dist/commands/project/log/append.d.ts.map +1 -1
- package/dist/commands/project/log/append.js +1034 -11
- package/dist/commands/project/new/index.d.ts +3 -2
- package/dist/commands/project/new/index.d.ts.map +1 -1
- package/dist/commands/project/new/index.js +2 -1
- package/dist/commands/project/new/scaffold.d.ts +5 -3
- package/dist/commands/project/new/scaffold.d.ts.map +1 -1
- package/dist/commands/project/new/scaffold.js +38 -10
- package/dist/commands/project/promote/index.d.ts +2 -0
- package/dist/commands/project/promote/index.d.ts.map +1 -0
- package/dist/commands/project/promote/index.js +1 -0
- package/dist/commands/project/promote/promote.d.ts +47 -0
- package/dist/commands/project/promote/promote.d.ts.map +1 -0
- package/dist/commands/project/promote/promote.js +322 -0
- package/dist/commands/project/split/run.d.ts.map +1 -1
- package/dist/commands/project/split/run.js +8 -1
- package/dist/commands/project/validate-plan/index.d.ts.map +1 -1
- package/dist/commands/project/validate-plan/index.js +25 -1
- package/dist/commands/project/validate-plan/validate-plan.d.ts +8 -0
- package/dist/commands/project/validate-plan/validate-plan.d.ts.map +1 -1
- package/dist/commands/project/validate-plan/validate-plan.js +49 -0
- package/dist/commands/shared/frontmatter.d.ts +1 -1
- package/dist/commands/shared/frontmatter.d.ts.map +1 -1
- package/dist/commands/shared/frontmatter.js +1 -0
- package/dist/commands/state/generate.d.ts.map +1 -1
- package/dist/commands/state/generate.js +23 -0
- package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-manifest.js +2 -0
- package/dist/config/oat-config.d.ts +41 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +111 -0
- package/package.json +2 -2
|
@@ -34,7 +34,7 @@ oat_phase_status: in_progress # Status: in_progress | complete | pr_open
|
|
|
34
34
|
# - { harness: cursor, model: gpt-5.5-xhigh }
|
|
35
35
|
# source: project-state
|
|
36
36
|
# oat_dispatch_ceiling: # legacy compatibility alias for capped managed provider targets
|
|
37
|
-
oat_workflow_mode: { OAT_WORKFLOW_MODE } # spec-driven | quick | import
|
|
37
|
+
oat_workflow_mode: { OAT_WORKFLOW_MODE } # spec-driven | quick | import | lite
|
|
38
38
|
oat_workflow_origin: native # native | imported
|
|
39
39
|
# oat_skill_gate_overrides: # optional; per-project posture for configured lifecycle gates
|
|
40
40
|
# oat-project-implement: disabled # only the literal value `disabled`; absence means follow configuration
|
|
@@ -11,6 +11,7 @@ interface ConfigCommandDependencies {
|
|
|
11
11
|
readOatConfig: (repoRoot: string) => Promise<OatConfig>;
|
|
12
12
|
readOatConfigForDefaultScopeRepair: (repoRoot: string) => Promise<OatConfig>;
|
|
13
13
|
readOatConfigForDocumentationExcludesRepair: (repoRoot: string) => Promise<OatConfig>;
|
|
14
|
+
readOatConfigForInstructionPointerExcludesRepair: (repoRoot: string) => Promise<OatConfig>;
|
|
14
15
|
writeOatConfig: (repoRoot: string, config: OatConfig) => Promise<void>;
|
|
15
16
|
readOatLocalConfig: (repoRoot: string) => Promise<OatLocalConfig>;
|
|
16
17
|
writeOatLocalConfig: (repoRoot: string, config: OatLocalConfig) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAIhF,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AAoBzC,OAAO,EAML,KAAK,SAAS,EACd,KAAK,cAAc,EAGnB,KAAK,UAAU,EAkBhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAGL,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,EAC/B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,mCAAmC,EACnC,0BAA0B,EAC3B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+GpC,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kCAAkC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7E,2CAA2C,EAAE,CAC3C,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,SAAS,CAAC,CAAC;IACxB,gDAAgD,EAAE,CAChD,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,SAAS,CAAC,CAAC;IACxB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,KAC/B,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC7C,mCAAmC,EAAE,OAAO,mCAAmC,CAAC;IAChF,0BAA0B,EAAE,OAAO,0BAA0B,CAAC;IAC9D,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAwnGD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CAkMT"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile as readFileDefault } from 'node:fs/promises';
|
|
2
2
|
import { isAbsolute, join } from 'node:path';
|
|
3
3
|
import { buildCommandContext } from '../../app/command-context.js';
|
|
4
|
+
import { normalizeExcludedPaths } from '../instructions/instructions.utils.js';
|
|
4
5
|
import { resolveProjectsRoot } from '../shared/oat-paths.js';
|
|
5
6
|
import { PROJECT_SCOPES } from '../shared/project-scope.js';
|
|
6
7
|
import { confirmAction, } from '../shared/shared.prompts.js';
|
|
@@ -9,7 +10,8 @@ import { compileDispatchCeilingPreset } from '../../config/dispatch-ceiling-pres
|
|
|
9
10
|
import { normalizeDispatchMatrix, validateDispatchRouteTarget, walkDispatchMatrix, } from '../../config/dispatch-matrix.js';
|
|
10
11
|
import { formatDispatchNotices, terminalReviewerNoticesForMatrix, } from '../../config/dispatch-notices.js';
|
|
11
12
|
import { dispatchPolicyModeDescription, dispatchPolicyPolicyDescription, managedDispatchPolicyValueList, } from '../../config/dispatch-policy-options.js';
|
|
12
|
-
import {
|
|
13
|
+
import { parseJsonConfig } from '../../config/json.js';
|
|
14
|
+
import { VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES, MAX_GATE_TIMEOUT_MS, MIN_GATE_TIMEOUT_MS, isValidGateTimeoutMs, normalizeWorkflowPostImplementSequence, readOatConfig, readOatConfigForDefaultScopeRepair, readOatConfigForDocumentationExcludesRepair, readOatConfigForInstructionPointerExcludesRepair, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
|
|
13
15
|
import { resolveEffectiveConfig, } from '../../config/resolve.js';
|
|
14
16
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
15
17
|
import { resolveProjectRoot } from '../../fs/paths.js';
|
|
@@ -18,6 +20,8 @@ import { createDispatchValidationPassContext, validateDispatchMatrixRefs, } from
|
|
|
18
20
|
import { Command } from 'commander';
|
|
19
21
|
import { createConfigDumpCommand } from './dump.js';
|
|
20
22
|
const DISPATCH_CEILING_PROVIDER_KEY_PREFIX = 'workflow.dispatchCeiling.providers.';
|
|
23
|
+
/** `C:\path`, `c:/path`, and the bare `C:` drive reference. */
|
|
24
|
+
const WINDOWS_DRIVE_PATH_RE = /^[A-Za-z]:/;
|
|
21
25
|
const DISPATCH_MATRIX_TIERS = [
|
|
22
26
|
'economy',
|
|
23
27
|
'balanced',
|
|
@@ -39,6 +43,7 @@ const KEY_ORDER = [
|
|
|
39
43
|
'documentation.tooling',
|
|
40
44
|
'documentation.config',
|
|
41
45
|
'documentation.excludes',
|
|
46
|
+
'documentation.instructionPointerExcludes',
|
|
42
47
|
'documentation.requireForProjectCompletion',
|
|
43
48
|
'explainers.defaults.style',
|
|
44
49
|
'explainers.defaults.palette',
|
|
@@ -189,6 +194,17 @@ const CONFIG_CATALOG = [
|
|
|
189
194
|
owningCommand: 'oat config set documentation.excludes <glob[,glob...]>',
|
|
190
195
|
description: 'Comma-separated globs, relative to the docs directory, excluded from `oat docs generate-index`. Repeated `--exclude` flags extend this list; an empty value clears the key.',
|
|
191
196
|
},
|
|
197
|
+
{
|
|
198
|
+
key: 'documentation.instructionPointerExcludes',
|
|
199
|
+
group: 'Shared Repo (.oat/config.json)',
|
|
200
|
+
file: '.oat/config.json',
|
|
201
|
+
scope: 'shared repo',
|
|
202
|
+
type: 'string[]',
|
|
203
|
+
defaultValue: 'unset',
|
|
204
|
+
mutability: 'read/write',
|
|
205
|
+
owningCommand: 'oat config set documentation.instructionPointerExcludes <path[,path...]>',
|
|
206
|
+
description: 'Comma-separated repository-relative directories that `oat instructions sync` and `oat instructions validate` must not treat as pointer sites, additive to the documentation content root they already skip. Absolute paths and paths escaping the repository are rejected; an empty value clears the key.',
|
|
207
|
+
},
|
|
192
208
|
{
|
|
193
209
|
key: 'documentation.requireForProjectCompletion',
|
|
194
210
|
group: 'Shared Repo (.oat/config.json)',
|
|
@@ -867,6 +883,7 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
867
883
|
readOatConfig,
|
|
868
884
|
readOatConfigForDefaultScopeRepair,
|
|
869
885
|
readOatConfigForDocumentationExcludesRepair,
|
|
886
|
+
readOatConfigForInstructionPointerExcludesRepair,
|
|
870
887
|
writeOatConfig,
|
|
871
888
|
readOatLocalConfig,
|
|
872
889
|
writeOatLocalConfig,
|
|
@@ -936,6 +953,43 @@ function normalizeSharedRoot(value) {
|
|
|
936
953
|
* an empty (or all-blank) value yields an empty list, which the caller treats
|
|
937
954
|
* as "clear the key" rather than as an error.
|
|
938
955
|
*/
|
|
956
|
+
/**
|
|
957
|
+
* Parse `documentation.instructionPointerExcludes` from one comma-separated
|
|
958
|
+
* value into the shape the loader and the consumer already agree on.
|
|
959
|
+
*
|
|
960
|
+
* Every entry goes through `normalizeExcludedPaths`, the same function
|
|
961
|
+
* `oat instructions sync` and `oat instructions validate` resolve exclusions
|
|
962
|
+
* with, so what `set` writes is exactly what those commands will read back:
|
|
963
|
+
* trimmed, de-duplicated, order-preserving, repository-relative POSIX paths.
|
|
964
|
+
*
|
|
965
|
+
* An entry that function drops -- an absolute path, or one escaping the
|
|
966
|
+
* repository with `..` -- is rejected here rather than stored. Such an entry
|
|
967
|
+
* can never name a directory inside the tree being scanned, so storing it would
|
|
968
|
+
* write a value the consumer only warns about and never honours, and an
|
|
969
|
+
* operator would have every reason to believe a tree was protected when it was
|
|
970
|
+
* not. An empty value clears the key, as it does for `documentation.excludes`.
|
|
971
|
+
*
|
|
972
|
+
* A Windows drive-letter path is rejected here too. `normalizeExcludedPaths`
|
|
973
|
+
* judges absoluteness with POSIX rules, so `C:\secrets` survives it as the
|
|
974
|
+
* relative-looking `C:/secrets`; accepting that would store an absolute path
|
|
975
|
+
* under a contract that says absolute paths are refused.
|
|
976
|
+
*/
|
|
977
|
+
function parseInstructionPointerExcludes(rawValue) {
|
|
978
|
+
const normalized = [];
|
|
979
|
+
for (const entry of rawValue
|
|
980
|
+
.split(',')
|
|
981
|
+
.map((value) => value.trim())
|
|
982
|
+
.filter((value) => value.length > 0)) {
|
|
983
|
+
const [normalizedEntry] = normalizeExcludedPaths([entry]);
|
|
984
|
+
if (normalizedEntry === undefined || WINDOWS_DRIVE_PATH_RE.test(entry)) {
|
|
985
|
+
throw new Error(`Invalid documentation.instructionPointerExcludes entry ${JSON.stringify(entry)}: entries must be repository-relative paths inside the repository. Absolute paths and paths escaping the repository cannot exclude anything.`);
|
|
986
|
+
}
|
|
987
|
+
if (!normalized.includes(normalizedEntry)) {
|
|
988
|
+
normalized.push(normalizedEntry);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
return normalized;
|
|
992
|
+
}
|
|
939
993
|
function parseDocumentationExcludes(rawValue) {
|
|
940
994
|
const parsed = rawValue
|
|
941
995
|
.split(',')
|
|
@@ -1126,6 +1180,26 @@ function defaultSurfaceForKey(key) {
|
|
|
1126
1180
|
}
|
|
1127
1181
|
return 'shared';
|
|
1128
1182
|
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Resolve the `--shared` / `--local` / `--user` trio to a single surface.
|
|
1185
|
+
*
|
|
1186
|
+
* Lifted verbatim out of the `set` action so `unset` enforces the same
|
|
1187
|
+
* mutual-exclusion rule through the same code path. The thrown message is
|
|
1188
|
+
* byte-identical to the one `set` raised inline, because tests pin it.
|
|
1189
|
+
*/
|
|
1190
|
+
function resolveSurfaceFlags(options) {
|
|
1191
|
+
const flagsPresent = [options.shared, options.local, options.user].filter(Boolean).length;
|
|
1192
|
+
if (flagsPresent > 1) {
|
|
1193
|
+
throw new Error('--shared, --local, and --user flags are mutually exclusive; pass at most one.');
|
|
1194
|
+
}
|
|
1195
|
+
if (options.shared)
|
|
1196
|
+
return 'shared';
|
|
1197
|
+
if (options.local)
|
|
1198
|
+
return 'local';
|
|
1199
|
+
if (options.user)
|
|
1200
|
+
return 'user';
|
|
1201
|
+
return 'auto';
|
|
1202
|
+
}
|
|
1129
1203
|
function parseBooleanValue(key, rawValue) {
|
|
1130
1204
|
const normalized = rawValue.trim().toLowerCase();
|
|
1131
1205
|
if (normalized !== 'true' && normalized !== 'false') {
|
|
@@ -1665,7 +1739,9 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
|
|
|
1665
1739
|
// would reject the very value the operator is trying to replace.
|
|
1666
1740
|
const config = key === 'documentation.excludes'
|
|
1667
1741
|
? await dependencies.readOatConfigForDocumentationExcludesRepair(repoRoot)
|
|
1668
|
-
:
|
|
1742
|
+
: key === 'documentation.instructionPointerExcludes'
|
|
1743
|
+
? await dependencies.readOatConfigForInstructionPointerExcludesRepair(repoRoot)
|
|
1744
|
+
: await dependencies.readOatConfig(repoRoot);
|
|
1669
1745
|
if (key.startsWith('documentation.')) {
|
|
1670
1746
|
const doc = { ...config.documentation };
|
|
1671
1747
|
if (key === 'documentation.root') {
|
|
@@ -1688,6 +1764,15 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
|
|
|
1688
1764
|
doc.excludes = excludes;
|
|
1689
1765
|
}
|
|
1690
1766
|
}
|
|
1767
|
+
else if (key === 'documentation.instructionPointerExcludes') {
|
|
1768
|
+
const excludes = parseInstructionPointerExcludes(rawValue);
|
|
1769
|
+
if (excludes.length === 0) {
|
|
1770
|
+
delete doc.instructionPointerExcludes;
|
|
1771
|
+
}
|
|
1772
|
+
else {
|
|
1773
|
+
doc.instructionPointerExcludes = excludes;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1691
1776
|
else if (key === 'documentation.requireForProjectCompletion') {
|
|
1692
1777
|
doc.requireForProjectCompletion =
|
|
1693
1778
|
rawValue.trim().toLowerCase() === 'true';
|
|
@@ -1700,7 +1785,9 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
|
|
|
1700
1785
|
? String(doc.requireForProjectCompletion ?? false)
|
|
1701
1786
|
: key === 'documentation.excludes'
|
|
1702
1787
|
? (doc.excludes ?? null)
|
|
1703
|
-
:
|
|
1788
|
+
: key === 'documentation.instructionPointerExcludes'
|
|
1789
|
+
? (doc.instructionPointerExcludes ?? null)
|
|
1790
|
+
: (doc[key.replace('documentation.', '')] ?? null);
|
|
1704
1791
|
return {
|
|
1705
1792
|
key,
|
|
1706
1793
|
value: resultValue,
|
|
@@ -1810,6 +1897,258 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
|
|
|
1810
1897
|
source: 'shared',
|
|
1811
1898
|
};
|
|
1812
1899
|
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Marker for a `KEY_ORDER` family that reached `unsetConfigValue` without an
|
|
1902
|
+
* owning branch. `index.test.ts` enumerates the live catalog and asserts no key
|
|
1903
|
+
* produces this message, so adding a key family without an unset path fails a
|
|
1904
|
+
* test rather than shipping a silent no-op.
|
|
1905
|
+
*/
|
|
1906
|
+
const UNSET_UNHANDLED_FAMILY_PREFIX = 'No unset handler for config key: ';
|
|
1907
|
+
/**
|
|
1908
|
+
* Copy `record` without one own key.
|
|
1909
|
+
*
|
|
1910
|
+
* Built with `Object.fromEntries` rather than `delete`, for the same reason
|
|
1911
|
+
* `normalizeOatConfig` does: a key named `__proto__` reaches the legacy
|
|
1912
|
+
* prototype setter through assignment, and provider names in
|
|
1913
|
+
* `workflow.dispatchCeiling.providers.<name>` come from user input. This makes
|
|
1914
|
+
* the copy taken here safe; it does not claim end-to-end `__proto__` safety for
|
|
1915
|
+
* the surrounding read/normalize/write path, which this plan does not touch.
|
|
1916
|
+
*/
|
|
1917
|
+
function withoutOwnKey(record, key) {
|
|
1918
|
+
return Object.fromEntries(Object.entries(record).filter(([entryKey]) => entryKey !== key));
|
|
1919
|
+
}
|
|
1920
|
+
/**
|
|
1921
|
+
* Remove one dotted path from a config object, pruning every parent the removal
|
|
1922
|
+
* empties.
|
|
1923
|
+
*
|
|
1924
|
+
* Pruning is strictly "the object has no remaining own keys". That is what
|
|
1925
|
+
* keeps a prune from destroying a sibling the `oat config` catalog does not
|
|
1926
|
+
* expose — `documentation.index` is parsed by `config/oat-config.ts` but is
|
|
1927
|
+
* not a `ConfigKey`, so an unset of the last catalogued `documentation.*` key
|
|
1928
|
+
* leaves the parent in place while it is still present.
|
|
1929
|
+
*
|
|
1930
|
+
* A missing path, a `null`/`undefined` leaf, or a non-object in the middle of
|
|
1931
|
+
* the path all report `removed: false`, which the caller surfaces as the
|
|
1932
|
+
* already-unset outcome rather than an error.
|
|
1933
|
+
*/
|
|
1934
|
+
function removeConfigPath(config, path) {
|
|
1935
|
+
const [head, ...rest] = path;
|
|
1936
|
+
if (head === undefined) {
|
|
1937
|
+
return { next: config, removed: false };
|
|
1938
|
+
}
|
|
1939
|
+
if (!Object.prototype.hasOwnProperty.call(config, head)) {
|
|
1940
|
+
return { next: config, removed: false };
|
|
1941
|
+
}
|
|
1942
|
+
if (rest.length === 0) {
|
|
1943
|
+
const current = config[head];
|
|
1944
|
+
// `null` is how a normalized surface spells "not set here" (see
|
|
1945
|
+
// `isResolvedValue` in config/resolve.ts), so it is already unset.
|
|
1946
|
+
if (current === undefined || current === null) {
|
|
1947
|
+
return { next: config, removed: false };
|
|
1948
|
+
}
|
|
1949
|
+
return { next: withoutOwnKey(config, head), removed: true };
|
|
1950
|
+
}
|
|
1951
|
+
const child = config[head];
|
|
1952
|
+
if (!isRecord(child)) {
|
|
1953
|
+
return { next: config, removed: false };
|
|
1954
|
+
}
|
|
1955
|
+
const result = removeConfigPath(child, rest);
|
|
1956
|
+
if (!result.removed) {
|
|
1957
|
+
return { next: config, removed: false };
|
|
1958
|
+
}
|
|
1959
|
+
if (Object.keys(result.next).length === 0) {
|
|
1960
|
+
return { next: withoutOwnKey(config, head), removed: true };
|
|
1961
|
+
}
|
|
1962
|
+
return { next: { ...config, [head]: result.next }, removed: true };
|
|
1963
|
+
}
|
|
1964
|
+
/**
|
|
1965
|
+
* Map a config key to its path inside the owning config file.
|
|
1966
|
+
*
|
|
1967
|
+
* One branch per `setConfigValue` family, so a new family that lands without an
|
|
1968
|
+
* unset path falls through to `UNSET_UNHANDLED_FAMILY_PREFIX` instead of being
|
|
1969
|
+
* silently mis-split. The dynamic dispatch-ceiling keys must not be split on
|
|
1970
|
+
* `.` blindly: a provider name may itself contain dots, which is why they are
|
|
1971
|
+
* parsed with the same helper `set` uses.
|
|
1972
|
+
*/
|
|
1973
|
+
function configPathForKey(key) {
|
|
1974
|
+
if (isDispatchCeilingProviderKey(key)) {
|
|
1975
|
+
const { provider, tier } = parseDispatchCeilingProviderConfigKey(key);
|
|
1976
|
+
const base = ['workflow', 'dispatchCeiling', 'providers', provider];
|
|
1977
|
+
return tier ? [...base, tier] : base;
|
|
1978
|
+
}
|
|
1979
|
+
if (isWorkflowKey(key)) {
|
|
1980
|
+
return key.split('.');
|
|
1981
|
+
}
|
|
1982
|
+
if (key === 'activeIdea') {
|
|
1983
|
+
return ['activeIdea'];
|
|
1984
|
+
}
|
|
1985
|
+
if (key === 'updateNotifications') {
|
|
1986
|
+
return ['updateNotifications'];
|
|
1987
|
+
}
|
|
1988
|
+
if (key === 'autoReviewAtCheckpoints') {
|
|
1989
|
+
return ['autoReviewAtCheckpoints'];
|
|
1990
|
+
}
|
|
1991
|
+
if (key.startsWith('explainers.') ||
|
|
1992
|
+
key.startsWith('documentation.') ||
|
|
1993
|
+
key.startsWith('archive.')) {
|
|
1994
|
+
return key.split('.');
|
|
1995
|
+
}
|
|
1996
|
+
if (key === 'git.defaultBranch' ||
|
|
1997
|
+
key === 'projects.root' ||
|
|
1998
|
+
key === 'projects.defaultScope' ||
|
|
1999
|
+
key === 'worktrees.root') {
|
|
2000
|
+
return key.split('.');
|
|
2001
|
+
}
|
|
2002
|
+
throw new Error(`${UNSET_UNHANDLED_FAMILY_PREFIX}${key}`);
|
|
2003
|
+
}
|
|
2004
|
+
/**
|
|
2005
|
+
* Remove a supported key from one config surface.
|
|
2006
|
+
*
|
|
2007
|
+
* Mirrors `setConfigValue`: the same `validateSurfaceForKey` restrictions, the
|
|
2008
|
+
* same `defaultSurfaceForKey` fallback for `auto`, and the same lenient readers
|
|
2009
|
+
* for the two keys whose own validation errors name `oat config` as the repair
|
|
2010
|
+
* path (otherwise a strict read would reject the very value being removed).
|
|
2011
|
+
*
|
|
2012
|
+
* Two families are deliberately refused rather than removed, which keeps
|
|
2013
|
+
* `unset` at parity with `set` instead of inventing a second removal path:
|
|
2014
|
+
*
|
|
2015
|
+
* - `activeProject` / `lastPausedProject` — DR-260222 keeps lifecycle state on
|
|
2016
|
+
* `oat config set <key> ''`.
|
|
2017
|
+
* - `tools.*` — the only mutable `KEY_ORDER` family whose `CONFIG_CATALOG`
|
|
2018
|
+
* `owningCommand` is not an `oat config set` invocation (it names
|
|
2019
|
+
* `oat tools install / oat tools update`), and `setConfigValue` already
|
|
2020
|
+
* refuses anything but `true` while pointing at `oat tools remove`, which
|
|
2021
|
+
* also removes the installed pack files. Letting `unset` clear the intent
|
|
2022
|
+
* alone would leave exactly the drift that message exists to prevent, so
|
|
2023
|
+
* there is no `set` removal behavior here for `unset` to be at parity with.
|
|
2024
|
+
*/
|
|
2025
|
+
async function unsetConfigValue(repoRoot, userConfigDir, key, surface, dependencies, warn) {
|
|
2026
|
+
validateSurfaceForKey(key, surface);
|
|
2027
|
+
const resolved = await dependencies.resolveEffectiveConfig(repoRoot, userConfigDir, dependencies.processEnv);
|
|
2028
|
+
const envShadowed = resolved.resolved[key]?.source === 'env';
|
|
2029
|
+
if (key === 'activeProject' || key === 'lastPausedProject') {
|
|
2030
|
+
throw new Error(`Cannot unset state key '${key}'. Lifecycle state is cleared with: oat config set ${key} ''`);
|
|
2031
|
+
}
|
|
2032
|
+
if (key.startsWith('tools.')) {
|
|
2033
|
+
const packName = key.slice('tools.'.length);
|
|
2034
|
+
throw new Error(`Pack intent '${key}' cannot be unset. To remove the pack and clear its intent, run: oat tools remove --pack ${packName} --scope project`);
|
|
2035
|
+
}
|
|
2036
|
+
// `workflow.dispatchCeiling` and `workflow.dispatchCeiling.providers` are
|
|
2037
|
+
// accepted by `isConfigKey` so `get` can return the aggregate view that
|
|
2038
|
+
// `buildResolvedConfigAggregate` assembles from the leaf keys. They are not
|
|
2039
|
+
// leaves and are not in `KEY_ORDER`; removing one would silently delete the
|
|
2040
|
+
// whole ceiling or the whole provider matrix, which no plan step asks for.
|
|
2041
|
+
if (key === 'workflow.dispatchCeiling' ||
|
|
2042
|
+
key === 'workflow.dispatchCeiling.providers') {
|
|
2043
|
+
throw new Error(`Cannot unset '${key}': it is an aggregate read view, not a stored key. Unset the individual workflow.dispatchCeiling.preset or workflow.dispatchCeiling.providers.<provider> keys instead.`);
|
|
2044
|
+
}
|
|
2045
|
+
const effectiveSurface = surface === 'auto'
|
|
2046
|
+
? defaultSurfaceForKey(key)
|
|
2047
|
+
: surface;
|
|
2048
|
+
const path = configPathForKey(key);
|
|
2049
|
+
const removed = await removeFromSurface(repoRoot, userConfigDir, key, effectiveSurface, path, dependencies);
|
|
2050
|
+
// The env guard is scoped to the targeted surface, not to the effective
|
|
2051
|
+
// value, so that `unset` mirrors `set`: `set` happily rewrites a stored value
|
|
2052
|
+
// an env var currently shadows, so `unset` must be able to remove that same
|
|
2053
|
+
// stored value. It only refuses when the surface holds nothing to remove and
|
|
2054
|
+
// the env override is what the caller is actually seeing -- reporting
|
|
2055
|
+
// "already unset" there would imply the effective value is gone when it is
|
|
2056
|
+
// not. When a stored value was removed while an override is active, the
|
|
2057
|
+
// removal is reported and the still-live override is warned about, so an
|
|
2058
|
+
// env-sourced value is never reported as unset.
|
|
2059
|
+
if (envShadowed) {
|
|
2060
|
+
if (!removed) {
|
|
2061
|
+
throw new Error(`Cannot unset '${key}' at '${effectiveSurface}' scope: nothing is stored there, and its effective value comes from an environment variable override (source: env). Clear the environment variable in your shell to stop overriding it.`);
|
|
2062
|
+
}
|
|
2063
|
+
warn(`${key} was removed from ${effectiveSurface} config, but an environment variable override still supplies its effective value.`);
|
|
2064
|
+
}
|
|
2065
|
+
return { key, removed, source: effectiveSurface };
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Remove `path` from one surface, falling back to the file on disk.
|
|
2069
|
+
*
|
|
2070
|
+
* The normalizing readers silently drop a stored value that fails validation
|
|
2071
|
+
* instead of throwing, so such a key is invisible to `removeConfigPath` and
|
|
2072
|
+
* would be reported as already-unset while still physically present in the
|
|
2073
|
+
* file. `set` repairs the same file by rewriting it, so `unset` must be able to
|
|
2074
|
+
* clean it too. The normalized read stays the primary path -- it preserves the
|
|
2075
|
+
* lenient readers for the two keys whose strict read throws -- and the raw read
|
|
2076
|
+
* runs only when the normalized pass found nothing to remove.
|
|
2077
|
+
*/
|
|
2078
|
+
async function removeFromSurface(repoRoot, userConfigDir, key, effectiveSurface, path, dependencies) {
|
|
2079
|
+
if (effectiveSurface === 'user') {
|
|
2080
|
+
const configPath = join(userConfigDir, 'config.json');
|
|
2081
|
+
const userConfig = await dependencies.readUserConfig(userConfigDir);
|
|
2082
|
+
const { next, removed } = removeConfigPath(userConfig, path);
|
|
2083
|
+
if (removed) {
|
|
2084
|
+
await dependencies.writeUserConfig(userConfigDir, next);
|
|
2085
|
+
return true;
|
|
2086
|
+
}
|
|
2087
|
+
const repaired = await removeConfigPathOnDisk(configPath, path);
|
|
2088
|
+
if (repaired) {
|
|
2089
|
+
await dependencies.writeUserConfig(userConfigDir, repaired);
|
|
2090
|
+
return true;
|
|
2091
|
+
}
|
|
2092
|
+
return false;
|
|
2093
|
+
}
|
|
2094
|
+
if (effectiveSurface === 'local') {
|
|
2095
|
+
const configPath = join(repoRoot, '.oat', 'config.local.json');
|
|
2096
|
+
const localConfig = await dependencies.readOatLocalConfig(repoRoot);
|
|
2097
|
+
const { next, removed } = removeConfigPath(localConfig, path);
|
|
2098
|
+
if (removed) {
|
|
2099
|
+
await dependencies.writeOatLocalConfig(repoRoot, next);
|
|
2100
|
+
return true;
|
|
2101
|
+
}
|
|
2102
|
+
const repaired = await removeConfigPathOnDisk(configPath, path);
|
|
2103
|
+
if (repaired) {
|
|
2104
|
+
await dependencies.writeOatLocalConfig(repoRoot, repaired);
|
|
2105
|
+
return true;
|
|
2106
|
+
}
|
|
2107
|
+
return false;
|
|
2108
|
+
}
|
|
2109
|
+
const configPath = join(repoRoot, '.oat', 'config.json');
|
|
2110
|
+
const sharedConfig = key === 'documentation.excludes'
|
|
2111
|
+
? await dependencies.readOatConfigForDocumentationExcludesRepair(repoRoot)
|
|
2112
|
+
: key === 'documentation.instructionPointerExcludes'
|
|
2113
|
+
? await dependencies.readOatConfigForInstructionPointerExcludesRepair(repoRoot)
|
|
2114
|
+
: key === 'projects.defaultScope'
|
|
2115
|
+
? await dependencies.readOatConfigForDefaultScopeRepair(repoRoot)
|
|
2116
|
+
: await dependencies.readOatConfig(repoRoot);
|
|
2117
|
+
const { next, removed } = removeConfigPath(sharedConfig, path);
|
|
2118
|
+
if (removed) {
|
|
2119
|
+
await dependencies.writeOatConfig(repoRoot, next);
|
|
2120
|
+
return true;
|
|
2121
|
+
}
|
|
2122
|
+
const repaired = await removeConfigPathOnDisk(configPath, path);
|
|
2123
|
+
if (repaired) {
|
|
2124
|
+
await dependencies.writeOatConfig(repoRoot, repaired);
|
|
2125
|
+
return true;
|
|
2126
|
+
}
|
|
2127
|
+
return false;
|
|
2128
|
+
}
|
|
2129
|
+
/**
|
|
2130
|
+
* Remove `path` from the raw JSON on disk, ignoring normalization.
|
|
2131
|
+
*
|
|
2132
|
+
* Returns the rewritten object when the path was physically present, or `null`
|
|
2133
|
+
* when the file is missing, unreadable as an object, or simply does not hold
|
|
2134
|
+
* the path. A `null` stored value counts as absent, matching `isResolvedValue`
|
|
2135
|
+
* in `config/resolve.ts` and the leaf rule in `removeConfigPath`.
|
|
2136
|
+
*/
|
|
2137
|
+
async function removeConfigPathOnDisk(configPath, path) {
|
|
2138
|
+
let raw;
|
|
2139
|
+
try {
|
|
2140
|
+
raw = await readFileDefault(configPath, 'utf8');
|
|
2141
|
+
}
|
|
2142
|
+
catch {
|
|
2143
|
+
return null;
|
|
2144
|
+
}
|
|
2145
|
+
const parsed = parseJsonConfig(raw, configPath);
|
|
2146
|
+
if (!isRecord(parsed)) {
|
|
2147
|
+
return null;
|
|
2148
|
+
}
|
|
2149
|
+
const { next, removed } = removeConfigPath(parsed, path);
|
|
2150
|
+
return removed ? next : null;
|
|
2151
|
+
}
|
|
1813
2152
|
async function loadDispatchMatrixRecommendation(dependencies) {
|
|
1814
2153
|
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
1815
2154
|
const assetPath = join(assetsRoot, DISPATCH_MATRIX_RECOMMENDATION_ASSET);
|
|
@@ -2052,6 +2391,41 @@ async function runSet(keyArg, rawValue, surface, context, dependencies) {
|
|
|
2052
2391
|
process.exitCode = 1;
|
|
2053
2392
|
}
|
|
2054
2393
|
}
|
|
2394
|
+
async function runUnset(keyArg, surface, context, dependencies) {
|
|
2395
|
+
try {
|
|
2396
|
+
if (!isConfigKey(keyArg)) {
|
|
2397
|
+
throw new Error(`Unknown config key: ${keyArg}`);
|
|
2398
|
+
}
|
|
2399
|
+
const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
|
|
2400
|
+
const userConfigDir = join(context.home, '.oat');
|
|
2401
|
+
const result = await unsetConfigValue(repoRoot, userConfigDir, keyArg, surface, dependencies, context.logger.warn);
|
|
2402
|
+
if (context.json) {
|
|
2403
|
+
context.logger.json({
|
|
2404
|
+
status: 'ok',
|
|
2405
|
+
key: result.key,
|
|
2406
|
+
value: null,
|
|
2407
|
+
source: result.source,
|
|
2408
|
+
removed: result.removed,
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
else {
|
|
2412
|
+
context.logger.info(result.removed
|
|
2413
|
+
? `${result.key} unset from ${result.source} config`
|
|
2414
|
+
: `${result.key} is already unset in ${result.source} config`);
|
|
2415
|
+
}
|
|
2416
|
+
process.exitCode = 0;
|
|
2417
|
+
}
|
|
2418
|
+
catch (error) {
|
|
2419
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2420
|
+
if (context.json) {
|
|
2421
|
+
context.logger.json({ status: 'error', message });
|
|
2422
|
+
}
|
|
2423
|
+
else {
|
|
2424
|
+
context.logger.error(message);
|
|
2425
|
+
}
|
|
2426
|
+
process.exitCode = 1;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2055
2429
|
async function runAdopt(templateArg, options, context, dependencies) {
|
|
2056
2430
|
try {
|
|
2057
2431
|
if (templateArg !== 'dispatch-matrix') {
|
|
@@ -2173,21 +2547,7 @@ export function createConfigCommand(overrides = {}) {
|
|
|
2173
2547
|
.action(async (key, value, options, command) => {
|
|
2174
2548
|
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
2175
2549
|
try {
|
|
2176
|
-
const
|
|
2177
|
-
options.shared,
|
|
2178
|
-
options.local,
|
|
2179
|
-
options.user,
|
|
2180
|
-
].filter(Boolean).length;
|
|
2181
|
-
if (flagsPresent > 1) {
|
|
2182
|
-
throw new Error('--shared, --local, and --user flags are mutually exclusive; pass at most one.');
|
|
2183
|
-
}
|
|
2184
|
-
let surface = 'auto';
|
|
2185
|
-
if (options.shared)
|
|
2186
|
-
surface = 'shared';
|
|
2187
|
-
else if (options.local)
|
|
2188
|
-
surface = 'local';
|
|
2189
|
-
else if (options.user)
|
|
2190
|
-
surface = 'user';
|
|
2550
|
+
const surface = resolveSurfaceFlags(options);
|
|
2191
2551
|
await runSet(key, value, surface, context, dependencies);
|
|
2192
2552
|
}
|
|
2193
2553
|
catch (error) {
|
|
@@ -2200,6 +2560,29 @@ export function createConfigCommand(overrides = {}) {
|
|
|
2200
2560
|
}
|
|
2201
2561
|
process.exitCode = 1;
|
|
2202
2562
|
}
|
|
2563
|
+
}))
|
|
2564
|
+
.addCommand(new Command('unset')
|
|
2565
|
+
.description('Remove an OAT config value from one surface')
|
|
2566
|
+
.argument('<key>', 'Config key')
|
|
2567
|
+
.option('--shared', 'Remove from the shared repo config (.oat/config.json)')
|
|
2568
|
+
.option('--local', 'Remove from the repo-local config (.oat/config.local.json)')
|
|
2569
|
+
.option('--user', 'Remove from the user-level config (~/.oat/config.json)')
|
|
2570
|
+
.action(async (key, options, command) => {
|
|
2571
|
+
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
2572
|
+
try {
|
|
2573
|
+
const surface = resolveSurfaceFlags(options);
|
|
2574
|
+
await runUnset(key, surface, context, dependencies);
|
|
2575
|
+
}
|
|
2576
|
+
catch (error) {
|
|
2577
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2578
|
+
if (context.json) {
|
|
2579
|
+
context.logger.json({ status: 'error', message });
|
|
2580
|
+
}
|
|
2581
|
+
else {
|
|
2582
|
+
context.logger.error(message);
|
|
2583
|
+
}
|
|
2584
|
+
process.exitCode = 1;
|
|
2585
|
+
}
|
|
2203
2586
|
}))
|
|
2204
2587
|
.addCommand(new Command('adopt')
|
|
2205
2588
|
.description('Adopt a bundled OAT config recommendation')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
|
|
2
|
-
import { appendProjectLog } from '../project/log/append.js';
|
|
2
|
+
import { appendProjectLog, type GateProjectLogReceipt } from '../project/log/append.js';
|
|
3
3
|
import { type ExecTarget, type OatConfig, type OatLocalConfig, type UserConfig } from '../../config/oat-config.js';
|
|
4
4
|
import { type ResolvedConfig } from '../../config/resolve.js';
|
|
5
5
|
import { type ModelFamily } from '../../providers/identity/family.js';
|
|
@@ -30,6 +30,8 @@ interface GateCommandDependencies {
|
|
|
30
30
|
processEnv: NodeJS.ProcessEnv;
|
|
31
31
|
writeGateRunMarker: (path: string, marker: GateRunMarker, warn: (message: string) => void) => Promise<boolean>;
|
|
32
32
|
removeGateRunMarker: (path: string, warn: (message: string) => void) => Promise<void>;
|
|
33
|
+
writeGateProjectLogReceipt: (path: string, receipt: GateProjectLogReceipt, warn: (message: string) => void) => Promise<boolean>;
|
|
34
|
+
sleep: (ms: number) => Promise<void>;
|
|
33
35
|
writeDiagnostic: (message: string) => void;
|
|
34
36
|
}
|
|
35
37
|
type GateTimeoutSource = 'cli' | 'target' | 'config' | 'env' | 'scope-default' | 'default';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"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"}
|