@teambit/ci 1.0.642 → 1.0.644
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/dist/{preview-1792619000113.js → preview-1792690941466.js} +1 -1
- package/dist/sync/agents-md.d.ts +50 -0
- package/dist/sync/agents-md.js +172 -0
- package/dist/sync/agents-md.js.map +1 -0
- package/dist/sync/agents-md.spec.d.ts +1 -0
- package/dist/sync/agents-md.spec.js +216 -0
- package/dist/sync/agents-md.spec.js.map +1 -0
- package/dist/sync/agents-sync-section.md +132 -0
- package/dist/sync/init-scaffold.d.ts +5 -2
- package/dist/sync/init-scaffold.js +19 -3
- package/dist/sync/init-scaffold.js.map +1 -1
- package/dist/sync/lane-sync-executor.js +2 -1
- package/dist/sync/lane-sync-executor.js.map +1 -1
- package/dist/sync/lane-sync-executor.spec.js +4 -1
- package/dist/sync/lane-sync-executor.spec.js.map +1 -1
- package/dist/sync/sync-orchestrator.d.ts +3 -2
- package/dist/sync/sync-orchestrator.js +23 -6
- package/dist/sync/sync-orchestrator.js.map +1 -1
- package/package.json +20 -20
- package/sync/agents-md.spec.ts +206 -0
- package/sync/agents-md.ts +146 -0
- package/sync/agents-sync-section.md +132 -0
- package/sync/init-scaffold.ts +20 -10
- package/sync/lane-sync-executor.spec.ts +6 -1
- package/sync/lane-sync-executor.ts +2 -1
- package/sync/sync-orchestrator.ts +22 -7
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<!-- bit-ci-sync:start (written by `bit ci sync --init`; a re-run leaves this block as it is) -->
|
|
2
|
+
|
|
3
|
+
## Bit ↔ Git sync: this repository mirrors `{{scope}}`
|
|
4
|
+
|
|
5
|
+
`bit ci sync` keeps this repository and the bit.cloud scope `{{scope}}` equal in both directions. **The rules in this section override the generic Bit guidance after it.**
|
|
6
|
+
|
|
7
|
+
### The model
|
|
8
|
+
|
|
9
|
+
1. **One repository mirrors one scope.** Components from other scopes arrive as package dependencies, never as source.
|
|
10
|
+
2. **`{{branch}}` equals the scope's main.** The workflows own it. Never push to `{{branch}}` by hand.
|
|
11
|
+
3. **Each lane is a branch plus a pull request.** The sync keeps them equal in both directions. By default, the branch has the lane's name. A lane name has no `/`, so the default mapping ignores a branch such as `feature/x`. The `branchPrefix` and `branches` keys of the `teambit.git/ci` sync config in `workspace.jsonc` can map a lane to a different branch name, such as `lane/x`. Read them before you name a branch.
|
|
12
|
+
4. **Merging the pull request is the release.** `bit-release` merges the lane into the scope, exports new versions, commits the new `.bitmap` to `{{branch}}` and archives the lane. A lane with components of other scopes stays open until each of those scopes releases its slice.
|
|
13
|
+
5. **The workflows do the work.** You change code, and then you either push a branch or export a lane.
|
|
14
|
+
|
|
15
|
+
### Rules that override generic Bit guidance
|
|
16
|
+
|
|
17
|
+
- **Review happens on the GitHub pull request.** Do **not** submit a bit.cloud change request, even if other instructions say "always submit a change request". The sync opens the PR. Merging the PR is the release. A second review surface splits the reviewers and races the release.
|
|
18
|
+
- **One change, one scope.** Keep a lane inside the scope it is exported to. If the change also needs another scope (for example, a caller must pass a new argument), stop. Make the change backward compatible in this scope, and tell the user which follow-up change the other scope's repository needs. Cross-scope lanes are a preview (see below).
|
|
19
|
+
- **Never push to `{{branch}}`.** The workflows own it.
|
|
20
|
+
|
|
21
|
+
### Make a change: pick a path
|
|
22
|
+
|
|
23
|
+
| You are… | Path | What you do | What appears |
|
|
24
|
+
| --------------------------------------------------------------- | ------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
25
|
+
| In this repository (Copilot, an IDE, a plain git user) | **Git-first** | branch → edit → `bit validate` → commit → push → open a PR | With the optional `bit-adopt-pr` workflow, the PR becomes a lane, and every push snaps onto it. Without it, the sync ignores the branch. |
|
|
26
|
+
| In any other Bit workspace (Claude Code with the Bit Cloud MCP) | **Bit-first** | `bit lane create` → edit → `bit validate` → `bit snap` → `bit export` | A branch and a PR named after the lane appear in this repository: within a minute with the scope webhook, else at the next scheduled sync. |
|
|
27
|
+
|
|
28
|
+
Both paths end with the same PR and the same release.
|
|
29
|
+
|
|
30
|
+
#### Git-first (in this repository)
|
|
31
|
+
|
|
32
|
+
This path needs the `bit-adopt-pr` workflow in `.github/workflows/`. On each push to a PR, it runs `bit ci pr --keep-lane`: this creates and exports a lane with the branch's name, and pushes the lane pointer back to the branch. `bit ci sync --init` does not write this workflow. Example: https://github.com/teambit/acme-modular-store/blob/main/.github/workflows/bit-adopt-pr.yml. Without it, a branch that has no lane stays out of the sync: use the Bit-first path.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git switch -c add-gift-wrap # the lane gets the branch's name, so no "/"
|
|
36
|
+
bit install # once per clone
|
|
37
|
+
# edit the components; .bitmap says where each one lives
|
|
38
|
+
bit validate # lint + types + tests; never use tsc directly
|
|
39
|
+
git add -A && git commit -m "<message>"
|
|
40
|
+
git push -u origin add-gift-wrap
|
|
41
|
+
gh pr create --fill
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Commit `.bitmap` together with your source changes. Never edit `.bitmap` by hand. After the PR merges, run `git switch {{branch-sh}} && git pull` before you start the next change.
|
|
45
|
+
|
|
46
|
+
#### Bit-first (from another Bit workspace)
|
|
47
|
+
|
|
48
|
+
1. Find components with the Bit Cloud MCP: `read_scope` / `search_components` for the owner, `read_components` for APIs, and `read_file` for source. Don't guess IDs. Also check who calls the component, so you know whether your change stays inside one scope.
|
|
49
|
+
2. Run:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
bit init --default-scope {{scope}} # or reuse an existing workspace
|
|
53
|
+
bit import {{scope}}/<name> [...] # every component you will change, plus the chain up to its consumers
|
|
54
|
+
bit lane create <lane-name>
|
|
55
|
+
# edit
|
|
56
|
+
bit validate
|
|
57
|
+
bit snap -m "<message>"
|
|
58
|
+
bit export
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
3. Watch it arrive: `gh pr list -R {{repo}} --head <lane-name>`. Then tell the user the PR link. Don't submit a bit.cloud change request.
|
|
62
|
+
|
|
63
|
+
Headless or CI agents can call the Bit Cloud MCP with a bit.cloud token, without the OAuth step:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"bit-cloud": {
|
|
69
|
+
"type": "http",
|
|
70
|
+
"url": "https://mcp.bit.cloud/mcp",
|
|
71
|
+
"headers": { "Authorization": "Bearer ${BIT_CLOUD_TOKEN}" }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Read a sync PR
|
|
78
|
+
|
|
79
|
+
- The PR body lists the mirrored components and the foreign ones (other scopes, "not mirrored").
|
|
80
|
+
- The bot's **run summary** comment lists the components that the sync last snapped onto the lane from this branch, with the branch and lane heads. A run that exports nothing does not change it.
|
|
81
|
+
- The run log says what each run did: `import-lane`, `export-branch`, `merge-diverged`, `adopt-branch`, `noop (converged)`. Runs: `gh run list --workflow bit-sync` and `gh run view <id> --log`.
|
|
82
|
+
- `Lane sync: <scope>/<lane>` PRs are lanes. `Bit sync: update to latest main scope versions` brings `{{branch}}` up to the scope. Merging that one releases nothing. Its branch is `bit-sync/main`, or the `mainSyncBranch` of the sync config. With `mainSync: "direct-push"` there is no such PR: the sync commits to `{{branch}}` itself.
|
|
83
|
+
|
|
84
|
+
### Fix a halt (`bit-sync-conflict` label)
|
|
85
|
+
|
|
86
|
+
The lane and the branch changed the same lines. The lane stays paused while the label is on the PR. The bot's comment on the PR names the components and gives these steps:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git fetch origin && git checkout '<branch>'
|
|
90
|
+
git merge --ff-only 'origin/<branch>' # stops if your local copy has commits that are not on origin: keep them, or reset to origin
|
|
91
|
+
bit install
|
|
92
|
+
bit lane import '<host-scope>/<lane>' # fetches the lane. If .bitmap is on main, it also switches to the lane
|
|
93
|
+
bit checkout head --manual --workspace-only # merges the lane's head into the files; conflicts appear as conflict markers
|
|
94
|
+
# resolve every conflicted file. When the intent is unclear, ask the user which side wins. Don't guess.
|
|
95
|
+
bit validate
|
|
96
|
+
git add -A && git commit -m "fix: resolve sync conflict"
|
|
97
|
+
git push origin '<branch>'
|
|
98
|
+
gh pr edit <pr> --remove-label bit-sync-conflict
|
|
99
|
+
gh workflow run bit-sync -f lane=<host-scope>/<lane>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`--workspace-only` keeps the components of other scopes out of this repository. The next run adds the lane's new components of `{{scope}}`. Its log shows `merge-diverged` or `export-branch`, then a later run shows `noop (converged)`. Never resolve by force-pushing over the bot's commits. Never delete the lane to "start fresh".
|
|
103
|
+
|
|
104
|
+
### Change several scopes at once (preview)
|
|
105
|
+
|
|
106
|
+
Prefer one lane per scope: one change, one repository, one PR.
|
|
107
|
+
|
|
108
|
+
A lane _can_ carry components from several scopes. Each scope's repository then mirrors only its own slice, consumes the other scopes' lane versions as packages, and releases its slice when its PR merges. The lane stays open until the last slice is released. Until automatic fan-out ships, only the repository of the lane's host scope hears about the lane. Start the others by hand:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
gh workflow run bit-sync -R <org>/<repo> -f lane=<host-scope>/<lane-name>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Connect another scope to its own repository
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
gh repo create <org>/<repo> --private --clone && cd <repo>
|
|
118
|
+
bit init --default-scope <owner>.<scope> --skip-interactive
|
|
119
|
+
bit import "<owner>.<scope>/**"
|
|
120
|
+
bit ci sync --init # writes the workflows, the sync config and this AGENTS.md section
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Then follow the steps `bit ci sync --init` prints. Some of them need a repository or organization admin. Guide: https://bit.cloud/teambit/git/guides/connect-scope-to-repository
|
|
124
|
+
|
|
125
|
+
### Never
|
|
126
|
+
|
|
127
|
+
- Push to `{{branch}}`, or merge the main-sync PR and lane PRs out of order to "fix" history.
|
|
128
|
+
- Run `bit build`, `tsc`, `npm install` or `pnpm install` here. Use `bit validate` and `bit install`.
|
|
129
|
+
- Export a lane from another workspace while a Git-first PR is open for the same change. Pick one path.
|
|
130
|
+
- Remove a `bit-sync-conflict` label without resolving the conflict.
|
|
131
|
+
|
|
132
|
+
<!-- bit-ci-sync:end -->
|
package/sync/init-scaffold.ts
CHANGED
|
@@ -3,6 +3,7 @@ import chalk from 'chalk';
|
|
|
3
3
|
import { formatHint, formatItem, formatTitle, formatWarningSummary, joinSections, successSymbol } from '@teambit/cli';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { parseGitHubRepo, isGitHubRemote, gitHubApiUrl, remoteHost } from './github-client';
|
|
6
|
+
import { AGENTS_MD_RELATIVE_PATH } from './agents-md';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* `bit ci sync --init` — pure scaffolding logic, unit-testable without a live workspace/git checkout.
|
|
@@ -272,7 +273,10 @@ export function renderBitReleaseWorkflow(defaultBranch: string, wsDir?: string):
|
|
|
272
273
|
export interface ScaffoldFileOutcome {
|
|
273
274
|
/** relative to the workspace root, e.g. `.github/workflows/bit-sync.yml` */
|
|
274
275
|
relativePath: string;
|
|
275
|
-
|
|
276
|
+
/** `updated`: the file existed and `--init` added to it (the AGENTS.md sync section) */
|
|
277
|
+
status: 'written' | 'updated' | 'skipped';
|
|
278
|
+
/** what `--init` did, when the status alone does not say it */
|
|
279
|
+
note?: string;
|
|
276
280
|
}
|
|
277
281
|
|
|
278
282
|
// Never overwrites an existing file — `--init` must be safe to re-run after hand-edits.
|
|
@@ -344,8 +348,19 @@ const SETUP_GUIDE_URL = 'https://github.com/teambit/acme-modular-store#set-it-up
|
|
|
344
348
|
const FILE_PURPOSE: Record<string, string> = {
|
|
345
349
|
[WORKFLOW_RELATIVE_PATHS.sync]: 'syncs lanes and branches: on export, on push, and every 30 minutes',
|
|
346
350
|
[WORKFLOW_RELATIVE_PATHS.release]: 'releases the scope when a pull request merges',
|
|
351
|
+
[AGENTS_MD_RELATIVE_PATH]: 'tells coding agents how the sync works in this repository',
|
|
347
352
|
};
|
|
348
353
|
|
|
354
|
+
/** The note the report shows next to a file. */
|
|
355
|
+
function fileNote(file: ScaffoldFileOutcome): string {
|
|
356
|
+
if (file.note) return file.note;
|
|
357
|
+
if (file.status === 'written') return FILE_PURPOSE[file.relativePath] ?? '';
|
|
358
|
+
if (file.status === 'updated') return 'added the sync rules at the top';
|
|
359
|
+
return file.relativePath === AGENTS_MD_RELATIVE_PATH
|
|
360
|
+
? 'already has the sync rules, left unchanged'
|
|
361
|
+
: 'already exists, left unchanged';
|
|
362
|
+
}
|
|
363
|
+
|
|
349
364
|
export interface InitReportInput {
|
|
350
365
|
/** the workspace's default scope, the one this repository mirrors */
|
|
351
366
|
scopeId?: string;
|
|
@@ -368,7 +383,7 @@ export interface InitReportInput {
|
|
|
368
383
|
repoHasCommits?: boolean;
|
|
369
384
|
/** false when the workspace is not in a git repository yet: step 1 then starts with `git init` */
|
|
370
385
|
inGitRepo?: boolean;
|
|
371
|
-
/** scaffolded
|
|
386
|
+
/** scaffolded files (the workflows, AGENTS.md), with the path to show (relative to where the user stands) */
|
|
372
387
|
files: Array<ScaffoldFileOutcome & { displayPath: string }>;
|
|
373
388
|
/** workspace.jsonc, as seen from where the user stands */
|
|
374
389
|
configDisplayPath?: string;
|
|
@@ -490,8 +505,8 @@ export function renderInitReport(input: InitReportInput): string {
|
|
|
490
505
|
const why = input.originUrl ? "the remote didn't name its default branch" : 'no remote names the default branch';
|
|
491
506
|
header.push(
|
|
492
507
|
formatWarningSummary(
|
|
493
|
-
`${why}, so the workflows use "${defaultBranch}". If that's wrong,\n` +
|
|
494
|
-
` edit the branch filters in both workflow files.`
|
|
508
|
+
`${why}, so the workflows and AGENTS.md use "${defaultBranch}". If that's wrong,\n` +
|
|
509
|
+
` edit the branch filters in both workflow files and the branch in the AGENTS.md sync section.`
|
|
495
510
|
)
|
|
496
511
|
);
|
|
497
512
|
}
|
|
@@ -507,12 +522,7 @@ export function renderInitReport(input: InitReportInput): string {
|
|
|
507
522
|
const width = Math.max(...input.files.map((f) => f.displayPath.length), configDisplayPath.length) + 2;
|
|
508
523
|
const fileItem = (displayPath: string, note: string) => formatItem(`${displayPath.padEnd(width)}${formatHint(note)}`);
|
|
509
524
|
const files = [
|
|
510
|
-
...input.files.map((file) =>
|
|
511
|
-
fileItem(
|
|
512
|
-
file.displayPath,
|
|
513
|
-
file.status === 'written' ? (FILE_PURPOSE[file.relativePath] ?? '') : 'already exists, left unchanged'
|
|
514
|
-
)
|
|
515
|
-
),
|
|
525
|
+
...input.files.map((file) => fileItem(file.displayPath, fileNote(file))),
|
|
516
526
|
fileItem(
|
|
517
527
|
configDisplayPath,
|
|
518
528
|
input.configAdded ? 'added "teambit.git/ci": { "sync": {} }' : 'already configures sync, left unchanged'
|
|
@@ -350,8 +350,13 @@ describe('haltCommentBody', () => {
|
|
|
350
350
|
branch: LANE_NAME,
|
|
351
351
|
laneId: `acme.shop/${LANE_NAME}`,
|
|
352
352
|
});
|
|
353
|
-
expect(body).to.include(
|
|
353
|
+
expect(body).to.include(
|
|
354
|
+
`git fetch origin && git checkout '${LANE_NAME}' && git merge --ff-only 'origin/${LANE_NAME}'`
|
|
355
|
+
);
|
|
354
356
|
expect(body).to.include(`bit lane import 'acme.shop/${LANE_NAME}'`);
|
|
357
|
+
// On a branch whose .bitmap is already on the lane, `bit lane import` only fetches: the merge is this step.
|
|
358
|
+
// --workspace-only: no component of another scope lands here. The next run adds new ones of this scope.
|
|
359
|
+
expect(body).to.include('bit checkout head --manual --workspace-only');
|
|
355
360
|
expect(body).to.include(`git push origin '${LANE_NAME}'`);
|
|
356
361
|
// the reason is prose, not a command, and the runbook still reads as one
|
|
357
362
|
expect(body).to.include('merge conflicts in: acme.shop/comp1');
|
|
@@ -1932,8 +1932,9 @@ export function haltCommentBody({
|
|
|
1932
1932
|
const resolution =
|
|
1933
1933
|
note ??
|
|
1934
1934
|
`To resolve locally:
|
|
1935
|
-
git fetch origin && git checkout ${shellQuote(branch)}
|
|
1935
|
+
git fetch origin && git checkout ${shellQuote(branch)} && git merge --ff-only ${shellQuote(`origin/${branch}`)}
|
|
1936
1936
|
bit lane import ${shellQuote(laneId)}
|
|
1937
|
+
bit checkout head --manual --workspace-only # merges the lane's head into the files; conflicts get conflict markers
|
|
1937
1938
|
# resolve conflicts, commit the result, then:
|
|
1938
1939
|
git push origin ${shellQuote(branch)}`;
|
|
1939
1940
|
return `bit-git-sync could not reconcile this branch automatically: ${reason}
|
|
@@ -24,6 +24,7 @@ import { MainSyncExecutor } from './main-sync-executor';
|
|
|
24
24
|
import { selectGitHostProvider } from './git-host-provider';
|
|
25
25
|
import { gitRepoRoot, isNonContentPath, listRemoteBranches } from './git-ops';
|
|
26
26
|
import { chooseInitDefaultBranch, deriveOwnerRepo, renderInitReport, scaffoldWorkflowFiles } from './init-scaffold';
|
|
27
|
+
import { UNKNOWN_REPO, scaffoldAgentsMd } from './agents-md';
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Refuse a `--dry-run` whose plan would be computed by force-checking-out branches over uncommitted
|
|
@@ -209,8 +210,9 @@ export class SyncOrchestrator {
|
|
|
209
210
|
|
|
210
211
|
/**
|
|
211
212
|
* `bit ci sync --init` — one-command onboarding: scaffolds the two workflow files, adds the sync
|
|
212
|
-
* config block to workspace.jsonc if missing,
|
|
213
|
-
* re-run: existing files are skipped, an existing
|
|
213
|
+
* config block to workspace.jsonc if missing, puts the sync rules for coding agents into AGENTS.md,
|
|
214
|
+
* and returns the report of the steps left. Safe to re-run: existing files are skipped, an existing
|
|
215
|
+
* config block or AGENTS.md sync section is left alone; it never reconciles.
|
|
214
216
|
*/
|
|
215
217
|
private async syncInit(): Promise<string> {
|
|
216
218
|
const remoteUrl = await git.remote(['get-url', 'origin']).catch(() => undefined);
|
|
@@ -249,6 +251,15 @@ export class SyncOrchestrator {
|
|
|
249
251
|
return fromCwd && !path.isAbsolute(fromCwd) ? fromCwd : abs;
|
|
250
252
|
};
|
|
251
253
|
const configAdded = await this.ensureSyncConfigBlock();
|
|
254
|
+
// AGENTS.md belongs to the workspace, where agents run bit commands.
|
|
255
|
+
const ownerRepo = deriveOwnerRepo(origin);
|
|
256
|
+
const agentsOutcome = scaffoldAgentsMd(this.deps.workspace.path, {
|
|
257
|
+
scope: this.deps.workspace.defaultScope ?? '<owner>.<scope>',
|
|
258
|
+
repo: ownerRepo
|
|
259
|
+
? `${ownerRepo.host === 'github.com' ? '' : `${ownerRepo.host}/`}${ownerRepo.owner}/${ownerRepo.repo}`
|
|
260
|
+
: UNKNOWN_REPO,
|
|
261
|
+
defaultBranch,
|
|
262
|
+
});
|
|
252
263
|
// No commit yet: the first commit must take the whole workspace, not only the files --init wrote.
|
|
253
264
|
const repoHasCommits = await git
|
|
254
265
|
.raw(['rev-parse', '--verify', '--quiet', 'HEAD'])
|
|
@@ -260,6 +271,7 @@ export class SyncOrchestrator {
|
|
|
260
271
|
const handled = [
|
|
261
272
|
...fileOutcomes.map((outcome) => path.join(scaffoldRoot, outcome.relativePath)),
|
|
262
273
|
path.join(this.deps.workspace.path, 'workspace.jsonc'),
|
|
274
|
+
path.join(this.deps.workspace.path, agentsOutcome.relativePath),
|
|
263
275
|
];
|
|
264
276
|
const toStage: string[] = [];
|
|
265
277
|
const ignored: string[] = [];
|
|
@@ -291,7 +303,7 @@ export class SyncOrchestrator {
|
|
|
291
303
|
// Returned, not logged: the command prints what `report()` returns.
|
|
292
304
|
return renderInitReport({
|
|
293
305
|
scopeId: this.deps.workspace.defaultScope,
|
|
294
|
-
ownerRepo
|
|
306
|
+
ownerRepo,
|
|
295
307
|
originUrl: origin,
|
|
296
308
|
defaultBranch,
|
|
297
309
|
defaultBranchGuessed: !detectedBranch,
|
|
@@ -299,10 +311,13 @@ export class SyncOrchestrator {
|
|
|
299
311
|
repoRootFromCwd: path.relative(process.cwd(), scaffoldRoot) || '.',
|
|
300
312
|
repoHasCommits,
|
|
301
313
|
inGitRepo: Boolean(repoRoot),
|
|
302
|
-
files:
|
|
303
|
-
...outcome
|
|
304
|
-
|
|
305
|
-
|
|
314
|
+
files: [
|
|
315
|
+
...fileOutcomes.map((outcome) => ({
|
|
316
|
+
...outcome,
|
|
317
|
+
displayPath: displayPath(path.join(scaffoldRoot, outcome.relativePath)),
|
|
318
|
+
})),
|
|
319
|
+
{ ...agentsOutcome, displayPath: displayPath(path.join(this.deps.workspace.path, agentsOutcome.relativePath)) },
|
|
320
|
+
],
|
|
306
321
|
configDisplayPath: displayPath(path.join(this.deps.workspace.path, 'workspace.jsonc')),
|
|
307
322
|
configAdded,
|
|
308
323
|
...(repoRoot ? { toStage, ignored } : {}),
|