@open-agent-toolkit/cli 0.2.65 → 0.2.66
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/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +19 -1
- package/assets/docs/cli-utilities/index.md +3 -0
- package/assets/docs/cli-utilities/remote-project-management.md +191 -0
- package/assets/docs/reference/cli-reference.md +12 -1
- package/assets/docs/reference/file-locations.md +22 -0
- package/assets/docs/reference/oat-directory-structure.md +30 -17
- package/assets/docs/reference/troubleshooting.md +44 -0
- package/assets/docs/workflows/skills/index.md +33 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-doctor/SKILL.md +4 -4
- package/assets/skills/oat-pjm-remote/SKILL.md +101 -0
- package/assets/skills/oat-pjm-remote/references/external-action-protocol.md +43 -0
- package/dist/commands/backlog/new.d.ts +1 -0
- package/dist/commands/backlog/new.d.ts.map +1 -1
- package/dist/commands/backlog/new.js +3 -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 +232 -1
- package/dist/commands/pjm/doctor.d.ts +2 -0
- package/dist/commands/pjm/doctor.d.ts.map +1 -1
- package/dist/commands/pjm/doctor.js +71 -1
- package/dist/commands/pjm/index.d.ts +2 -0
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +3 -0
- package/dist/commands/pjm/remote/__integration__/lifecycle-harness.d.ts +60 -0
- package/dist/commands/pjm/remote/__integration__/lifecycle-harness.d.ts.map +1 -0
- package/dist/commands/pjm/remote/__integration__/lifecycle-harness.js +151 -0
- package/dist/commands/pjm/remote/association.d.ts +27 -0
- package/dist/commands/pjm/remote/association.d.ts.map +1 -0
- package/dist/commands/pjm/remote/association.js +68 -0
- package/dist/commands/pjm/remote/authority.d.ts +210 -0
- package/dist/commands/pjm/remote/authority.d.ts.map +1 -0
- package/dist/commands/pjm/remote/authority.js +341 -0
- package/dist/commands/pjm/remote/batch.d.ts +15 -0
- package/dist/commands/pjm/remote/batch.d.ts.map +1 -0
- package/dist/commands/pjm/remote/batch.js +126 -0
- package/dist/commands/pjm/remote/closeout.d.ts +69 -0
- package/dist/commands/pjm/remote/closeout.d.ts.map +1 -0
- package/dist/commands/pjm/remote/closeout.js +208 -0
- package/dist/commands/pjm/remote/create-binding.d.ts +62 -0
- package/dist/commands/pjm/remote/create-binding.d.ts.map +1 -0
- package/dist/commands/pjm/remote/create-binding.js +126 -0
- package/dist/commands/pjm/remote/credential-safety.d.ts +7 -0
- package/dist/commands/pjm/remote/credential-safety.d.ts.map +1 -0
- package/dist/commands/pjm/remote/credential-safety.js +21 -0
- package/dist/commands/pjm/remote/discussion.d.ts +49 -0
- package/dist/commands/pjm/remote/discussion.d.ts.map +1 -0
- package/dist/commands/pjm/remote/discussion.js +124 -0
- package/dist/commands/pjm/remote/doctor.d.ts +22 -0
- package/dist/commands/pjm/remote/doctor.d.ts.map +1 -0
- package/dist/commands/pjm/remote/doctor.js +380 -0
- package/dist/commands/pjm/remote/external-action.d.ts +208 -0
- package/dist/commands/pjm/remote/external-action.d.ts.map +1 -0
- package/dist/commands/pjm/remote/external-action.js +367 -0
- package/dist/commands/pjm/remote/host-execution.d.ts +28 -0
- package/dist/commands/pjm/remote/host-execution.d.ts.map +1 -0
- package/dist/commands/pjm/remote/host-execution.js +63 -0
- package/dist/commands/pjm/remote/index.d.ts +41 -0
- package/dist/commands/pjm/remote/index.d.ts.map +1 -0
- package/dist/commands/pjm/remote/index.js +280 -0
- package/dist/commands/pjm/remote/jira-adf.d.ts +35 -0
- package/dist/commands/pjm/remote/jira-adf.d.ts.map +1 -0
- package/dist/commands/pjm/remote/jira-adf.js +169 -0
- package/dist/commands/pjm/remote/lifecycle.d.ts +163 -0
- package/dist/commands/pjm/remote/lifecycle.d.ts.map +1 -0
- package/dist/commands/pjm/remote/lifecycle.js +224 -0
- package/dist/commands/pjm/remote/local-projection.d.ts +30 -0
- package/dist/commands/pjm/remote/local-projection.d.ts.map +1 -0
- package/dist/commands/pjm/remote/local-projection.js +95 -0
- package/dist/commands/pjm/remote/managed-markdown.d.ts +30 -0
- package/dist/commands/pjm/remote/managed-markdown.d.ts.map +1 -0
- package/dist/commands/pjm/remote/managed-markdown.js +128 -0
- package/dist/commands/pjm/remote/migrate.d.ts +14 -0
- package/dist/commands/pjm/remote/migrate.d.ts.map +1 -0
- package/dist/commands/pjm/remote/migrate.js +32 -0
- package/dist/commands/pjm/remote/operation-state.d.ts +15 -0
- package/dist/commands/pjm/remote/operation-state.d.ts.map +1 -0
- package/dist/commands/pjm/remote/operation-state.js +143 -0
- package/dist/commands/pjm/remote/outbound-projection-safety.d.ts +25 -0
- package/dist/commands/pjm/remote/outbound-projection-safety.d.ts.map +1 -0
- package/dist/commands/pjm/remote/outbound-projection-safety.js +99 -0
- package/dist/commands/pjm/remote/output.d.ts +60 -0
- package/dist/commands/pjm/remote/output.d.ts.map +1 -0
- package/dist/commands/pjm/remote/output.js +48 -0
- package/dist/commands/pjm/remote/preview.d.ts +88 -0
- package/dist/commands/pjm/remote/preview.d.ts.map +1 -0
- package/dist/commands/pjm/remote/preview.js +154 -0
- package/dist/commands/pjm/remote/provider-conformance.d.ts +13 -0
- package/dist/commands/pjm/remote/provider-conformance.d.ts.map +1 -0
- package/dist/commands/pjm/remote/provider-conformance.js +37 -0
- package/dist/commands/pjm/remote/provider.d.ts +57 -0
- package/dist/commands/pjm/remote/provider.d.ts.map +1 -0
- package/dist/commands/pjm/remote/provider.js +28 -0
- package/dist/commands/pjm/remote/providers/github-publication-safety.d.ts +46 -0
- package/dist/commands/pjm/remote/providers/github-publication-safety.d.ts.map +1 -0
- package/dist/commands/pjm/remote/providers/github-publication-safety.js +126 -0
- package/dist/commands/pjm/remote/providers/github.d.ts +207 -0
- package/dist/commands/pjm/remote/providers/github.d.ts.map +1 -0
- package/dist/commands/pjm/remote/providers/github.js +1456 -0
- package/dist/commands/pjm/remote/providers/jira.d.ts +245 -0
- package/dist/commands/pjm/remote/providers/jira.d.ts.map +1 -0
- package/dist/commands/pjm/remote/providers/jira.js +1650 -0
- package/dist/commands/pjm/remote/providers/linear.d.ts +182 -0
- package/dist/commands/pjm/remote/providers/linear.d.ts.map +1 -0
- package/dist/commands/pjm/remote/providers/linear.js +1289 -0
- package/dist/commands/pjm/remote/purpose-policy.d.ts +29 -0
- package/dist/commands/pjm/remote/purpose-policy.d.ts.map +1 -0
- package/dist/commands/pjm/remote/purpose-policy.js +118 -0
- package/dist/commands/pjm/remote/reconcile.d.ts +42 -0
- package/dist/commands/pjm/remote/reconcile.d.ts.map +1 -0
- package/dist/commands/pjm/remote/reconcile.js +101 -0
- package/dist/commands/pjm/remote/resolution.d.ts +122 -0
- package/dist/commands/pjm/remote/resolution.d.ts.map +1 -0
- package/dist/commands/pjm/remote/resolution.js +243 -0
- package/dist/commands/pjm/remote/schema.d.ts +9309 -0
- package/dist/commands/pjm/remote/schema.d.ts.map +1 -0
- package/dist/commands/pjm/remote/schema.js +1503 -0
- package/dist/commands/pjm/remote/service.d.ts +20 -0
- package/dist/commands/pjm/remote/service.d.ts.map +1 -0
- package/dist/commands/pjm/remote/service.js +5121 -0
- package/dist/commands/pjm/remote/shared-storage.d.ts +36 -0
- package/dist/commands/pjm/remote/shared-storage.d.ts.map +1 -0
- package/dist/commands/pjm/remote/shared-storage.js +110 -0
- package/dist/commands/pjm/remote/snapshot.d.ts +32 -0
- package/dist/commands/pjm/remote/snapshot.d.ts.map +1 -0
- package/dist/commands/pjm/remote/snapshot.js +140 -0
- package/dist/commands/pjm/remote/storage-locator.d.ts +29 -0
- package/dist/commands/pjm/remote/storage-locator.d.ts.map +1 -0
- package/dist/commands/pjm/remote/storage-locator.js +62 -0
- package/dist/commands/pjm/remote/store.d.ts +85 -0
- package/dist/commands/pjm/remote/store.d.ts.map +1 -0
- package/dist/commands/pjm/remote/store.js +553 -0
- package/dist/commands/pjm/remote/verification.d.ts +40 -0
- package/dist/commands/pjm/remote/verification.d.ts.map +1 -0
- package/dist/commands/pjm/remote/verification.js +100 -0
- package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -1
- package/dist/commands/tools/shared/pack-manifest.js +1 -0
- package/dist/config/oat-config.d.ts +26 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +186 -2
- package/package.json +2 -2
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oat-pjm-remote
|
|
3
|
+
description: Use when explicitly intaking, publishing, refreshing, reconciling, or continuing an OAT PJM remote binding through a live host capability. Keeps policy, approval, state, and success verdicts in the OAT CLI while the host discovers and invokes currently granted execution capabilities.
|
|
4
|
+
disable-model-invocation: false
|
|
5
|
+
user-invocable: true
|
|
6
|
+
allowed-tools: Read, Bash, AskUserQuestion
|
|
7
|
+
metadata:
|
|
8
|
+
version: 1.0.2
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Operate Remote Project Bindings
|
|
12
|
+
|
|
13
|
+
Use the OAT CLI as the authority for policy, approval, durable operation state,
|
|
14
|
+
and verified outcomes. Your role is limited to live capability discovery,
|
|
15
|
+
executing the exact semantic action emitted by the CLI, and returning one
|
|
16
|
+
bounded sanitized observation.
|
|
17
|
+
|
|
18
|
+
## Progress Indicators (User-Facing)
|
|
19
|
+
|
|
20
|
+
Provide short updates at the durable boundaries: preflight, CLI preview or
|
|
21
|
+
handoff, live capability selection, observation submission, and terminal CLI
|
|
22
|
+
verdict. Never describe a host invocation result as success before the CLI has
|
|
23
|
+
verified authoritative read-back.
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
27
|
+
OAT ▸ REMOTE PROJECT MANAGEMENT
|
|
28
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- `[1/4] Verifying PJM adoption and local policy…`
|
|
32
|
+
- `[2/4] Discovering a matching live host capability…`
|
|
33
|
+
- `[3/4] Preparing the durable CLI action with bounded evidence…`
|
|
34
|
+
- `[4/4] Submitting evidence for CLI verification…`
|
|
35
|
+
|
|
36
|
+
## Preflight
|
|
37
|
+
|
|
38
|
+
Run:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
oat pjm doctor --json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Continue only when `adoption.state` is `declared` or `inferred-legacy`. For
|
|
45
|
+
`none` or `partial-initialization`, stop before any remote action and direct the
|
|
46
|
+
operator to `oat pjm init`.
|
|
47
|
+
|
|
48
|
+
## Live Capability Discovery
|
|
49
|
+
|
|
50
|
+
Before the first provider-contacting remote command, inspect currently granted
|
|
51
|
+
MCP or connector tools and their live descriptions. Select a capability only
|
|
52
|
+
when its semantic operation, provider, and exact
|
|
53
|
+
account/workspace/site/repository context match the request.
|
|
54
|
+
|
|
55
|
+
If no capable granted connector exists, you may inspect an already configured
|
|
56
|
+
provider CLI and its live help before the first attempt. Do not install a tool,
|
|
57
|
+
request authentication material, encode or retain its command dialect, or
|
|
58
|
+
switch execution surfaces after an attempt begins.
|
|
59
|
+
|
|
60
|
+
Construct only the bounded provider-neutral capability evidence accepted by the
|
|
61
|
+
CLI: provider, exact context, surface kind, availability, semantic capabilities,
|
|
62
|
+
observation time, and evidence digest. Never include a native tool name, schema,
|
|
63
|
+
catalog, raw description, help text, request, or response.
|
|
64
|
+
|
|
65
|
+
## Lifecycle
|
|
66
|
+
|
|
67
|
+
1. Complete live capability discovery before the first provider-contacting
|
|
68
|
+
remote command.
|
|
69
|
+
2. Run the requested `oat pjm remote` command in JSON mode and pass the bounded
|
|
70
|
+
evidence through `--capability-evidence-stdin`. For mutations, also supply
|
|
71
|
+
only the current caller-owned authority evidence requested by the command.
|
|
72
|
+
3. Treat CLI policy, preview, approval, safety, and terminal verdicts as
|
|
73
|
+
authoritative. Never broaden a field mask or reconstruct publication
|
|
74
|
+
content from repository files.
|
|
75
|
+
4. When the CLI returns `pending` with `externalAction`, follow
|
|
76
|
+
[the action protocol](references/external-action-protocol.md) and execute the
|
|
77
|
+
exact emitted semantic action at most once.
|
|
78
|
+
5. Submit exactly one sanitized observation through `operation continue`.
|
|
79
|
+
6. Continue only while the CLI emits another exact action for the same durable
|
|
80
|
+
operation. Stop on any terminal CLI envelope.
|
|
81
|
+
|
|
82
|
+
Never infer success from a connector result, process exit, or visible remote
|
|
83
|
+
change. Only a CLI `ok` envelope after authoritative read-back is success.
|
|
84
|
+
|
|
85
|
+
## Discussion Reads
|
|
86
|
+
|
|
87
|
+
Discussion is read-only evidence. Honor the CLI-provided page/cursor and maximum
|
|
88
|
+
item limit. Return only the bounded sanitized observation. Do not persist a
|
|
89
|
+
thread, assignee list, activity history, or native response. A requested local
|
|
90
|
+
distillation is a separate local edit and never comment synchronization.
|
|
91
|
+
|
|
92
|
+
## Safety Boundary
|
|
93
|
+
|
|
94
|
+
- Never read, request, print, or persist authentication headers or credential
|
|
95
|
+
values.
|
|
96
|
+
- Never scan the repository, worktree, Git history, or arbitrary files for
|
|
97
|
+
secrets.
|
|
98
|
+
- Never add fields to the normalized outbound projection.
|
|
99
|
+
- Never pass native requests, raw provider payloads, tool catalogs, or help
|
|
100
|
+
output into durable OAT evidence.
|
|
101
|
+
- Never declare remote success directly.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# External Action Protocol
|
|
2
|
+
|
|
3
|
+
The CLI emits a versioned provider-neutral action containing a durable
|
|
4
|
+
operation ID, step ID, action digest, provider context, semantic intent,
|
|
5
|
+
expected observation contract, and (for mutation) the exact outbound
|
|
6
|
+
projection and safety-result digests.
|
|
7
|
+
|
|
8
|
+
Initial live connector discovery (or configured-CLI-help fallback) and bounded
|
|
9
|
+
provider-neutral capability evidence construction happen before the first
|
|
10
|
+
provider-contacting remote command. The evidence is passed through
|
|
11
|
+
`--capability-evidence-stdin`; native tool names, schemas, catalogs,
|
|
12
|
+
descriptions, help text, requests, and responses are excluded.
|
|
13
|
+
|
|
14
|
+
Before execution:
|
|
15
|
+
|
|
16
|
+
1. Confirm the action belongs to the current durable operation and step.
|
|
17
|
+
2. Confirm the previously selected capability remains currently granted.
|
|
18
|
+
3. Confirm semantic operation and exact provider context.
|
|
19
|
+
4. For a mutation, confirm the projection and safety digests are present. Do
|
|
20
|
+
not reconstruct, enrich, or reinterpret the projection.
|
|
21
|
+
|
|
22
|
+
Execute at most once. Return only one observation with:
|
|
23
|
+
|
|
24
|
+
- the unchanged operation ID, step ID, and action digest;
|
|
25
|
+
- observation time and host-surface kind;
|
|
26
|
+
- bounded capability evidence digest and exact provider context;
|
|
27
|
+
- sanitized classification, durable identity/aliases when observed,
|
|
28
|
+
allowlisted fields, revision evidence, and a diagnostic code.
|
|
29
|
+
|
|
30
|
+
Do not return a native request, raw response, captured catalog, live help text,
|
|
31
|
+
process environment, authentication data, or provider-generated success claim.
|
|
32
|
+
Use:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
oat pjm remote operation continue \
|
|
36
|
+
--operation <operation-id> \
|
|
37
|
+
--observation-stdin \
|
|
38
|
+
--json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A repeated, stale, mismatched, oversized, or unsanitized observation must be
|
|
42
|
+
rejected by the CLI. An ambiguous post-attempt outcome remains uncertain and
|
|
43
|
+
must be reconciled before any new execution choice or retry.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/backlog/new.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/commands/backlog/new.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,EACL,sBAAsB,EACtB,KAAK,4BAA4B,EAClC,MAAM,oBAAoB,CAAC;AAS5B,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,eAAe,CAAC;IAC9B,KAAK,EAAE,4BAA4B,CAAC;CACrC;AAED,MAAM,WAAW,6BAA6B;IAC5C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AAgKD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,EACjC,SAAS,GAAE,OAAO,CAAC,6BAA6B,CAAM,GACrD,OAAO,CAAC,uBAAuB,CAAC,CAwDlC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { access, readFile, rm, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { parseAssociatedIssues, serializeAssociatedIssues, } from '../pjm/remote/association.js';
|
|
3
4
|
import { resolvePjmTemplate, } from '../pjm/template-source.js';
|
|
4
5
|
import { stripTemplateFrontmatter } from '../shared/strip-template-frontmatter.js';
|
|
5
6
|
import YAML from 'yaml';
|
|
@@ -72,6 +73,7 @@ function normalizeInputs(options) {
|
|
|
72
73
|
scopeEstimate,
|
|
73
74
|
labels,
|
|
74
75
|
description: options.description,
|
|
76
|
+
associatedIssues: serializeAssociatedIssues(parseAssociatedIssues(options.associatedIssues ?? [])),
|
|
75
77
|
};
|
|
76
78
|
}
|
|
77
79
|
function renderBacklogItem(template, values) {
|
|
@@ -90,7 +92,7 @@ function renderBacklogItem(template, values) {
|
|
|
90
92
|
assignee: null,
|
|
91
93
|
created: values.timestamp,
|
|
92
94
|
updated: values.timestamp,
|
|
93
|
-
associated_issues:
|
|
95
|
+
associated_issues: values.associatedIssues,
|
|
94
96
|
external_plans: [],
|
|
95
97
|
}).trimEnd();
|
|
96
98
|
return `---\n${frontmatter}\n---\n\n${body.trimEnd()}\n`;
|
|
@@ -21,6 +21,7 @@ interface ConfigCommandDependencies {
|
|
|
21
21
|
resolveEffectiveConfig: (repoRoot: string, userConfigDir: string, env: NodeJS.ProcessEnv) => Promise<ResolvedConfig>;
|
|
22
22
|
resolveAssetsRoot: () => Promise<string>;
|
|
23
23
|
readFile: (path: string) => Promise<string>;
|
|
24
|
+
atomicWriteJson: (path: string, data: unknown) => Promise<void>;
|
|
24
25
|
confirmAction: (message: string, ctx: PromptContext) => Promise<boolean>;
|
|
25
26
|
validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<MatrixCellAvailabilityResponse>;
|
|
26
27
|
createDispatchValidationPassContext: typeof createDispatchValidationPassContext;
|
|
@@ -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;AAIhF,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AAoBzC,OAAO,EAML,KAAK,SAAS,EACd,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ import { parseJsonConfig } from '../../config/json.js';
|
|
|
14
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';
|
|
15
15
|
import { resolveEffectiveConfig, } from '../../config/resolve.js';
|
|
16
16
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
17
|
+
import { atomicWriteJson } from '../../fs/io.js';
|
|
17
18
|
import { resolveProjectRoot } from '../../fs/paths.js';
|
|
18
19
|
import { normalizeMatrixCellAvailability, validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
19
20
|
import { createDispatchValidationPassContext, validateDispatchMatrixRefs, } from '../../providers/identity/dispatch-validation.js';
|
|
@@ -28,6 +29,31 @@ const DISPATCH_MATRIX_TIERS = [
|
|
|
28
29
|
'high',
|
|
29
30
|
'frontier',
|
|
30
31
|
];
|
|
32
|
+
const PJM_REMOTE_PROVIDERS = ['github', 'linear', 'jira'];
|
|
33
|
+
const PJM_REMOTE_OPERATIONS = [
|
|
34
|
+
'create',
|
|
35
|
+
'update-fields',
|
|
36
|
+
'transition',
|
|
37
|
+
'annotate',
|
|
38
|
+
'delete',
|
|
39
|
+
'relink',
|
|
40
|
+
'detach',
|
|
41
|
+
'recreate',
|
|
42
|
+
];
|
|
43
|
+
const PJM_REMOTE_CONFIG_KEYS = [
|
|
44
|
+
'pjm.remote',
|
|
45
|
+
'pjm.remote.schemaVersion',
|
|
46
|
+
'pjm.remote.storage.state',
|
|
47
|
+
'pjm.remote.policy',
|
|
48
|
+
'pjm.remote.policy.description',
|
|
49
|
+
'pjm.remote.policy.authority.default',
|
|
50
|
+
...PJM_REMOTE_OPERATIONS.map((operation) => `pjm.remote.policy.authority.operations.${operation}`),
|
|
51
|
+
...PJM_REMOTE_PROVIDERS.flatMap((provider) => [
|
|
52
|
+
`pjm.remote.policy.providers.${provider}.description`,
|
|
53
|
+
`pjm.remote.policy.providers.${provider}.authority.default`,
|
|
54
|
+
...PJM_REMOTE_OPERATIONS.map((operation) => `pjm.remote.policy.providers.${provider}.authority.operations.${operation}`),
|
|
55
|
+
]),
|
|
56
|
+
];
|
|
31
57
|
const KEY_ORDER = [
|
|
32
58
|
'activeIdea',
|
|
33
59
|
'activeProject',
|
|
@@ -58,6 +84,7 @@ const KEY_ORDER = [
|
|
|
58
84
|
'git.defaultBranch',
|
|
59
85
|
'projects.root',
|
|
60
86
|
'projects.defaultScope',
|
|
87
|
+
...PJM_REMOTE_CONFIG_KEYS,
|
|
61
88
|
'tools.brainstorm',
|
|
62
89
|
'tools.core',
|
|
63
90
|
'tools.docs',
|
|
@@ -94,7 +121,45 @@ const KEY_ORDER = [
|
|
|
94
121
|
'workflow.gateTimeouts.artifact',
|
|
95
122
|
'worktrees.root',
|
|
96
123
|
];
|
|
124
|
+
const PJM_REMOTE_CONFIG_CATALOG = PJM_REMOTE_CONFIG_KEYS.map((key) => {
|
|
125
|
+
const aggregate = key === 'pjm.remote' || key === 'pjm.remote.policy';
|
|
126
|
+
const schemaVersion = key === 'pjm.remote.schemaVersion';
|
|
127
|
+
const storage = key === 'pjm.remote.storage.state';
|
|
128
|
+
const authority = key.includes('.authority.');
|
|
129
|
+
const description = key.endsWith('.description');
|
|
130
|
+
const type = schemaVersion
|
|
131
|
+
? 'literal 1'
|
|
132
|
+
: storage
|
|
133
|
+
? 'local | shared'
|
|
134
|
+
: authority
|
|
135
|
+
? 'read-only | user-approved | user-authorized | autonomous'
|
|
136
|
+
: description
|
|
137
|
+
? 'none | managed-section | replace'
|
|
138
|
+
: 'object';
|
|
139
|
+
return {
|
|
140
|
+
key,
|
|
141
|
+
group: 'PJM Remote Shared Policy',
|
|
142
|
+
file: '.oat/config.json',
|
|
143
|
+
scope: 'shared repo',
|
|
144
|
+
type,
|
|
145
|
+
defaultValue: schemaVersion
|
|
146
|
+
? '1'
|
|
147
|
+
: storage
|
|
148
|
+
? 'local'
|
|
149
|
+
: authority
|
|
150
|
+
? 'read-only'
|
|
151
|
+
: description
|
|
152
|
+
? 'none'
|
|
153
|
+
: 'unset',
|
|
154
|
+
mutability: aggregate || schemaVersion ? 'read-only' : 'read/write',
|
|
155
|
+
owningCommand: aggregate || schemaVersion
|
|
156
|
+
? 'individual child keys'
|
|
157
|
+
: `oat config set ${key} <value> --shared`,
|
|
158
|
+
description: 'Repository-owned remote storage or mutation policy; host execution is discovered live and cannot broaden it.',
|
|
159
|
+
};
|
|
160
|
+
});
|
|
97
161
|
const CONFIG_CATALOG = [
|
|
162
|
+
...PJM_REMOTE_CONFIG_CATALOG,
|
|
98
163
|
{
|
|
99
164
|
key: 'projects.root',
|
|
100
165
|
group: 'Shared Repo (.oat/config.json)',
|
|
@@ -893,6 +958,7 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
893
958
|
resolveEffectiveConfig,
|
|
894
959
|
resolveAssetsRoot,
|
|
895
960
|
readFile: (path) => readFileDefault(path, 'utf8'),
|
|
961
|
+
atomicWriteJson,
|
|
896
962
|
confirmAction,
|
|
897
963
|
validateMatrixCell,
|
|
898
964
|
createDispatchValidationPassContext,
|
|
@@ -905,6 +971,9 @@ function isConfigKey(value) {
|
|
|
905
971
|
value === 'workflow.dispatchCeiling.providers' ||
|
|
906
972
|
isDispatchCeilingProviderKey(value));
|
|
907
973
|
}
|
|
974
|
+
function isPjmRemoteConfigKey(key) {
|
|
975
|
+
return key.startsWith('pjm.remote');
|
|
976
|
+
}
|
|
908
977
|
function isDispatchCeilingProviderKey(value) {
|
|
909
978
|
return (value.startsWith(DISPATCH_CEILING_PROVIDER_KEY_PREFIX) &&
|
|
910
979
|
value.slice(DISPATCH_CEILING_PROVIDER_KEY_PREFIX.length).trim().length > 0);
|
|
@@ -1119,6 +1188,12 @@ function validateSurfaceForKey(key, surface) {
|
|
|
1119
1188
|
}
|
|
1120
1189
|
return;
|
|
1121
1190
|
}
|
|
1191
|
+
if (isPjmRemoteConfigKey(key)) {
|
|
1192
|
+
if (surface !== 'shared') {
|
|
1193
|
+
throw new Error(`Cannot set '${key}' at '${surface}' scope. PJM remote policy and storage can only be set at shared scope.`);
|
|
1194
|
+
}
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1122
1197
|
if (key.startsWith('explainers.')) {
|
|
1123
1198
|
const allowed = key === 'explainers.defaults.style' ||
|
|
1124
1199
|
key === 'explainers.defaults.palette' ||
|
|
@@ -1532,6 +1607,98 @@ function formatResolvedValue(value) {
|
|
|
1532
1607
|
}
|
|
1533
1608
|
return String(value);
|
|
1534
1609
|
}
|
|
1610
|
+
function defaultPjmRemoteSharedConfig() {
|
|
1611
|
+
return {
|
|
1612
|
+
schemaVersion: 1,
|
|
1613
|
+
storage: { state: 'local' },
|
|
1614
|
+
policy: {
|
|
1615
|
+
description: 'none',
|
|
1616
|
+
authority: { default: 'read-only', operations: {} },
|
|
1617
|
+
providers: {},
|
|
1618
|
+
},
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1621
|
+
function applyPjmRemoteSharedValue(current, key, rawValue) {
|
|
1622
|
+
if (key === 'pjm.remote' ||
|
|
1623
|
+
key === 'pjm.remote.policy' ||
|
|
1624
|
+
key === 'pjm.remote.schemaVersion') {
|
|
1625
|
+
throw new Error(`Config key '${key}' is read-only; set one of its documented child keys.`);
|
|
1626
|
+
}
|
|
1627
|
+
const remote = structuredClone(current ?? defaultPjmRemoteSharedConfig());
|
|
1628
|
+
if (key === 'pjm.remote.storage.state') {
|
|
1629
|
+
const state = rawValue.trim();
|
|
1630
|
+
if (state !== 'local' && state !== 'shared') {
|
|
1631
|
+
throw new Error(`Invalid value for ${key}: expected one of local | shared, got '${rawValue}'.`);
|
|
1632
|
+
}
|
|
1633
|
+
if (state === 'shared') {
|
|
1634
|
+
throw new Error("Shared operational storage requires 'oat pjm remote storage shared' preview and approval; direct config set is blocked.");
|
|
1635
|
+
}
|
|
1636
|
+
remote.storage = { state };
|
|
1637
|
+
return remote;
|
|
1638
|
+
}
|
|
1639
|
+
const descriptions = [
|
|
1640
|
+
'none',
|
|
1641
|
+
'managed-section',
|
|
1642
|
+
'replace',
|
|
1643
|
+
];
|
|
1644
|
+
const authorities = [
|
|
1645
|
+
'read-only',
|
|
1646
|
+
'user-approved',
|
|
1647
|
+
'user-authorized',
|
|
1648
|
+
'autonomous',
|
|
1649
|
+
];
|
|
1650
|
+
const value = rawValue.trim();
|
|
1651
|
+
if (key === 'pjm.remote.policy.description') {
|
|
1652
|
+
if (!descriptions.includes(value)) {
|
|
1653
|
+
throw new Error(`Invalid value for ${key}: expected one of ${descriptions.join(' | ')}, got '${rawValue}'.`);
|
|
1654
|
+
}
|
|
1655
|
+
remote.policy.description = value;
|
|
1656
|
+
return remote;
|
|
1657
|
+
}
|
|
1658
|
+
if (!authorities.includes(value)) {
|
|
1659
|
+
if (key.endsWith('.description')) {
|
|
1660
|
+
if (!descriptions.includes(value)) {
|
|
1661
|
+
throw new Error(`Invalid value for ${key}: expected one of ${descriptions.join(' | ')}, got '${rawValue}'.`);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
else {
|
|
1665
|
+
throw new Error(`Invalid value for ${key}: expected one of ${authorities.join(' | ')}, got '${rawValue}'.`);
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
if (key === 'pjm.remote.policy.authority.default') {
|
|
1669
|
+
remote.policy.authority.default = value;
|
|
1670
|
+
return remote;
|
|
1671
|
+
}
|
|
1672
|
+
const repositoryOperationPrefix = 'pjm.remote.policy.authority.operations.';
|
|
1673
|
+
if (key.startsWith(repositoryOperationPrefix)) {
|
|
1674
|
+
const operation = key.slice(repositoryOperationPrefix.length);
|
|
1675
|
+
remote.policy.authority.operations ??= {};
|
|
1676
|
+
remote.policy.authority.operations[operation] =
|
|
1677
|
+
value;
|
|
1678
|
+
return remote;
|
|
1679
|
+
}
|
|
1680
|
+
const parts = key.split('.');
|
|
1681
|
+
const provider = parts[4];
|
|
1682
|
+
remote.policy.providers ??= {};
|
|
1683
|
+
const providerPolicy = structuredClone(remote.policy.providers[provider] ?? {});
|
|
1684
|
+
if (parts[5] === 'description') {
|
|
1685
|
+
providerPolicy.description = value;
|
|
1686
|
+
}
|
|
1687
|
+
else {
|
|
1688
|
+
providerPolicy.authority ??= {};
|
|
1689
|
+
if (parts[6] === 'default') {
|
|
1690
|
+
providerPolicy.authority.default = value;
|
|
1691
|
+
}
|
|
1692
|
+
else {
|
|
1693
|
+
providerPolicy.authority.operations ??= {};
|
|
1694
|
+
const operation = parts[7];
|
|
1695
|
+
providerPolicy.authority.operations[operation] =
|
|
1696
|
+
value;
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
remote.policy.providers[provider] = providerPolicy;
|
|
1700
|
+
return remote;
|
|
1701
|
+
}
|
|
1535
1702
|
async function getConfigValue(repoRoot, userConfigDir, key, dependencies, preserveRawObject = false) {
|
|
1536
1703
|
const resolved = await dependencies.resolveEffectiveConfig(repoRoot, userConfigDir, dependencies.processEnv);
|
|
1537
1704
|
const entry = resolved.resolved[key];
|
|
@@ -1600,6 +1767,19 @@ async function listConfigKeys(repoRoot, userConfigDir, dependencies) {
|
|
|
1600
1767
|
async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, dependencies, warn) {
|
|
1601
1768
|
validateSurfaceForKey(key, surface);
|
|
1602
1769
|
const effectiveSurface = surface === 'auto' ? defaultSurfaceForKey(key) : surface;
|
|
1770
|
+
if (isPjmRemoteConfigKey(key)) {
|
|
1771
|
+
const config = await dependencies.readOatConfig(repoRoot);
|
|
1772
|
+
const remote = applyPjmRemoteSharedValue(config.pjm?.remote, key, rawValue);
|
|
1773
|
+
await dependencies.writeOatConfig(repoRoot, {
|
|
1774
|
+
...config,
|
|
1775
|
+
pjm: { ...config.pjm, remote },
|
|
1776
|
+
});
|
|
1777
|
+
return {
|
|
1778
|
+
key,
|
|
1779
|
+
value: rawValue.trim(),
|
|
1780
|
+
source: 'shared',
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1603
1783
|
if (isWorkflowKey(key)) {
|
|
1604
1784
|
const parsedValue = parseWorkflowValue(key, rawValue);
|
|
1605
1785
|
const displayValue = formatResolvedValue(parsedValue);
|
|
@@ -1990,7 +2170,8 @@ function configPathForKey(key) {
|
|
|
1990
2170
|
}
|
|
1991
2171
|
if (key.startsWith('explainers.') ||
|
|
1992
2172
|
key.startsWith('documentation.') ||
|
|
1993
|
-
key.startsWith('archive.')
|
|
2173
|
+
key.startsWith('archive.') ||
|
|
2174
|
+
isPjmRemoteConfigKey(key)) {
|
|
1994
2175
|
return key.split('.');
|
|
1995
2176
|
}
|
|
1996
2177
|
if (key === 'git.defaultBranch' ||
|
|
@@ -2024,6 +2205,15 @@ function configPathForKey(key) {
|
|
|
2024
2205
|
*/
|
|
2025
2206
|
async function unsetConfigValue(repoRoot, userConfigDir, key, surface, dependencies, warn) {
|
|
2026
2207
|
validateSurfaceForKey(key, surface);
|
|
2208
|
+
// These are structural views (and, for schemaVersion, the discriminator
|
|
2209
|
+
// that makes the remote policy readable), just as they are for `set`.
|
|
2210
|
+
// Refuse them before resolving config so an unset attempt can never be
|
|
2211
|
+
// mistaken for permission to remove the whole policy boundary.
|
|
2212
|
+
if (key === 'pjm.remote' ||
|
|
2213
|
+
key === 'pjm.remote.policy' ||
|
|
2214
|
+
key === 'pjm.remote.schemaVersion') {
|
|
2215
|
+
throw new Error(`Config key '${key}' is read-only; unset one of its documented child keys.`);
|
|
2216
|
+
}
|
|
2027
2217
|
const resolved = await dependencies.resolveEffectiveConfig(repoRoot, userConfigDir, dependencies.processEnv);
|
|
2028
2218
|
const envShadowed = resolved.resolved[key]?.source === 'env';
|
|
2029
2219
|
if (key === 'activeProject' || key === 'lastPausedProject') {
|
|
@@ -2107,6 +2297,22 @@ async function removeFromSurface(repoRoot, userConfigDir, key, effectiveSurface,
|
|
|
2107
2297
|
return false;
|
|
2108
2298
|
}
|
|
2109
2299
|
const configPath = join(repoRoot, '.oat', 'config.json');
|
|
2300
|
+
if (isPjmRemoteConfigKey(key)) {
|
|
2301
|
+
// PJM remote normalization materializes fail-closed defaults such as
|
|
2302
|
+
// policy.description=none and authority.default=read-only. Removing a
|
|
2303
|
+
// leaf from that normalized object and sending it through writeOatConfig
|
|
2304
|
+
// would therefore write the leaf straight back while reporting success.
|
|
2305
|
+
// The config has already passed the strict shared-policy reader in
|
|
2306
|
+
// resolveEffectiveConfig, so perform this removal against the validated raw
|
|
2307
|
+
// document and atomically persist only the requested structural change.
|
|
2308
|
+
const repaired = await removeConfigPathOnDisk(configPath, path);
|
|
2309
|
+
if (!repaired) {
|
|
2310
|
+
return false;
|
|
2311
|
+
}
|
|
2312
|
+
preservePjmRemotePolicyBoundary(repaired, path);
|
|
2313
|
+
await dependencies.atomicWriteJson(configPath, repaired);
|
|
2314
|
+
return true;
|
|
2315
|
+
}
|
|
2110
2316
|
const sharedConfig = key === 'documentation.excludes'
|
|
2111
2317
|
? await dependencies.readOatConfigForDocumentationExcludesRepair(repoRoot)
|
|
2112
2318
|
: key === 'documentation.instructionPointerExcludes'
|
|
@@ -2126,6 +2332,31 @@ async function removeFromSurface(repoRoot, userConfigDir, key, effectiveSurface,
|
|
|
2126
2332
|
}
|
|
2127
2333
|
return false;
|
|
2128
2334
|
}
|
|
2335
|
+
/**
|
|
2336
|
+
* Keep the required PJM remote policy object when unsetting its final leaf.
|
|
2337
|
+
*
|
|
2338
|
+
* The recursive remover normally prunes empty parents. For this one schema,
|
|
2339
|
+
* however, `policy` is the structural boundary that keeps sibling remote state
|
|
2340
|
+
* (notably `storage.state=shared`) readable. An empty policy is valid and
|
|
2341
|
+
* normalizes to the fail-closed defaults; an absent policy makes the complete
|
|
2342
|
+
* remote object unreadable.
|
|
2343
|
+
*/
|
|
2344
|
+
function preservePjmRemotePolicyBoundary(config, path) {
|
|
2345
|
+
if (path[0] !== 'pjm' || path[1] !== 'remote' || path[2] !== 'policy') {
|
|
2346
|
+
return;
|
|
2347
|
+
}
|
|
2348
|
+
const pjm = config.pjm;
|
|
2349
|
+
if (!isRecord(pjm)) {
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
const remote = pjm.remote;
|
|
2353
|
+
if (!isRecord(remote)) {
|
|
2354
|
+
return;
|
|
2355
|
+
}
|
|
2356
|
+
if (!Object.prototype.hasOwnProperty.call(remote, 'policy')) {
|
|
2357
|
+
remote.policy = {};
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2129
2360
|
/**
|
|
2130
2361
|
* Remove `path` from the raw JSON on disk, ignoring normalization.
|
|
2131
2362
|
*
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { DoctorCheck } from '../../ui/output.js';
|
|
2
2
|
import { type PjmAdoption } from './adoption.js';
|
|
3
|
+
import { type RemoteDoctorInput } from './remote/doctor.js';
|
|
3
4
|
export interface PjmDoctorOptions {
|
|
4
5
|
projectRoot?: string;
|
|
5
6
|
adoption?: PjmAdoption;
|
|
7
|
+
remote?: RemoteDoctorInput;
|
|
6
8
|
}
|
|
7
9
|
export declare function runPjmDoctorChecks(repoRoot: string, options?: PjmDoctorOptions): Promise<DoctorCheck[]>;
|
|
8
10
|
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/doctor.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,EAAyB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AA8MhF,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,WAAW,EAAE,CAAC,CAmVxB"}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import { execFile as execFileCallback } from 'node:child_process';
|
|
1
2
|
import { access, readdir, readFile } from 'node:fs/promises';
|
|
2
|
-
import { basename, dirname, join } from 'node:path';
|
|
3
|
+
import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
3
5
|
import { BACKLOG_ITEM_STATUSES, extractBacklogStatus, isTerminalBacklogStatus, isValidBacklogStatus, } from '../backlog/shared/item-status.js';
|
|
4
6
|
import { getFrontmatterBlock } from '../shared/frontmatter.js';
|
|
7
|
+
import { parseJsonConfig } from '../../config/json.js';
|
|
5
8
|
import { resolvePjmAdoption } from './adoption.js';
|
|
6
9
|
import { CANONICAL_REPO_REFERENCE_PATHS } from './init.js';
|
|
10
|
+
import { runRemoteDoctorChecks } from './remote/doctor.js';
|
|
11
|
+
import { resolveRemoteStorageLocations } from './remote/storage-locator.js';
|
|
12
|
+
const execFileAsync = promisify(execFileCallback);
|
|
7
13
|
const ALLOWED_TOP_LEVEL_DIRECTORIES = new Set([
|
|
8
14
|
'pjm',
|
|
9
15
|
'reference',
|
|
@@ -435,5 +441,69 @@ export async function runPjmDoctorChecks(repoRoot, options = {}) {
|
|
|
435
441
|
? undefined
|
|
436
442
|
: 'Run `oat backlog archive <id>` to archive each completed item still under items/.',
|
|
437
443
|
});
|
|
444
|
+
const defaultRemote = await resolveDefaultRemoteDoctorInput(projectRoot, repoRoot);
|
|
445
|
+
checks.push(...(await runRemoteDoctorChecks(options.remote ?? defaultRemote)));
|
|
438
446
|
return checks;
|
|
439
447
|
}
|
|
448
|
+
async function resolveDefaultRemoteDoctorInput(projectRoot, pjmRepoRoot) {
|
|
449
|
+
const rawConfig = await readRawRemoteConfig(projectRoot);
|
|
450
|
+
const stateStorage = isRecord(rawConfig) &&
|
|
451
|
+
isRecord(rawConfig.storage) &&
|
|
452
|
+
rawConfig.storage.state === 'shared'
|
|
453
|
+
? 'shared'
|
|
454
|
+
: 'local';
|
|
455
|
+
try {
|
|
456
|
+
const [{ stdout: commonDirOutput }, { stdout: originOutput }] = await Promise.all([
|
|
457
|
+
execFileAsync('git', ['rev-parse', '--git-common-dir'], {
|
|
458
|
+
cwd: projectRoot,
|
|
459
|
+
}),
|
|
460
|
+
execFileAsync('git', ['config', '--get', 'remote.origin.url'], {
|
|
461
|
+
cwd: projectRoot,
|
|
462
|
+
}).catch(() => ({ stdout: '' })),
|
|
463
|
+
]);
|
|
464
|
+
const commonDir = commonDirOutput.trim();
|
|
465
|
+
const gitCommonDir = isAbsolute(commonDir)
|
|
466
|
+
? commonDir
|
|
467
|
+
: resolve(projectRoot, commonDir);
|
|
468
|
+
const repositoryIdentity = originOutput.trim() || `local-repository:${resolve(projectRoot)}`;
|
|
469
|
+
const locations = resolveRemoteStorageLocations({
|
|
470
|
+
repoRoot: projectRoot,
|
|
471
|
+
gitCommonDir,
|
|
472
|
+
repositoryIdentity,
|
|
473
|
+
stateStorage,
|
|
474
|
+
target: { kind: 'backlog', scope: 'shared', path: null },
|
|
475
|
+
});
|
|
476
|
+
return {
|
|
477
|
+
portableBindingsDir: locations.portable.bindingsDir,
|
|
478
|
+
operationalBindingsDir: locations.operational.bindingsDir,
|
|
479
|
+
operationsDir: locations.operational.operationsDir,
|
|
480
|
+
policy: rawConfig,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
const fallbackRoot = join(pjmRepoRoot, 'pjm', 'remote');
|
|
485
|
+
return {
|
|
486
|
+
portableBindingsDir: join(fallbackRoot, 'bindings'),
|
|
487
|
+
operationalBindingsDir: join(fallbackRoot, 'state', 'bindings'),
|
|
488
|
+
operationsDir: join(fallbackRoot, 'state', 'operations'),
|
|
489
|
+
policy: rawConfig,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
async function readRawRemoteConfig(projectRoot) {
|
|
494
|
+
const content = await readIfExists(join(projectRoot, '.oat', 'config.json'));
|
|
495
|
+
if (!content)
|
|
496
|
+
return undefined;
|
|
497
|
+
try {
|
|
498
|
+
const config = parseJsonConfig(content, join(projectRoot, '.oat', 'config.json'));
|
|
499
|
+
if (!isRecord(config) || !isRecord(config.pjm))
|
|
500
|
+
return undefined;
|
|
501
|
+
return config.pjm.remote;
|
|
502
|
+
}
|
|
503
|
+
catch {
|
|
504
|
+
return undefined;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
function isRecord(value) {
|
|
508
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
509
|
+
}
|
|
@@ -6,6 +6,7 @@ import { resolvePjmAdoption } from './adoption.js';
|
|
|
6
6
|
import { runPjmDoctorChecks } from './doctor.js';
|
|
7
7
|
import { initializeRepoReference } from './init.js';
|
|
8
8
|
import { migratePjmRepo, readPjmMigrationPrompt } from './migrate.js';
|
|
9
|
+
import { createPjmRemoteCommand } from './remote/index.js';
|
|
9
10
|
interface PjmCommandDependencies {
|
|
10
11
|
buildCommandContext: typeof buildCommandContext;
|
|
11
12
|
resolveProjectRoot: typeof resolveProjectRoot;
|
|
@@ -15,6 +16,7 @@ interface PjmCommandDependencies {
|
|
|
15
16
|
runPjmDoctorChecks: typeof runPjmDoctorChecks;
|
|
16
17
|
migratePjmRepo: typeof migratePjmRepo;
|
|
17
18
|
readPjmMigrationPrompt: typeof readPjmMigrationPrompt;
|
|
19
|
+
createPjmRemoteCommand: typeof createPjmRemoteCommand;
|
|
18
20
|
}
|
|
19
21
|
export declare function createPjmCommand(overrides?: Partial<PjmCommandDependencies>): Command;
|
|
20
22
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAA0B,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAA0B,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAiBxD,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;IACtD,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AA8FD,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC9C,OAAO,CA0LT"}
|