@bastani/atomic 0.5.25 → 0.5.26-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/.agents/skills/ado-commit/SKILL.md +92 -0
- package/.agents/skills/ado-create-pr/SKILL.md +209 -0
- package/.claude/settings.json +1 -0
- package/.mcp.json +5 -0
- package/.opencode/opencode.json +7 -1
- package/README.md +150 -116
- package/assets/settings.schema.json +2 -2
- package/dist/sdk/runtime/executor.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/open-claude-design/claude/index.d.ts +46 -0
- package/dist/sdk/workflows/builtin/open-claude-design/claude/index.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/copilot/index.d.ts +34 -0
- package/dist/sdk/workflows/builtin/open-claude-design/copilot/index.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/constants.d.ts +72 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/constants.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/design-system.d.ts +46 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/design-system.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/export.d.ts +32 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/export.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/import.d.ts +33 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/import.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/prompts.d.ts +106 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/prompts.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/scan.d.ts +50 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/scan.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/validation.d.ts +12 -0
- package/dist/sdk/workflows/builtin/open-claude-design/helpers/validation.d.ts.map +1 -0
- package/dist/sdk/workflows/builtin/open-claude-design/opencode/index.d.ts +36 -0
- package/dist/sdk/workflows/builtin/open-claude-design/opencode/index.d.ts.map +1 -0
- package/dist/services/config/atomic-config.d.ts +6 -0
- package/dist/services/config/atomic-config.d.ts.map +1 -1
- package/dist/services/config/scm-sync.d.ts +37 -0
- package/dist/services/config/scm-sync.d.ts.map +1 -0
- package/package.json +7 -7
- package/src/cli.ts +2 -2
- package/src/commands/cli/chat/index.ts +8 -1
- package/src/commands/cli/config.ts +34 -10
- package/src/commands/cli/init/index.ts +9 -0
- package/src/sdk/runtime/executor.ts +13 -0
- package/src/sdk/workflows/builtin/open-claude-design/claude/index.ts +499 -0
- package/src/sdk/workflows/builtin/open-claude-design/copilot/index.ts +507 -0
- package/src/sdk/workflows/builtin/open-claude-design/helpers/constants.ts +159 -0
- package/src/sdk/workflows/builtin/open-claude-design/helpers/design-system.ts +88 -0
- package/src/sdk/workflows/builtin/open-claude-design/helpers/export.ts +193 -0
- package/src/sdk/workflows/builtin/open-claude-design/helpers/import.ts +52 -0
- package/src/sdk/workflows/builtin/open-claude-design/helpers/prompts.ts +1110 -0
- package/src/sdk/workflows/builtin/open-claude-design/helpers/scan.ts +117 -0
- package/src/sdk/workflows/builtin/open-claude-design/helpers/validation.ts +38 -0
- package/src/sdk/workflows/builtin/open-claude-design/opencode/index.ts +570 -0
- package/src/services/config/atomic-config.ts +12 -0
- package/src/services/config/scm-sync.ts +174 -0
- package/src/services/config/settings.ts +19 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design.md persistence — loading, saving, and reading design system data.
|
|
3
|
+
*
|
|
4
|
+
* The Design.md file is a structured markdown document containing design
|
|
5
|
+
* tokens (colors, typography, spacing, components) extracted from the
|
|
6
|
+
* codebase and approved by the user via HIL. It serves as the single
|
|
7
|
+
* source of truth for all generation and refinement stages.
|
|
8
|
+
*/
|
|
9
|
+
/** Structured representation of the design system data. */
|
|
10
|
+
export interface DesignSystemData {
|
|
11
|
+
/** Raw markdown content of Design.md. */
|
|
12
|
+
raw: string;
|
|
13
|
+
/** Absolute path to the Design.md file. */
|
|
14
|
+
path: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Load an existing Design.md from the given path.
|
|
18
|
+
* Used when the user provides `--design-system=<path>`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadDesignSystem(designSystemPath: string): Promise<DesignSystemData>;
|
|
21
|
+
/**
|
|
22
|
+
* Persist the design system builder's output as Design.md in the project root.
|
|
23
|
+
*
|
|
24
|
+
* The builder stage produces a visible session where the agent constructs
|
|
25
|
+
* the Design.md content interactively with the user. We read the transcript
|
|
26
|
+
* and extract the final Design.md content that the agent wrote.
|
|
27
|
+
*
|
|
28
|
+
* For simplicity, the agent in the builder stage is instructed to write
|
|
29
|
+
* Design.md directly to disk. This function reads it back to populate
|
|
30
|
+
* the DesignSystemData for downstream stages.
|
|
31
|
+
*/
|
|
32
|
+
export declare function persistDesignSystem(root: string): Promise<DesignSystemData>;
|
|
33
|
+
/**
|
|
34
|
+
* Read the existing .impeccable.md brand context file, if present.
|
|
35
|
+
* Returns empty string if the file does not exist.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readImpeccableMd(root: string): Promise<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Derive a URL-safe slug from the user's prompt for directory naming.
|
|
40
|
+
*/
|
|
41
|
+
export declare function slugifyPrompt(prompt: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Ensure the scratch directory exists for intermediate workflow outputs.
|
|
44
|
+
*/
|
|
45
|
+
export declare function ensureScratchDir(root: string): Promise<string>;
|
|
46
|
+
//# sourceMappingURL=design-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-system.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/open-claude-design/helpers/design-system.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,2DAA2D;AAC3D,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAI3B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,gBAAgB,CAAC,CAI3B;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMpE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUpD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKpE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export engine — handoff bundle packaging.
|
|
3
|
+
*
|
|
4
|
+
* Writes the deterministic parts of the handoff bundle (no LLM call):
|
|
5
|
+
* - handoff-prompt.md — ready-to-use prompt for Claude Code
|
|
6
|
+
* - README.md — how to use the bundle
|
|
7
|
+
*
|
|
8
|
+
* The exporter stage (LLM) handles copying design files, writing
|
|
9
|
+
* design-intent.md and component-specs.md since those require
|
|
10
|
+
* understanding the generated design content.
|
|
11
|
+
*/
|
|
12
|
+
import type { DesignSystemData } from "./design-system.ts";
|
|
13
|
+
export interface HandoffBundleOptions {
|
|
14
|
+
designSystem: DesignSystemData;
|
|
15
|
+
prompt: string;
|
|
16
|
+
outputType: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Write the deterministic handoff bundle files.
|
|
20
|
+
*
|
|
21
|
+
* The exporter stage is responsible for:
|
|
22
|
+
* - Copying design files (index.html, styles.css, script.js) to design/
|
|
23
|
+
* - Writing design-intent.md from transcript analysis
|
|
24
|
+
* - Writing component-specs.md from design analysis
|
|
25
|
+
*
|
|
26
|
+
* This function writes the remaining deterministic files:
|
|
27
|
+
* - Design.md (copy of the design system)
|
|
28
|
+
* - handoff-prompt.md (ready-to-use implementation prompt)
|
|
29
|
+
* - README.md (bundle documentation)
|
|
30
|
+
*/
|
|
31
|
+
export declare function writeHandoffBundle(finalDesignDir: string, opts: HandoffBundleOptions): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/open-claude-design/helpers/export.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CAyBf"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import handler — input type detection and aggregation.
|
|
3
|
+
*
|
|
4
|
+
* Classifies the user's `--reference` input as a URL, file path, or
|
|
5
|
+
* neither, and aggregates all import sources into a structured context
|
|
6
|
+
* object that the generator consumes.
|
|
7
|
+
*/
|
|
8
|
+
/** Aggregated import context passed to the generator stage. */
|
|
9
|
+
export interface ImportContext {
|
|
10
|
+
/** The user's free-form design prompt. */
|
|
11
|
+
prompt: string;
|
|
12
|
+
/** Raw reference string (URL, file path, or empty). */
|
|
13
|
+
reference: string;
|
|
14
|
+
/** Extracted content from a web URL capture, or null. */
|
|
15
|
+
webCapture: string | null;
|
|
16
|
+
/** Extracted content from a parsed file, or null. */
|
|
17
|
+
fileParse: string | null;
|
|
18
|
+
}
|
|
19
|
+
/** Check whether the reference string looks like a URL. */
|
|
20
|
+
export declare function isUrl(reference: string): boolean;
|
|
21
|
+
/** Check whether the reference string looks like a file path. */
|
|
22
|
+
export declare function isFilePath(reference: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Aggregate all import results into a single context object.
|
|
25
|
+
* Pure deterministic function — no LLM call.
|
|
26
|
+
*/
|
|
27
|
+
export declare function aggregateImportResults(opts: {
|
|
28
|
+
prompt: string;
|
|
29
|
+
reference: string;
|
|
30
|
+
webCapture: string | null;
|
|
31
|
+
fileParse: string | null;
|
|
32
|
+
}): ImportContext;
|
|
33
|
+
//# sourceMappingURL=import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/open-claude-design/helpers/import.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,qDAAqD;IACrD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,2DAA2D;AAC3D,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAGhD;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAMrD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GAAG,aAAa,CAOhB"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt builders for the open-claude-design workflow.
|
|
3
|
+
*
|
|
4
|
+
* Each builder produces a focused, single-responsibility prompt for one
|
|
5
|
+
* stage of the 5-phase design pipeline. Context-engineering principles:
|
|
6
|
+
*
|
|
7
|
+
* - Position-aware framing: key context (design prompt, design system)
|
|
8
|
+
* at the TOP and BOTTOM of every prompt.
|
|
9
|
+
* - Forward-only data flow: downstream stages embed upstream outputs
|
|
10
|
+
* verbatim — no re-discovery.
|
|
11
|
+
* - Trailing-prose guarantee: every prompt asks for a short prose recap
|
|
12
|
+
* so transcript reads never return empty.
|
|
13
|
+
* - HIL via AskUserQuestion: explicit instructions to use the tool,
|
|
14
|
+
* never regular NL conversation, for user decisions.
|
|
15
|
+
*/
|
|
16
|
+
import type { ImportContext } from "./import.ts";
|
|
17
|
+
import type { DesignSystemData } from "./design-system.ts";
|
|
18
|
+
/** Phase 1 — headless: find CSS/Tailwind/design files in codebase. */
|
|
19
|
+
export declare function buildDesignLocatorPrompt(opts: {
|
|
20
|
+
root: string;
|
|
21
|
+
}): string;
|
|
22
|
+
/** Phase 1 — headless: extract colors, fonts, spacing from located files. */
|
|
23
|
+
export declare function buildDesignAnalyzerPrompt(opts: {
|
|
24
|
+
root: string;
|
|
25
|
+
}): string;
|
|
26
|
+
/** Phase 1 — headless: find existing component patterns in the codebase. */
|
|
27
|
+
export declare function buildDesignPatternPrompt(opts: {
|
|
28
|
+
root: string;
|
|
29
|
+
}): string;
|
|
30
|
+
/**
|
|
31
|
+
* Phase 1 — visible, HIL: present findings and build Design.md with
|
|
32
|
+
* user approval at each decision point.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildDesignSystemBuilderPrompt(opts: {
|
|
35
|
+
root: string;
|
|
36
|
+
locatorOutput: string;
|
|
37
|
+
analyzerOutput: string;
|
|
38
|
+
patternsOutput: string;
|
|
39
|
+
existingImpeccable: string;
|
|
40
|
+
}): string;
|
|
41
|
+
/** Phase 2 — headless: navigate URL, screenshot, extract DOM/CSS. */
|
|
42
|
+
export declare function buildWebCapturePrompt(opts: {
|
|
43
|
+
url: string;
|
|
44
|
+
screenshotDir: string;
|
|
45
|
+
}): string;
|
|
46
|
+
/** Phase 2 — headless: parse document reference (DOCX/PPTX/XLSX/image/PDF). */
|
|
47
|
+
export declare function buildFileParserPrompt(opts: {
|
|
48
|
+
filePath: string;
|
|
49
|
+
}): string;
|
|
50
|
+
/** Phase 3 — visible: generate first design version. */
|
|
51
|
+
export declare function buildGeneratorPrompt(opts: {
|
|
52
|
+
prompt: string;
|
|
53
|
+
outputType: string;
|
|
54
|
+
designSystem: DesignSystemData;
|
|
55
|
+
importContext: ImportContext;
|
|
56
|
+
root: string;
|
|
57
|
+
outputDir: string;
|
|
58
|
+
}): string;
|
|
59
|
+
/** Phase 4 — visible, HIL: collect user feedback on the current design. */
|
|
60
|
+
export declare function buildRefineFeedbackPrompt(opts: {
|
|
61
|
+
prompt: string;
|
|
62
|
+
designDir: string;
|
|
63
|
+
iteration: number;
|
|
64
|
+
maxIterations: number;
|
|
65
|
+
}): string;
|
|
66
|
+
/** Phase 4 — headless: automated design critique with structured output. */
|
|
67
|
+
export declare function buildCritiquePrompt(opts: {
|
|
68
|
+
designDir: string;
|
|
69
|
+
designSystem: DesignSystemData;
|
|
70
|
+
userFeedback: string;
|
|
71
|
+
}): string;
|
|
72
|
+
/** Phase 4 — headless: visual validation via playwright screenshot. */
|
|
73
|
+
export declare function buildScreenshotValidationPrompt(opts: {
|
|
74
|
+
designDir: string;
|
|
75
|
+
scratchDir: string;
|
|
76
|
+
}): string;
|
|
77
|
+
/** Phase 4 — visible: apply feedback + critique findings to the design. */
|
|
78
|
+
export declare function buildApplyChangesPrompt(opts: {
|
|
79
|
+
prompt: string;
|
|
80
|
+
designDir: string;
|
|
81
|
+
designSystem: DesignSystemData;
|
|
82
|
+
userFeedback: string;
|
|
83
|
+
critiqueOutput: string;
|
|
84
|
+
screenshotOutput: string;
|
|
85
|
+
scanFindings: string;
|
|
86
|
+
iteration: number;
|
|
87
|
+
}): string;
|
|
88
|
+
/**
|
|
89
|
+
* Phase 4 — visible: final deterministic gate. Runs when the post-loop
|
|
90
|
+
* scanner still reports findings. The agent MUST remove every one before
|
|
91
|
+
* export; no ambiguity, no negotiation, no new features.
|
|
92
|
+
*/
|
|
93
|
+
export declare function buildForcedFixPrompt(opts: {
|
|
94
|
+
designDir: string;
|
|
95
|
+
designSystem: DesignSystemData;
|
|
96
|
+
scanFindings: string;
|
|
97
|
+
}): string;
|
|
98
|
+
/** Phase 5 — visible: export design and create output-type-tailored assets. */
|
|
99
|
+
export declare function buildExportPrompt(opts: {
|
|
100
|
+
prompt: string;
|
|
101
|
+
designDir: string;
|
|
102
|
+
finalDesignDir: string;
|
|
103
|
+
designSystem: DesignSystemData;
|
|
104
|
+
outputType: string;
|
|
105
|
+
}): string;
|
|
106
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/open-claude-design/helpers/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic impeccable scan — runs the `impeccable detect --json` CLI
|
|
3
|
+
* against a design directory and returns structured findings.
|
|
4
|
+
*
|
|
5
|
+
* No LLM call; the refinement loop surfaces these findings to the
|
|
6
|
+
* apply-changes stage so the agent can fix banned anti-patterns
|
|
7
|
+
* alongside user feedback.
|
|
8
|
+
*/
|
|
9
|
+
/** Shape of a single finding emitted by `impeccable detect --json`. */
|
|
10
|
+
export interface ScanFinding {
|
|
11
|
+
readonly antipattern: string;
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly description: string;
|
|
14
|
+
readonly file: string;
|
|
15
|
+
readonly line: number;
|
|
16
|
+
readonly snippet: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Result of running the scanner. Discriminated on `available` so callers
|
|
20
|
+
* can distinguish "ran successfully, no findings" from "scanner missing".
|
|
21
|
+
*/
|
|
22
|
+
export type ScanResult = {
|
|
23
|
+
readonly available: true;
|
|
24
|
+
readonly findings: readonly ScanFinding[];
|
|
25
|
+
} | {
|
|
26
|
+
readonly available: false;
|
|
27
|
+
readonly reason: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Run `impeccable detect --json` against `designDir`. The CLI exits 0
|
|
31
|
+
* whether or not findings exist, so we parse the JSON array and return
|
|
32
|
+
* its length. If the CLI is missing or its output is not parseable,
|
|
33
|
+
* return `{ available: false, reason }` so the caller can gracefully
|
|
34
|
+
* proceed without scan input.
|
|
35
|
+
*/
|
|
36
|
+
export declare function runImpeccableScan(designDir: string): Promise<ScanResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Returns true iff the scanner ran successfully AND reported at least
|
|
39
|
+
* one finding. Narrows the union so callers can access `findings`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function hasBlockingFindings(scan: ScanResult): scan is {
|
|
42
|
+
available: true;
|
|
43
|
+
findings: readonly ScanFinding[];
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Render findings as a human-readable block for inclusion in agent
|
|
47
|
+
* prompts. Groups by anti-pattern id, lists each file:line with snippet.
|
|
48
|
+
*/
|
|
49
|
+
export declare function renderScanFindings(findings: readonly ScanFinding[]): string;
|
|
50
|
+
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/open-claude-design/helpers/scan.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,uEAAuE;AACvE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,CAuCrB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,GACf,IAAI,IAAI;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE,CAE/D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAC/B,MAAM,CAqBR"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation helpers — refinement loop exit detection and critique parsing.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Detect whether the user signaled "done" via AskUserQuestion in the
|
|
6
|
+
* feedback stage. The feedback stage's prompt instructs the agent to
|
|
7
|
+
* include one of the completion signal phrases when the user approves.
|
|
8
|
+
*
|
|
9
|
+
* Returns `true` if the refinement loop should exit.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isRefinementComplete(feedbackResult: string): boolean;
|
|
12
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/open-claude-design/helpers/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoBH;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAQpE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* open-claude-design / opencode
|
|
3
|
+
*
|
|
4
|
+
* OpenCode replica of the Claude open-claude-design workflow. Orchestrates
|
|
5
|
+
* the design skill ecosystem (impeccable, critique, shape, polish, audit,
|
|
6
|
+
* etc.) into a deterministic 5-phase pipeline:
|
|
7
|
+
*
|
|
8
|
+
* Phase 1: Design System Onboarding — extract tokens, build Design.md (HIL)
|
|
9
|
+
* Phase 2: Import — aggregate text/URL/file references
|
|
10
|
+
* Phase 3: Generation — produce first design version
|
|
11
|
+
* Phase 4: Refinement Loop — bounded iterate with critique + user feedback
|
|
12
|
+
* Phase 5: Export/Handoff — HTML export + Claude Code handoff bundle
|
|
13
|
+
*
|
|
14
|
+
* OpenCode-specific concerns (see references/failure-modes.md):
|
|
15
|
+
*
|
|
16
|
+
* • F5 — every `ctx.stage()` is a FRESH session. Every specialist receives
|
|
17
|
+
* its required context verbatim in its first prompt.
|
|
18
|
+
* • F3 — `result.data!.parts` is a heterogenous array (text/tool/reasoning/
|
|
19
|
+
* file parts). Use `extractResponseText()` to filter to text parts only;
|
|
20
|
+
* concatenating raw `parts` produces `[object Object]` strings.
|
|
21
|
+
* • F6 — every prompt explicitly requires trailing prose so transcripts and
|
|
22
|
+
* `extractResponseText()` reads are never empty.
|
|
23
|
+
* • F9 — `s.save()` receives the unwrapped `{ info, parts }` payload from
|
|
24
|
+
* `result.data!`; passing the full `result` breaks downstream reads.
|
|
25
|
+
*
|
|
26
|
+
* Sub-agents are dispatched via the `agent` parameter on
|
|
27
|
+
* `s.client.session.prompt()` (OpenCode's SDK-native way to route a turn
|
|
28
|
+
* to a named sub-agent).
|
|
29
|
+
*
|
|
30
|
+
* See claude/index.ts for the full topology diagram and design rationale.
|
|
31
|
+
*
|
|
32
|
+
* Run: atomic workflow -n open-claude-design -a opencode "design a dashboard"
|
|
33
|
+
*/
|
|
34
|
+
declare const _default: import("../../../index.ts").WorkflowDefinition<"opencode", "prompt" | "reference" | "output-type" | "design-system">;
|
|
35
|
+
export default _default;
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/sdk/workflows/builtin/open-claude-design/opencode/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;;AAoDH,wBAqea"}
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* 2) global `~/.atomic/settings.json` (default fallback)
|
|
8
8
|
*/
|
|
9
9
|
import { type AgentKey, type ProviderOverrides } from "./index.ts";
|
|
10
|
+
/** Source control providers Atomic can auto-configure MCP servers for. */
|
|
11
|
+
export declare const SCM_PROVIDERS: readonly ["github", "azure-devops", "sapling"];
|
|
12
|
+
export type ScmProvider = (typeof SCM_PROVIDERS)[number];
|
|
13
|
+
export declare function isScmProvider(value: unknown): value is ScmProvider;
|
|
10
14
|
/**
|
|
11
15
|
* Atomic project configuration schema.
|
|
12
16
|
*/
|
|
@@ -15,6 +19,8 @@ export interface AtomicConfig {
|
|
|
15
19
|
version?: number;
|
|
16
20
|
/** Timestamp of last init */
|
|
17
21
|
lastUpdated?: string;
|
|
22
|
+
/** Selected source control provider (drives MCP server enable/disable sync). */
|
|
23
|
+
scm?: ScmProvider;
|
|
18
24
|
/** Per-provider overrides for chatFlags and envVars */
|
|
19
25
|
providers?: Partial<Record<AgentKey, ProviderOverrides>>;
|
|
20
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-config.d.ts","sourceRoot":"","sources":["../../../src/services/config/atomic-config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAOnE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;CAC1D;
|
|
1
|
+
{"version":3,"file":"atomic-config.d.ts","sourceRoot":"","sources":["../../../src/services/config/atomic-config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAOnE,0EAA0E;AAC1E,eAAO,MAAM,aAAa,gDAAiD,CAAC;AAC5E,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;CAC1D;AA0HD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAMvF;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAG5B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source-control-driven MCP server enable/disable sync.
|
|
3
|
+
*
|
|
4
|
+
* When the user sets `scm` in `.atomic/settings.json` to one of
|
|
5
|
+
* `github`, `azure-devops`, or `sapling`, Atomic keeps the corresponding
|
|
6
|
+
* MCP servers in the project's agent configs consistent on every
|
|
7
|
+
* `atomic chat` / `atomic workflow` startup:
|
|
8
|
+
*
|
|
9
|
+
* - `.claude/settings.json` → updates the `disabledMcpjsonServers` array
|
|
10
|
+
* - `.opencode/opencode.json` → flips `mcp.<server>.enabled` flags
|
|
11
|
+
*
|
|
12
|
+
* Only servers that already exist in the config are touched — we never
|
|
13
|
+
* add MCP server definitions the user didn't set up. Files that don't
|
|
14
|
+
* exist are skipped (the user may not use that agent).
|
|
15
|
+
*/
|
|
16
|
+
import type { ScmProvider } from "./atomic-config.ts";
|
|
17
|
+
/**
|
|
18
|
+
* Pure helper: returns the `--disable-mcp-server <name>` flag sequence to
|
|
19
|
+
* append when spawning Copilot CLI, given a selected scm provider.
|
|
20
|
+
*
|
|
21
|
+
* Copilot has no on-disk MCP server enable/disable store, so Atomic
|
|
22
|
+
* injects the flags on the CLI invocation instead. Returns an empty
|
|
23
|
+
* array when scm is unset so callers can spread unconditionally.
|
|
24
|
+
*/
|
|
25
|
+
export declare function copilotScmDisableFlags(scm: ScmProvider | undefined): string[];
|
|
26
|
+
/**
|
|
27
|
+
* Resolve Copilot's scm-derived `--disable-mcp-server` flags from the
|
|
28
|
+
* project's atomic config. Best-effort — returns `[]` on any failure.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getCopilotScmDisableFlags(projectRoot: string): Promise<string[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Apply the current `scm` selection to the project's agent config files.
|
|
33
|
+
* No-op when `scm` is unset. Swallows errors so a malformed agent
|
|
34
|
+
* config never blocks `atomic chat` / `atomic workflow` startup.
|
|
35
|
+
*/
|
|
36
|
+
export declare function syncScmMcpServers(projectRoot: string): Promise<void>;
|
|
37
|
+
//# sourceMappingURL=scm-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scm-sync.d.ts","sourceRoot":"","sources":["../../../src/services/config/scm-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAatD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,EAAE,CAQ7E;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CAOnB;AA4FD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAc1E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.26-0",
|
|
4
4
|
"description": "Configuration management CLI and SDK for coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -70,18 +70,18 @@
|
|
|
70
70
|
"@types/bun": "^1.3.12",
|
|
71
71
|
"@types/react": "^19.2.14",
|
|
72
72
|
"lefthook": "^2.1.6",
|
|
73
|
-
"oxlint": "^1.
|
|
74
|
-
"typescript": "^6.0.
|
|
73
|
+
"oxlint": "^1.61.0",
|
|
74
|
+
"typescript": "^6.0.3",
|
|
75
75
|
"typescript-language-server": "^5.1.3"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.
|
|
78
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.116",
|
|
79
79
|
"@clack/prompts": "^1.2.0",
|
|
80
80
|
"@commander-js/extra-typings": "^14.0.0",
|
|
81
81
|
"@github/copilot-sdk": "^0.2.2",
|
|
82
|
-
"@opencode-ai/sdk": "^1.
|
|
83
|
-
"@opentui/core": "^0.1.
|
|
84
|
-
"@opentui/react": "^0.1.
|
|
82
|
+
"@opencode-ai/sdk": "^1.14.19",
|
|
83
|
+
"@opentui/core": "^0.1.102",
|
|
84
|
+
"@opentui/react": "^0.1.102",
|
|
85
85
|
"commander": "^14.0.3",
|
|
86
86
|
"ignore": "^7.0.5",
|
|
87
87
|
"yaml": "^2.8.3",
|
package/src/cli.ts
CHANGED
|
@@ -318,8 +318,8 @@ Examples:
|
|
|
318
318
|
configCmd
|
|
319
319
|
.command("set")
|
|
320
320
|
.description("Set a configuration value")
|
|
321
|
-
.argument("<key>", "Configuration key (
|
|
322
|
-
.argument("<value>", "Value to set (
|
|
321
|
+
.argument("<key>", "Configuration key (telemetry | scm)")
|
|
322
|
+
.argument("<value>", "Value to set (telemetry: true|false; scm: github|azure-devops|sapling)")
|
|
323
323
|
.action(async (key: string, value: string) => {
|
|
324
324
|
const { configCommand } = await import("./commands/cli/config.ts");
|
|
325
325
|
const exitCode = await configCommand("set", key, value);
|
|
@@ -18,6 +18,7 @@ import { homedir } from "node:os";
|
|
|
18
18
|
import { mkdir, writeFile, rm } from "node:fs/promises";
|
|
19
19
|
import { AGENT_CONFIG, type AgentKey } from "../../../services/config/index.ts";
|
|
20
20
|
import { getProviderOverrides } from "../../../services/config/atomic-config.ts";
|
|
21
|
+
import { getCopilotScmDisableFlags } from "../../../services/config/scm-sync.ts";
|
|
21
22
|
import { ensureProjectSetup } from "../init/index.ts";
|
|
22
23
|
import { COLORS } from "../../../theme/colors.ts";
|
|
23
24
|
import { isCommandInstalled } from "../../../services/system/detect.ts";
|
|
@@ -83,7 +84,13 @@ export async function buildAgentArgs(
|
|
|
83
84
|
|
|
84
85
|
const flags = overrides.chatFlags ?? [...config.chat_flags];
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
// Copilot has no on-disk MCP toggle — `--disable-mcp-server <name>` is
|
|
88
|
+
// the equivalent of flipping `enabled: false` in .opencode/opencode.json
|
|
89
|
+
// or adding to `disabledMcpjsonServers` in .claude/settings.json.
|
|
90
|
+
const scmFlags =
|
|
91
|
+
agentType === "copilot" ? await getCopilotScmDisableFlags(projectRoot) : [];
|
|
92
|
+
|
|
93
|
+
return [...flags, ...scmFlags, ...passthroughArgs];
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
function generateChatId(): string {
|
|
@@ -5,10 +5,17 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Currently supported:
|
|
7
7
|
* atomic config set telemetry true|false
|
|
8
|
+
* atomic config set scm github|azure-devops|sapling
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
import { log } from "@clack/prompts";
|
|
11
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
setScmProvider,
|
|
14
|
+
setTelemetryEnabled,
|
|
15
|
+
} from "../../services/config/settings.ts";
|
|
16
|
+
import { SCM_PROVIDERS, isScmProvider } from "../../services/config/atomic-config.ts";
|
|
17
|
+
|
|
18
|
+
const SUPPORTED_KEYS = ["telemetry", "scm"] as const;
|
|
12
19
|
|
|
13
20
|
/**
|
|
14
21
|
* Execute the config command
|
|
@@ -33,24 +40,41 @@ export async function configCommand(
|
|
|
33
40
|
return 1;
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
if (
|
|
37
|
-
log.error(
|
|
43
|
+
if (!(SUPPORTED_KEYS as readonly string[]).includes(key)) {
|
|
44
|
+
log.error(
|
|
45
|
+
`Unknown config key: ${key}. Supported keys: ${SUPPORTED_KEYS.join(", ")}.`,
|
|
46
|
+
);
|
|
38
47
|
return 1;
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
if (!value) {
|
|
42
|
-
log.error(
|
|
51
|
+
log.error(`Missing value. Usage: atomic config set ${key} <value>`);
|
|
43
52
|
return 1;
|
|
44
53
|
}
|
|
45
54
|
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
if (key === "telemetry") {
|
|
56
|
+
if (value !== "true" && value !== "false") {
|
|
57
|
+
log.error(`Invalid value: ${value}. Must be 'true' or 'false'.`);
|
|
58
|
+
return 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const enabled = value === "true";
|
|
62
|
+
await setTelemetryEnabled(enabled);
|
|
63
|
+
log.success(`Telemetry has been ${enabled ? "enabled" : "disabled"}.`);
|
|
64
|
+
return 0;
|
|
49
65
|
}
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
67
|
+
// key === "scm"
|
|
68
|
+
if (!isScmProvider(value)) {
|
|
69
|
+
log.error(
|
|
70
|
+
`Invalid value: ${value}. Must be one of: ${SCM_PROVIDERS.join(", ")}.`,
|
|
71
|
+
);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
53
74
|
|
|
54
|
-
|
|
75
|
+
await setScmProvider(value);
|
|
76
|
+
log.success(
|
|
77
|
+
`Source control provider set to ${value}. The GitHub and Azure DevOps MCP servers in .claude/settings.json and .opencode/opencode.json will be reconciled on the next 'atomic chat' or 'atomic workflow' run.`,
|
|
78
|
+
);
|
|
55
79
|
return 0;
|
|
56
80
|
}
|
|
@@ -8,11 +8,19 @@
|
|
|
8
8
|
|
|
9
9
|
import type { AgentKey } from "../../../services/config/index.ts";
|
|
10
10
|
import { getConfigRoot } from "../../../services/config/config-path.ts";
|
|
11
|
+
import { syncScmMcpServers } from "../../../services/config/scm-sync.ts";
|
|
11
12
|
import { applyManagedOnboardingFiles } from "./onboarding.ts";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Ensure the project is configured for the given agent. Idempotent — safe
|
|
15
16
|
* to call on every `atomic chat` invocation.
|
|
17
|
+
*
|
|
18
|
+
* Runs in two phases:
|
|
19
|
+
* 1. Copy/merge bundled onboarding files into the project.
|
|
20
|
+
* 2. Reconcile the SCM MCP-server enable/disable state in the agent
|
|
21
|
+
* configs to match the user's `scm` selection in `.atomic/settings.json`.
|
|
22
|
+
* Order matters: the onboarding step may have just written the
|
|
23
|
+
* baseline configs.
|
|
16
24
|
*/
|
|
17
25
|
export async function ensureProjectSetup(
|
|
18
26
|
agentKey: AgentKey,
|
|
@@ -20,4 +28,5 @@ export async function ensureProjectSetup(
|
|
|
20
28
|
): Promise<void> {
|
|
21
29
|
const configRoot = getConfigRoot();
|
|
22
30
|
await applyManagedOnboardingFiles(agentKey, projectRoot, configRoot);
|
|
31
|
+
await syncScmMcpServers(projectRoot);
|
|
23
32
|
}
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
type ProviderOverrides,
|
|
40
40
|
} from "../../services/config/definitions.ts";
|
|
41
41
|
import { getProviderOverrides } from "../../services/config/atomic-config.ts";
|
|
42
|
+
import { getCopilotScmDisableFlags } from "../../services/config/scm-sync.ts";
|
|
42
43
|
import { ensureDir } from "../../services/system/copy.ts";
|
|
43
44
|
import type { SessionEvent } from "@github/copilot-sdk";
|
|
44
45
|
import type { SessionPromptResponse } from "@opencode-ai/sdk/v2";
|
|
@@ -281,6 +282,7 @@ function buildPaneCommand(
|
|
|
281
282
|
agent: AgentType,
|
|
282
283
|
port: number,
|
|
283
284
|
overrides: ProviderOverrides = {},
|
|
285
|
+
extraChatFlags: string[] = [],
|
|
284
286
|
): { command: string; envVars: Record<string, string> } {
|
|
285
287
|
const {
|
|
286
288
|
cmd,
|
|
@@ -301,6 +303,7 @@ function buildPaneCommand(
|
|
|
301
303
|
"--port",
|
|
302
304
|
String(port),
|
|
303
305
|
...chatFlags,
|
|
306
|
+
...extraChatFlags,
|
|
304
307
|
].join(" "),
|
|
305
308
|
envVars,
|
|
306
309
|
};
|
|
@@ -1141,6 +1144,12 @@ interface SharedRunnerState {
|
|
|
1141
1144
|
inputs: Record<string, string>;
|
|
1142
1145
|
/** User-configured provider overrides (global + local merged). */
|
|
1143
1146
|
providerOverrides: ProviderOverrides;
|
|
1147
|
+
/**
|
|
1148
|
+
* Extra CLI flags appended to the agent's chat flags, derived from
|
|
1149
|
+
* the project's scm selection. Currently only populated for Copilot
|
|
1150
|
+
* (which has no on-disk MCP toggle — see `getCopilotScmDisableFlags`).
|
|
1151
|
+
*/
|
|
1152
|
+
extraChatFlags: string[];
|
|
1144
1153
|
panel: OrchestratorPanel;
|
|
1145
1154
|
/** Sessions that have been spawned (for name uniqueness + cleanup). */
|
|
1146
1155
|
activeRegistry: Map<string, ActiveSession>;
|
|
@@ -1420,6 +1429,7 @@ function createSessionRunner(
|
|
|
1420
1429
|
shared.agent,
|
|
1421
1430
|
port,
|
|
1422
1431
|
shared.providerOverrides,
|
|
1432
|
+
shared.extraChatFlags,
|
|
1423
1433
|
);
|
|
1424
1434
|
|
|
1425
1435
|
// ── 7. Create tmux window or headless execution ──
|
|
@@ -1789,6 +1799,8 @@ export async function runOrchestrator(): Promise<void> {
|
|
|
1789
1799
|
process.chdir(cwd);
|
|
1790
1800
|
|
|
1791
1801
|
const providerOverrides = await getProviderOverrides(agent, cwd);
|
|
1802
|
+
const extraChatFlags =
|
|
1803
|
+
agent === "copilot" ? await getCopilotScmDisableFlags(cwd) : [];
|
|
1792
1804
|
const sessionsBaseDir = join(getSessionsBaseDir(), workflowRunId);
|
|
1793
1805
|
await ensureDir(sessionsBaseDir);
|
|
1794
1806
|
|
|
@@ -1856,6 +1868,7 @@ export async function runOrchestrator(): Promise<void> {
|
|
|
1856
1868
|
agent,
|
|
1857
1869
|
inputs,
|
|
1858
1870
|
providerOverrides,
|
|
1871
|
+
extraChatFlags,
|
|
1859
1872
|
panel,
|
|
1860
1873
|
activeRegistry: new Map(),
|
|
1861
1874
|
completedRegistry: new Map(),
|