@teambit/ci 1.0.495 → 1.0.497
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/ci.docs.mdx +39 -9
- package/dist/ci.docs.mdx +39 -9
- package/dist/ci.main.runtime.d.ts +6 -0
- package/dist/ci.main.runtime.js +24 -3
- package/dist/ci.main.runtime.js.map +1 -1
- package/dist/{preview-1786461108763.js → preview-1786718956243.js} +1 -1
- package/dist/sync/lane-sync-executor.d.ts +56 -14
- package/dist/sync/lane-sync-executor.js +196 -37
- package/dist/sync/lane-sync-executor.js.map +1 -1
- package/dist/sync/lane-sync-executor.spec.js +127 -3
- package/dist/sync/lane-sync-executor.spec.js.map +1 -1
- package/dist/sync/sync-planner.d.ts +10 -1
- package/dist/sync/sync-planner.js +37 -13
- package/dist/sync/sync-planner.js.map +1 -1
- package/dist/sync/sync-planner.spec.js +44 -2
- package/dist/sync/sync-planner.spec.js.map +1 -1
- package/dist/sync/sync-state.d.ts +33 -1
- package/dist/sync/sync-state.js +60 -3
- package/dist/sync/sync-state.js.map +1 -1
- package/dist/sync/sync-state.spec.js +28 -0
- package/dist/sync/sync-state.spec.js.map +1 -1
- package/package.json +21 -21
- package/sync/lane-sync-executor.spec.ts +110 -3
- package/sync/lane-sync-executor.ts +234 -32
- package/sync/sync-planner.spec.ts +36 -1
- package/sync/sync-planner.ts +36 -16
- package/sync/sync-state.spec.ts +33 -0
- package/sync/sync-state.ts +62 -1
|
@@ -417,6 +417,98 @@ describe('close-pr re-verifies the tip before retiring a branch', () => {
|
|
|
417
417
|
(0, _chai().expect)(await closePr()).to.equal('my-lane -> close-pr (no open PR, branch my-lane left in place)');
|
|
418
418
|
});
|
|
419
419
|
});
|
|
420
|
+
describe('differentLaneStillClaims uses .bitmap blob equality, not commit reachability', () => {
|
|
421
|
+
function executorWithInheritance(inherited) {
|
|
422
|
+
const executor = new (_laneSyncExecutor().LaneSyncExecutor)({
|
|
423
|
+
lanes: {},
|
|
424
|
+
ci: {},
|
|
425
|
+
logger: {
|
|
426
|
+
console: () => {},
|
|
427
|
+
consoleWarning: () => {},
|
|
428
|
+
error: () => {}
|
|
429
|
+
},
|
|
430
|
+
gitHost: undefined,
|
|
431
|
+
cfg: (0, _syncConfig().resolveSyncConfig)({}),
|
|
432
|
+
defaultScope: 'acme.shop'
|
|
433
|
+
});
|
|
434
|
+
executor.branchInheritsBitmapFromDefault = async () => inherited;
|
|
435
|
+
return (mirroredLane, laneIdStr) => executor.differentLaneStillClaims(mirroredLane, laneIdStr, 'my-branch', 'main');
|
|
436
|
+
}
|
|
437
|
+
it('does not claim when there is no mirrored lane pointer at all — never even checks the blob', async () => {
|
|
438
|
+
const differentLaneStillClaims = executorWithInheritance(true);
|
|
439
|
+
(0, _chai().expect)(await differentLaneStillClaims(undefined, 'acme.shop/my-lane')).to.equal(false);
|
|
440
|
+
});
|
|
441
|
+
it("does not claim for this lane's own pointer — never even checks the blob", async () => {
|
|
442
|
+
const differentLaneStillClaims = executorWithInheritance(true);
|
|
443
|
+
(0, _chai().expect)(await differentLaneStillClaims('acme.shop/my-lane', 'acme.shop/my-lane')).to.equal(false);
|
|
444
|
+
});
|
|
445
|
+
it("does not claim when the different-lane .bitmap is byte-identical to the default branch's — inherited", async () => {
|
|
446
|
+
const differentLaneStillClaims = executorWithInheritance(true);
|
|
447
|
+
(0, _chai().expect)(await differentLaneStillClaims('acme.shop/other-lane', 'acme.shop/my-lane')).to.equal(false);
|
|
448
|
+
});
|
|
449
|
+
it("STILL claims when the different-lane .bitmap has diverged from the default branch's — halt, not adopt", async () => {
|
|
450
|
+
const differentLaneStillClaims = executorWithInheritance(false);
|
|
451
|
+
(0, _chai().expect)(await differentLaneStillClaims('acme.shop/other-lane', 'acme.shop/my-lane')).to.equal(true);
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
describe('computeHasIndependentHistory gates the ancestry check to own-live claims with a state commit', () => {
|
|
455
|
+
function executorWithAncestryResult(result) {
|
|
456
|
+
const calls = [];
|
|
457
|
+
const executor = new (_laneSyncExecutor().LaneSyncExecutor)({
|
|
458
|
+
lanes: {},
|
|
459
|
+
ci: {},
|
|
460
|
+
logger: {
|
|
461
|
+
console: () => {},
|
|
462
|
+
consoleWarning: () => {},
|
|
463
|
+
error: () => {}
|
|
464
|
+
},
|
|
465
|
+
gitHost: undefined,
|
|
466
|
+
cfg: (0, _syncConfig().resolveSyncConfig)({}),
|
|
467
|
+
defaultScope: 'acme.shop'
|
|
468
|
+
});
|
|
469
|
+
executor.hasIndependentHistoryBelowStateCommit = async (stateCommit, defaultBranch) => {
|
|
470
|
+
calls.push([stateCommit, defaultBranch]);
|
|
471
|
+
return result;
|
|
472
|
+
};
|
|
473
|
+
const compute = (ownership, stateCommit, defaultBranch) => executor.computeHasIndependentHistory(ownership, stateCommit, defaultBranch);
|
|
474
|
+
return {
|
|
475
|
+
compute,
|
|
476
|
+
calls
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
it('skips the ancestry check entirely for a reachable claim (own-merged)', async () => {
|
|
480
|
+
const {
|
|
481
|
+
compute,
|
|
482
|
+
calls
|
|
483
|
+
} = executorWithAncestryResult(true);
|
|
484
|
+
(0, _chai().expect)(await compute('own-merged', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1', 'main')).to.equal(false);
|
|
485
|
+
(0, _chai().expect)(calls).to.deep.equal([]);
|
|
486
|
+
});
|
|
487
|
+
it('skips the ancestry check entirely for own-superseded too', async () => {
|
|
488
|
+
const {
|
|
489
|
+
compute,
|
|
490
|
+
calls
|
|
491
|
+
} = executorWithAncestryResult(true);
|
|
492
|
+
(0, _chai().expect)(await compute('own-superseded', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1', 'main')).to.equal(false);
|
|
493
|
+
(0, _chai().expect)(calls).to.deep.equal([]);
|
|
494
|
+
});
|
|
495
|
+
it('skips the check when there is no state commit to inspect, even for an own-live claim', async () => {
|
|
496
|
+
const {
|
|
497
|
+
compute,
|
|
498
|
+
calls
|
|
499
|
+
} = executorWithAncestryResult(true);
|
|
500
|
+
(0, _chai().expect)(await compute('own-live', undefined, 'main')).to.equal(false);
|
|
501
|
+
(0, _chai().expect)(calls).to.deep.equal([]);
|
|
502
|
+
});
|
|
503
|
+
it('defers to the ancestry check for an own-live claim with a state commit', async () => {
|
|
504
|
+
const {
|
|
505
|
+
compute,
|
|
506
|
+
calls
|
|
507
|
+
} = executorWithAncestryResult(true);
|
|
508
|
+
(0, _chai().expect)(await compute('own-live', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1', 'main')).to.equal(true);
|
|
509
|
+
(0, _chai().expect)(calls).to.deep.equal([['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1', 'main']]);
|
|
510
|
+
});
|
|
511
|
+
});
|
|
420
512
|
describe('classifyPushRejection confirms a race before calling it one', () => {
|
|
421
513
|
const BASE_SHA = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1';
|
|
422
514
|
const MOVED_SHA = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2';
|
|
@@ -474,9 +566,10 @@ describe('executeExportBranch reports the ledger-race wording when only the ledg
|
|
|
474
566
|
executor.lastNonSyncCommitMessage = async () => 'feat: some change';
|
|
475
567
|
executor.checkoutFromRemote = async () => {};
|
|
476
568
|
executor.restoreWorkspace = async () => {};
|
|
477
|
-
// The export half already succeeded
|
|
478
|
-
|
|
479
|
-
|
|
569
|
+
// The export half already succeeded; only the ledger commit that follows raced.
|
|
570
|
+
executor.snapAndExportOntoLane = async () => ({
|
|
571
|
+
status: 'exported'
|
|
572
|
+
});
|
|
480
573
|
executor.recordLaneHeadOnBranch = async () => ({
|
|
481
574
|
status: 'raced'
|
|
482
575
|
});
|
|
@@ -494,6 +587,37 @@ describe('executeExportBranch reports the ledger-race wording when only the ledg
|
|
|
494
587
|
});
|
|
495
588
|
});
|
|
496
589
|
|
|
590
|
+
// Adoption never snaps or exports, so its raced line must NOT claim the lane was updated — the lane
|
|
591
|
+
// is untouched and only the branch's pointer commit lost the race.
|
|
592
|
+
describe('executeAdoptBranch reports a lane-untouched race when its ledger push races', () => {
|
|
593
|
+
it('surfaces "lane untouched; adoption ledger commit lost the push race" without halting', async () => {
|
|
594
|
+
const {
|
|
595
|
+
executor
|
|
596
|
+
} = stubExecutor();
|
|
597
|
+
executor.deps.ci = {
|
|
598
|
+
hasUnsyncedWorkChanges: async () => false
|
|
599
|
+
};
|
|
600
|
+
executor.checkoutFromRemote = async () => {};
|
|
601
|
+
executor.restoreWorkspace = async () => {};
|
|
602
|
+
executor.materializeLane = async () => undefined;
|
|
603
|
+
executor.recordLaneHeadOnBranch = async () => ({
|
|
604
|
+
status: 'raced'
|
|
605
|
+
});
|
|
606
|
+
const summary = await executor.executeAdoptBranch({
|
|
607
|
+
target: {
|
|
608
|
+
hostScope: 'acme.shop',
|
|
609
|
+
name: 'my-lane'
|
|
610
|
+
},
|
|
611
|
+
laneIdStr: 'acme.shop/my-lane',
|
|
612
|
+
branch: 'my-lane',
|
|
613
|
+
defaultBranch: 'main'
|
|
614
|
+
});
|
|
615
|
+
(0, _chai().expect)(summary).to.equal('my-lane -> raced (lane untouched; adoption ledger commit lost the push race — next run re-plans)');
|
|
616
|
+
(0, _chai().expect)(summary).to.not.include('lane updated');
|
|
617
|
+
(0, _chai().expect)(summary).to.not.include('HALTED');
|
|
618
|
+
});
|
|
619
|
+
});
|
|
620
|
+
|
|
497
621
|
// A destructive auto-resolution (onConflict git-wins/lane-wins) that already exported must not vanish
|
|
498
622
|
// from the summary just because the ledger push raced.
|
|
499
623
|
describe('racedLedgerPushSummary keeps the conflict-policy clause', () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_chai","data","require","_laneSyncExecutor","_syncConfig","stubExecutor","warnings","executor","LaneSyncExecutor","lanes","ci","logger","console","consoleWarning","msg","push","error","gitHost","undefined","cfg","resolveSyncConfig","defaultScope","comp","id","head","toStringWithoutVersion","scope","split","describe","a","b","it","fingerprint","laneHeadFingerprint","expect","to","match","equal","moved","not","DEFAULT_SCOPE","ours","theirs","foreignLaneComponents","deep","namespaced","description","crossScopeDescription","include","ids","Array","from","length","_","index","LANE_HEAD","body","componentCount","laneSyncPrBody","laneIdStr","laneUrl","branch","laneHead","components","repeat","rendered","be","below","FOREIGN","summary","crossScopeSkipSummary","refusal","crossScopeRefusal","reason","crossScopeMidFlightHaltReason","branchMirrorsOtherLaneReason","note","branchMirrorsOtherLaneNote","throwingExecutor","gitHostCalls","noopLogger","debug","getDefaultBranchName","Error","name","findPrByBranch","number","htmlUrl","labels","addLabel","comment","fetched","syncLane","hostScope","dryRun","LANE_NAME","haltCommentBody","laneId","line","dryRunSummaryLine","type","forEach","contain","deleteBranch","EVIDENCE_SHA","MOVED_SHA","retirer","currentTip","pushError","pushes","currentBranchTip","pushBranchDeletion","sha","closePr","executeClosePr","laneName","defaultBranch","expectedTipSha","join","BASE_SHA","REJECTION","classifier","baseSha","e","classifyPushRejection","classify","unrelated","lastNonSyncCommitMessage","checkoutFromRemote","restoreWorkspace","snapAndExportOntoLane","recordLaneHeadOnBranch","status","executeExportBranch","target","racedLedgerPushSummary","isProtectedBranch"],"sources":["lane-sync-executor.spec.ts"],"sourcesContent":["import { expect } from 'chai';\nimport {\n branchMirrorsOtherLaneNote,\n branchMirrorsOtherLaneReason,\n crossScopeDescription,\n crossScopeMidFlightHaltReason,\n crossScopeRefusal,\n crossScopeSkipSummary,\n dryRunSummaryLine,\n foreignLaneComponents,\n haltCommentBody,\n isProtectedBranch,\n laneHeadFingerprint,\n LaneSyncExecutor,\n laneSyncPrBody,\n racedLedgerPushSummary,\n} from './lane-sync-executor';\nimport { resolveSyncConfig } from './sync-config';\n\n/**\n * One stub executor for every seam-based test: real executor code over stubbed deps, no repository.\n * `warnings` collects `consoleWarning` lines for tests that assert on them.\n */\nfunction stubExecutor(): { executor: LaneSyncExecutor; warnings: string[] } {\n const warnings: string[] = [];\n const executor = new LaneSyncExecutor({\n lanes: {} as any,\n ci: {} as any,\n logger: { console: () => {}, consoleWarning: (msg: string) => warnings.push(msg), error: () => {} } as any,\n gitHost: undefined,\n cfg: resolveSyncConfig({}),\n defaultScope: 'acme.shop',\n });\n return { executor, warnings };\n}\n\ntype LaneComponents = Parameters<typeof laneHeadFingerprint>[0];\n\n/** A stand-in for `LaneData`'s component entry; the helpers only read the id string, scope and head. */\nfunction comp(id: string, head: string): LaneComponents[number] {\n return {\n id: { toStringWithoutVersion: () => id, scope: id.split('/', 1)[0] },\n head,\n } as unknown as LaneComponents[number];\n}\n\ndescribe('laneHeadFingerprint', () => {\n const a = comp('acme.shop/comp1', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1');\n const b = comp('acme.shop/comp2', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2');\n\n it('is a single 40-hex token, so it survives being written into a commit trailer as an annotation', () => {\n const fingerprint = laneHeadFingerprint([a, b]);\n expect(fingerprint).to.match(/^[0-9a-f]{40}$/);\n });\n\n it('is stable under reordering: the remote listing order must not look like the lane moved', () => {\n expect(laneHeadFingerprint([a, b])).to.equal(laneHeadFingerprint([b, a]));\n });\n\n it('changes when a component head changes', () => {\n const moved = comp('acme.shop/comp2', 'cccccccccccccccccccccccccccccccccccccc33');\n expect(laneHeadFingerprint([a, moved])).to.not.equal(laneHeadFingerprint([a, b]));\n });\n\n it('changes when a component is added or removed', () => {\n expect(laneHeadFingerprint([a])).to.not.equal(laneHeadFingerprint([a, b]));\n expect(laneHeadFingerprint([])).to.not.equal(laneHeadFingerprint([a]));\n });\n\n it('does not depend on the lane object, only on its content', () => {\n expect(laneHeadFingerprint([a, b])).to.equal(laneHeadFingerprint([comp('acme.shop/comp1', a.head), b]));\n });\n});\n\ndescribe('foreignLaneComponents', () => {\n const DEFAULT_SCOPE = 'acme.shop';\n const ours = comp('acme.shop/comp1', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1');\n const theirs = comp('other.scope/comp2', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2');\n\n it('is empty for a lane whose components are all in the repository scope', () => {\n expect(foreignLaneComponents([ours], DEFAULT_SCOPE)).to.deep.equal([]);\n expect(foreignLaneComponents([], DEFAULT_SCOPE)).to.deep.equal([]);\n });\n\n it('names every component outside the repository scope', () => {\n expect(foreignLaneComponents([ours, theirs], DEFAULT_SCOPE)).to.deep.equal(['other.scope/comp2']);\n });\n\n it('compares the scope, not the id prefix: a namespaced component of our scope is ours', () => {\n // `acme.shop/ui/button` must not read as scope `acme.shop/ui`.\n const namespaced = comp('acme.shop/ui/button', 'ccccccccccccccccccccccccccccccccccccc333');\n expect(foreignLaneComponents([namespaced], DEFAULT_SCOPE)).to.deep.equal([]);\n });\n\n it('treats a lane hosted elsewhere but filled with our components as ours (hosting != content)', () => {\n expect(foreignLaneComponents([ours], DEFAULT_SCOPE)).to.deep.equal([]);\n });\n});\n\ndescribe('crossScopeDescription', () => {\n const DEFAULT_SCOPE = 'acme.shop';\n\n it('names the foreign scopes and this repository scope', () => {\n const description = crossScopeDescription(['other.scope/comp2', 'third.scope/comp3'], DEFAULT_SCOPE);\n expect(description).to.include('components from scope(s) other.scope, third.scope');\n expect(description).to.include(`(this repo maps scope ${DEFAULT_SCOPE})`);\n expect(description).to.include('foreign components: other.scope/comp2, third.scope/comp3');\n });\n\n it('lists at most five foreign components and summarizes the rest', () => {\n const ids = Array.from({ length: 8 }, (_, index) => `other.scope/comp${index}`);\n const description = crossScopeDescription(ids, DEFAULT_SCOPE);\n expect(description).to.include('other.scope/comp4');\n expect(description).to.not.include('other.scope/comp5');\n expect(description).to.include('…and 3 more');\n });\n\n it('does not append a count when everything is listed', () => {\n expect(crossScopeDescription(['other.scope/comp1'], DEFAULT_SCOPE)).to.not.include('more');\n });\n});\n\n// GitHub rejects a PR whose body exceeds 65,536 characters, whole-request; a lane has no size limit.\ndescribe('laneSyncPrBody', () => {\n const LANE_HEAD = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1';\n\n function body(componentCount: number) {\n return laneSyncPrBody({\n laneIdStr: 'acme.shop/my-lane',\n laneUrl: 'https://bit.cloud/acme/shop/~lane/my-lane',\n branch: 'my-lane',\n laneHead: LANE_HEAD,\n components: Array.from({ length: componentCount }, (_, index) =>\n comp(`acme.shop/namespace/component-with-a-realistic-name-${index}`, `${'0'.repeat(39)}${index % 10}`)\n ),\n });\n }\n\n it('lists at most twenty components and summarizes the rest, keeping the exact total', () => {\n const rendered = body(100);\n expect(rendered).to.include('component-with-a-realistic-name-19');\n expect(rendered).to.not.include('component-with-a-realistic-name-20');\n expect(rendered).to.include('and 80 more');\n expect(rendered).to.include('Components on the lane (100):');\n expect(rendered).to.include(`lane head: \\`${LANE_HEAD}\\``);\n });\n\n it('stays far inside a git host body limit for a lane of any size', () => {\n expect(body(100).length).to.be.below(60000);\n expect(body(5000).length).to.be.below(60000);\n });\n\n it('lists a small lane in full, with no summary line', () => {\n const rendered = body(3);\n expect(rendered).to.include('component-with-a-realistic-name-2');\n expect(rendered).to.not.include('more');\n expect(rendered).to.include('Components on the lane (3):');\n });\n\n it('says so explicitly when the lane has no components', () => {\n expect(body(0)).to.include('_none_');\n });\n});\n\ndescribe('cross-scope outcome messages', () => {\n const DEFAULT_SCOPE = 'acme.shop';\n const FOREIGN = ['other.scope/comp2'];\n\n it('an enumerated lane is SKIPPED, in the vocabulary of a healthy run', () => {\n const summary = crossScopeSkipSummary('my-lane', FOREIGN, DEFAULT_SCOPE);\n expect(summary).to.match(/^my-lane -> skipped \\(cross-scope lane: /);\n expect(summary).to.include('no branch created');\n // A HALTED/REFUSED marker in this line would flip the exit code of a healthy repository.\n expect(summary).to.not.include('HALTED');\n expect(summary).to.not.include('REFUSED');\n });\n\n it('an explicitly requested lane is REFUSED, with the reason and the \"nothing was written\" promise', () => {\n const refusal = crossScopeRefusal(FOREIGN, DEFAULT_SCOPE);\n expect(refusal).to.include('cross-scope lane: components from scope(s) other.scope');\n expect(refusal).to.include(\"not supported yet — see the docs' Cross-scope lanes section\");\n expect(refusal).to.include('No branch was created and nothing was written');\n });\n\n it('the refusal does not claim it created no branch when a branch already exists', () => {\n const refusal = crossScopeRefusal(FOREIGN, DEFAULT_SCOPE, 'my-lane');\n expect(refusal).to.include('Nothing was written; the existing branch my-lane was left untouched');\n expect(refusal).to.not.include('No branch was created');\n });\n\n it('a lane that became cross-scope mid-flight names the branch it can no longer converge with', () => {\n const reason = crossScopeMidFlightHaltReason('my-lane', FOREIGN, DEFAULT_SCOPE);\n expect(reason).to.include('lane became cross-scope after it was mirrored onto my-lane');\n expect(reason).to.include('can no longer be reconciled automatically');\n });\n});\n\ndescribe('branchMirrorsOtherLaneReason', () => {\n it('names the branch, the lane that owns it, and the lane that was refused', () => {\n const reason = branchMirrorsOtherLaneReason('release', 'other.scope/release', 'acme.shop/release');\n expect(reason).to.include('branch release mirrors lane other.scope/release');\n expect(reason).to.include('refusing to plan for acme.shop/release');\n expect(reason).to.include(\"overwrite the other lane's mirror\");\n });\n\n it('the PR comment tells the branch owner their lane is fine, and not to run the usual steps', () => {\n const note = branchMirrorsOtherLaneNote('other.scope/release', 'acme.shop/release');\n expect(note).to.include('belongs to lane `other.scope/release`');\n expect(note).to.include('nothing is wrong with it');\n expect(note).to.include('acme.shop/release');\n expect(note).to.match(/Do NOT run the usual \"bit lane import\" resolution steps/);\n expect(note).to.include('rename one of the two lanes');\n expect(note).to.include('`branches`');\n });\n});\n\n// The executor is real; `getDefaultBranchName` throwing is the seam — the first dependency\n// `reconcileLane` awaits after the fetch, so the throw reaches the outer catch with no git/network work.\ndescribe('syncLane outer catch under --dry-run', () => {\n function throwingExecutor(gitHostCalls: string[]): LaneSyncExecutor {\n const noopLogger = { console: () => {}, consoleWarning: () => {}, error: () => {}, debug: () => {} };\n const executor = new LaneSyncExecutor({\n lanes: {} as any,\n ci: {\n getDefaultBranchName: async () => {\n throw new Error('boom');\n },\n } as any,\n logger: noopLogger as any,\n gitHost: {\n name: 'stub',\n findPrByBranch: async () => {\n gitHostCalls.push('findPrByBranch');\n return { number: 7, htmlUrl: 'https://example.test/pr/7', labels: [] };\n },\n addLabel: async () => {\n gitHostCalls.push('addLabel');\n },\n comment: async () => {\n gitHostCalls.push('comment');\n },\n } as any,\n cfg: resolveSyncConfig({}),\n defaultScope: 'acme.shop',\n });\n // Mark the fetch done so the spec never touches a repository or the network.\n (executor as any).fetched = true;\n return executor;\n }\n\n it('reports the halt without reading, labelling or commenting on the PR', async () => {\n const gitHostCalls: string[] = [];\n const summary = await throwingExecutor(gitHostCalls).syncLane(\n { hostScope: 'acme.shop', name: 'my-lane' },\n { dryRun: true }\n );\n expect(summary).to.equal('HALTED my-lane -> unexpected error: boom');\n expect(gitHostCalls).to.deep.equal([]);\n });\n\n it('is non-vacuous: without --dry-run the same failure does read, label and comment the PR', async () => {\n const gitHostCalls: string[] = [];\n const summary = await throwingExecutor(gitHostCalls).syncLane({ hostScope: 'acme.shop', name: 'my-lane' });\n expect(summary).to.equal('HALTED my-lane -> unexpected error: boom');\n expect(gitHostCalls).to.deep.equal(['findPrByBranch', 'addLabel', 'comment']);\n });\n\n // '-hostile' is a legal bit lane name (the charset allows a leading '-') that can never be a branch.\n it('a lane whose name cannot map to a branch halts report-only instead of throwing', async () => {\n const gitHostCalls: string[] = [];\n const summary = await throwingExecutor(gitHostCalls).syncLane({ hostScope: 'acme.shop', name: '-hostile' });\n expect(summary).to.match(/^HALTED -hostile -> unexpected error: .*not a valid git branch name/);\n expect(gitHostCalls).to.deep.equal([]);\n });\n});\n\n// bit's lane-name charset admits `$`, `-`, `_` and `!`, so an unquoted runbook shell-expands when pasted.\ndescribe('haltCommentBody', () => {\n const LANE_NAME = 'fix-$home-and-!bang';\n\n it('single-quotes every value it interpolates into a command', () => {\n const body = haltCommentBody({\n reason: 'merge conflicts in: acme.shop/comp1',\n branch: LANE_NAME,\n laneId: `acme.shop/${LANE_NAME}`,\n });\n expect(body).to.include(`git fetch origin && git checkout '${LANE_NAME}'`);\n expect(body).to.include(`bit lane import 'acme.shop/${LANE_NAME}'`);\n expect(body).to.include(`git push origin '${LANE_NAME}'`);\n // the reason is prose, not a command, and the runbook still reads as one\n expect(body).to.include('merge conflicts in: acme.shop/comp1');\n expect(body).to.include('Remove the `bit-sync-conflict` label to resume syncing.');\n });\n\n // A configured `branches` override only has to be a valid git ref, and git accepts a quote in one.\n it('escapes a value that itself contains a quote, rather than ending the quoting early', () => {\n const body = haltCommentBody({ reason: 'x', branch: \"it's-a-branch\", laneId: 'acme.shop/lane' });\n expect(body).to.include(`git checkout 'it'\\\\''s-a-branch'`);\n });\n\n it('leaves an overriding note alone: it carries no commands to quote', () => {\n const body = haltCommentBody({ reason: 'x', branch: LANE_NAME, laneId: 'acme.shop/lane', note: 'nothing to do' });\n expect(body).to.include('nothing to do');\n expect(body).to.not.include('git checkout');\n });\n});\n\n// `summarizeSync` decides the exit code by scanning for the prefix and nothing else, so a prefix-less\n// line makes a dry run report success on a plan the real run would have halted on.\ndescribe('dryRunSummaryLine', () => {\n it('carries the HALTED prefix and the reason for a planned halt, so the run exits non-zero', () => {\n const line = dryRunSummaryLine('my-lane', { type: 'halt', reason: 'cannot tell which side is newer' });\n expect(line).to.equal('HALTED my-lane -> cannot tell which side is newer');\n });\n\n it('leaves every other planned action unprefixed — those runs are healthy', () => {\n (['import-lane', 'export-branch', 'merge-diverged'] as const).forEach((type) => {\n const line = dryRunSummaryLine('my-lane', { type });\n expect(line, type).to.equal(`my-lane -> ${type}`);\n expect(line, type).to.not.contain('HALTED');\n expect(line, type).to.not.contain('REFUSED');\n });\n expect(dryRunSummaryLine('my-lane', { type: 'noop', reason: 'converged' })).to.equal('my-lane -> noop');\n expect(dryRunSummaryLine('my-lane', { type: 'close-pr', deleteBranch: true })).to.equal('my-lane -> close-pr');\n });\n});\n\n// The deletion decision is computed from refs fetched once per run; on an `--all` run the branch can\n// advance while earlier lanes are reconciled. Both seams are stubbed, so no repository is touched.\ndescribe('close-pr re-verifies the tip before retiring a branch', () => {\n const EVIDENCE_SHA = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1';\n const MOVED_SHA = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2';\n\n function retirer(currentTip: string | undefined, pushError?: Error) {\n const { executor, warnings } = stubExecutor();\n const pushes: string[][] = [];\n (executor as any).currentBranchTip = async () => currentTip;\n (executor as any).pushBranchDeletion = async (branch: string, sha: string) => {\n pushes.push([branch, sha]);\n if (pushError) throw pushError;\n };\n const closePr = () =>\n (executor as any).executeClosePr({\n laneName: 'my-lane',\n laneIdStr: 'acme.shop/my-lane',\n branch: 'my-lane',\n defaultBranch: 'main',\n deleteBranch: true,\n expectedTipSha: EVIDENCE_SHA,\n }) as Promise<string>;\n return { closePr, warnings, pushes };\n }\n\n it('deletes at the evidence sha while the branch is still there', async () => {\n const { closePr, pushes } = retirer(EVIDENCE_SHA);\n expect(await closePr()).to.equal('my-lane -> close-pr (no open PR, branch my-lane deleted)');\n expect(pushes).to.deep.equal([['my-lane', EVIDENCE_SHA]]);\n });\n\n it('KEEPS the branch when the tip moved during the run, pushing nothing at all', async () => {\n const { closePr, warnings, pushes } = retirer(MOVED_SHA);\n const summary = await closePr();\n expect(summary).to.contain('branch my-lane kept: its tip advanced after the ownership evidence was read');\n expect(pushes).to.deep.equal([]);\n expect(warnings.join('\\n')).to.contain(`its tip is now ${MOVED_SHA} rather than the ${EVIDENCE_SHA}`);\n });\n\n it('keeps the branch when the tip cannot be re-read at all, rather than trusting the stale answer', async () => {\n const { closePr, pushes } = retirer(undefined);\n expect(await closePr()).to.contain('branch my-lane kept: its tip advanced');\n expect(pushes).to.deep.equal([]);\n });\n\n // The re-read and the push are not atomic; the server gets the last word, and it is not a crash.\n it('reports a lease refusal as the same kept outcome', async () => {\n const { closePr, warnings } = retirer(\n EVIDENCE_SHA,\n new Error('! [rejected] (delete) -> my-lane (stale info)\\nerror: failed to push some refs')\n );\n expect(await closePr()).to.contain('branch my-lane kept: its tip advanced');\n expect(warnings.join('\\n')).to.contain('the remote refused the lease');\n });\n\n it('an unrelated push failure still reads as \"left in place\", not as a race', async () => {\n const { closePr } = retirer(EVIDENCE_SHA, new Error('remote: GH006: Protected branch update failed'));\n expect(await closePr()).to.equal('my-lane -> close-pr (no open PR, branch my-lane left in place)');\n });\n});\n\ndescribe('classifyPushRejection confirms a race before calling it one', () => {\n const BASE_SHA = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1';\n const MOVED_SHA = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2';\n const REJECTION = new Error('! [rejected] HEAD -> feature (fetch first)\\nerror: failed to push some refs');\n\n function classifier(currentTip: string | undefined) {\n const { executor } = stubExecutor();\n (executor as any).currentBranchTip = async () => currentTip;\n return (baseSha: string | undefined, e: Error) =>\n (executor as any).classifyPushRejection('my-branch', baseSha, e) as Promise<'confirmed-race' | 'not-a-race'>;\n }\n\n it('confirms the race when the branch actually moved off the base we pushed against', async () => {\n const classify = classifier(MOVED_SHA);\n expect(await classify(BASE_SHA, REJECTION)).to.equal('confirmed-race');\n });\n\n it('confirms the race for a brand-new branch that now exists on the remote', async () => {\n const classify = classifier(MOVED_SHA);\n expect(await classify(undefined, REJECTION)).to.equal('confirmed-race');\n });\n\n // Message-text matching alone is not proof: a persistent, unrelated rejection could repeat the same\n // wording forever. Without this re-fetch-and-compare, that would go permanently green.\n it('answers not-a-race when the branch did NOT move — the wording matched but nothing raced', async () => {\n const classify = classifier(BASE_SHA);\n expect(await classify(BASE_SHA, REJECTION)).to.equal('not-a-race');\n });\n\n it('answers not-a-race when a brand-new branch still does not exist on the remote', async () => {\n const classify = classifier(undefined);\n expect(await classify(undefined, REJECTION)).to.equal('not-a-race');\n });\n\n // The polarity bug this guards: `currentTip === undefined` here means the re-fetch FAILED (network\n // blip, auth hiccup) — unknown, not evidence the branch moved. `undefined !== baseSha` reads as\n // truthy if compared naively, which would misreport an unanswerable check as a confirmed race and\n // paper over a real, persistent failure. Withhold like every other unknown-answer path in this file.\n it('answers not-a-race when the re-fetch itself fails, even though a base sha is known', async () => {\n const classify = classifier(undefined);\n expect(await classify(BASE_SHA, REJECTION)).to.equal('not-a-race');\n });\n\n it('answers not-a-race for a rejection whose wording is not a non-fast-forward race at all', async () => {\n const classify = classifier(MOVED_SHA);\n const unrelated = new Error('remote: GH006: Protected branch update failed');\n expect(await classify(BASE_SHA, unrelated)).to.equal('not-a-race');\n });\n});\n\n// The live incident's actual shape: the snap/export onto the lane already succeeded — the lane truly\n// moved — and only the branch's OWN ledger-commit push (recordLaneHeadOnBranch) lost the race. Nothing\n// exercised `racedLedgerPushSummary` before this; a wording regression there would have gone unnoticed.\ndescribe('executeExportBranch reports the ledger-race wording when only the ledger push races', () => {\n it('surfaces \"lane updated; branch ledger commit lost the push race\" without halting', async () => {\n const { executor } = stubExecutor();\n (executor as any).lastNonSyncCommitMessage = async () => 'feat: some change';\n (executor as any).checkoutFromRemote = async () => {};\n (executor as any).restoreWorkspace = async () => {};\n // The export half already succeeded (undefined = no error, matching this file's `Error | undefined`\n // contract for `snapAndExportOntoLane`); only the ledger commit that follows raced.\n (executor as any).snapAndExportOntoLane = async () => undefined;\n (executor as any).recordLaneHeadOnBranch = async () => ({ status: 'raced' });\n\n const summary = await (executor as any).executeExportBranch({\n target: { hostScope: 'acme.shop', name: 'my-lane' },\n laneIdStr: 'acme.shop/my-lane',\n branch: 'my-lane',\n defaultBranch: 'main',\n });\n\n expect(summary).to.equal(\n 'my-lane -> raced (lane updated; branch ledger commit lost the push race — next run re-plans)'\n );\n expect(summary).to.not.include('HALTED');\n });\n});\n\n// A destructive auto-resolution (onConflict git-wins/lane-wins) that already exported must not vanish\n// from the summary just because the ledger push raced.\ndescribe('racedLedgerPushSummary keeps the conflict-policy clause', () => {\n it('carries the merge path’s policyClause through the raced ledger line', () => {\n expect(racedLedgerPushSummary('my-lane', 'conflicts auto-resolved: git-wins on 3 file(s); ')).to.equal(\n 'my-lane -> raced (conflicts auto-resolved: git-wins on 3 file(s); lane updated; branch ledger commit ' +\n 'lost the push race — next run re-plans)'\n );\n });\n});\n\ndescribe('isProtectedBranch', () => {\n it('refuses the default branch and the main sync branch', () => {\n expect(isProtectedBranch('develop', 'develop', 'bit-sync/main')).to.equal(true);\n expect(isProtectedBranch('bit-sync/main', 'develop', 'bit-sync/main')).to.equal(true);\n });\n\n it('permits an ordinary lane branch', () => {\n expect(isProtectedBranch('my-lane', 'develop', 'bit-sync/main')).to.equal(false);\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_chai","data","require","_laneSyncExecutor","_syncConfig","stubExecutor","warnings","executor","LaneSyncExecutor","lanes","ci","logger","console","consoleWarning","msg","push","error","gitHost","undefined","cfg","resolveSyncConfig","defaultScope","comp","id","head","toStringWithoutVersion","scope","split","describe","a","b","it","fingerprint","laneHeadFingerprint","expect","to","match","equal","moved","not","DEFAULT_SCOPE","ours","theirs","foreignLaneComponents","deep","namespaced","description","crossScopeDescription","include","ids","Array","from","length","_","index","LANE_HEAD","body","componentCount","laneSyncPrBody","laneIdStr","laneUrl","branch","laneHead","components","repeat","rendered","be","below","FOREIGN","summary","crossScopeSkipSummary","refusal","crossScopeRefusal","reason","crossScopeMidFlightHaltReason","branchMirrorsOtherLaneReason","note","branchMirrorsOtherLaneNote","throwingExecutor","gitHostCalls","noopLogger","debug","getDefaultBranchName","Error","name","findPrByBranch","number","htmlUrl","labels","addLabel","comment","fetched","syncLane","hostScope","dryRun","LANE_NAME","haltCommentBody","laneId","line","dryRunSummaryLine","type","forEach","contain","deleteBranch","EVIDENCE_SHA","MOVED_SHA","retirer","currentTip","pushError","pushes","currentBranchTip","pushBranchDeletion","sha","closePr","executeClosePr","laneName","defaultBranch","expectedTipSha","join","executorWithInheritance","inherited","branchInheritsBitmapFromDefault","mirroredLane","differentLaneStillClaims","executorWithAncestryResult","result","calls","hasIndependentHistoryBelowStateCommit","stateCommit","compute","ownership","computeHasIndependentHistory","BASE_SHA","REJECTION","classifier","baseSha","e","classifyPushRejection","classify","unrelated","lastNonSyncCommitMessage","checkoutFromRemote","restoreWorkspace","snapAndExportOntoLane","status","recordLaneHeadOnBranch","executeExportBranch","target","deps","hasUnsyncedWorkChanges","materializeLane","executeAdoptBranch","racedLedgerPushSummary","isProtectedBranch"],"sources":["lane-sync-executor.spec.ts"],"sourcesContent":["import { expect } from 'chai';\nimport {\n branchMirrorsOtherLaneNote,\n branchMirrorsOtherLaneReason,\n crossScopeDescription,\n crossScopeMidFlightHaltReason,\n crossScopeRefusal,\n crossScopeSkipSummary,\n dryRunSummaryLine,\n foreignLaneComponents,\n haltCommentBody,\n isProtectedBranch,\n laneHeadFingerprint,\n LaneSyncExecutor,\n laneSyncPrBody,\n racedLedgerPushSummary,\n} from './lane-sync-executor';\nimport type { LaneOwnershipEvidence } from './sync-planner';\nimport { resolveSyncConfig } from './sync-config';\n\n/**\n * One stub executor for every seam-based test: real executor code over stubbed deps, no repository.\n * `warnings` collects `consoleWarning` lines for tests that assert on them.\n */\nfunction stubExecutor(): { executor: LaneSyncExecutor; warnings: string[] } {\n const warnings: string[] = [];\n const executor = new LaneSyncExecutor({\n lanes: {} as any,\n ci: {} as any,\n logger: { console: () => {}, consoleWarning: (msg: string) => warnings.push(msg), error: () => {} } as any,\n gitHost: undefined,\n cfg: resolveSyncConfig({}),\n defaultScope: 'acme.shop',\n });\n return { executor, warnings };\n}\n\ntype LaneComponents = Parameters<typeof laneHeadFingerprint>[0];\n\n/** A stand-in for `LaneData`'s component entry; the helpers only read the id string, scope and head. */\nfunction comp(id: string, head: string): LaneComponents[number] {\n return {\n id: { toStringWithoutVersion: () => id, scope: id.split('/', 1)[0] },\n head,\n } as unknown as LaneComponents[number];\n}\n\ndescribe('laneHeadFingerprint', () => {\n const a = comp('acme.shop/comp1', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1');\n const b = comp('acme.shop/comp2', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2');\n\n it('is a single 40-hex token, so it survives being written into a commit trailer as an annotation', () => {\n const fingerprint = laneHeadFingerprint([a, b]);\n expect(fingerprint).to.match(/^[0-9a-f]{40}$/);\n });\n\n it('is stable under reordering: the remote listing order must not look like the lane moved', () => {\n expect(laneHeadFingerprint([a, b])).to.equal(laneHeadFingerprint([b, a]));\n });\n\n it('changes when a component head changes', () => {\n const moved = comp('acme.shop/comp2', 'cccccccccccccccccccccccccccccccccccccc33');\n expect(laneHeadFingerprint([a, moved])).to.not.equal(laneHeadFingerprint([a, b]));\n });\n\n it('changes when a component is added or removed', () => {\n expect(laneHeadFingerprint([a])).to.not.equal(laneHeadFingerprint([a, b]));\n expect(laneHeadFingerprint([])).to.not.equal(laneHeadFingerprint([a]));\n });\n\n it('does not depend on the lane object, only on its content', () => {\n expect(laneHeadFingerprint([a, b])).to.equal(laneHeadFingerprint([comp('acme.shop/comp1', a.head), b]));\n });\n});\n\ndescribe('foreignLaneComponents', () => {\n const DEFAULT_SCOPE = 'acme.shop';\n const ours = comp('acme.shop/comp1', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1');\n const theirs = comp('other.scope/comp2', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2');\n\n it('is empty for a lane whose components are all in the repository scope', () => {\n expect(foreignLaneComponents([ours], DEFAULT_SCOPE)).to.deep.equal([]);\n expect(foreignLaneComponents([], DEFAULT_SCOPE)).to.deep.equal([]);\n });\n\n it('names every component outside the repository scope', () => {\n expect(foreignLaneComponents([ours, theirs], DEFAULT_SCOPE)).to.deep.equal(['other.scope/comp2']);\n });\n\n it('compares the scope, not the id prefix: a namespaced component of our scope is ours', () => {\n // `acme.shop/ui/button` must not read as scope `acme.shop/ui`.\n const namespaced = comp('acme.shop/ui/button', 'ccccccccccccccccccccccccccccccccccccc333');\n expect(foreignLaneComponents([namespaced], DEFAULT_SCOPE)).to.deep.equal([]);\n });\n\n it('treats a lane hosted elsewhere but filled with our components as ours (hosting != content)', () => {\n expect(foreignLaneComponents([ours], DEFAULT_SCOPE)).to.deep.equal([]);\n });\n});\n\ndescribe('crossScopeDescription', () => {\n const DEFAULT_SCOPE = 'acme.shop';\n\n it('names the foreign scopes and this repository scope', () => {\n const description = crossScopeDescription(['other.scope/comp2', 'third.scope/comp3'], DEFAULT_SCOPE);\n expect(description).to.include('components from scope(s) other.scope, third.scope');\n expect(description).to.include(`(this repo maps scope ${DEFAULT_SCOPE})`);\n expect(description).to.include('foreign components: other.scope/comp2, third.scope/comp3');\n });\n\n it('lists at most five foreign components and summarizes the rest', () => {\n const ids = Array.from({ length: 8 }, (_, index) => `other.scope/comp${index}`);\n const description = crossScopeDescription(ids, DEFAULT_SCOPE);\n expect(description).to.include('other.scope/comp4');\n expect(description).to.not.include('other.scope/comp5');\n expect(description).to.include('…and 3 more');\n });\n\n it('does not append a count when everything is listed', () => {\n expect(crossScopeDescription(['other.scope/comp1'], DEFAULT_SCOPE)).to.not.include('more');\n });\n});\n\n// GitHub rejects a PR whose body exceeds 65,536 characters, whole-request; a lane has no size limit.\ndescribe('laneSyncPrBody', () => {\n const LANE_HEAD = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1';\n\n function body(componentCount: number) {\n return laneSyncPrBody({\n laneIdStr: 'acme.shop/my-lane',\n laneUrl: 'https://bit.cloud/acme/shop/~lane/my-lane',\n branch: 'my-lane',\n laneHead: LANE_HEAD,\n components: Array.from({ length: componentCount }, (_, index) =>\n comp(`acme.shop/namespace/component-with-a-realistic-name-${index}`, `${'0'.repeat(39)}${index % 10}`)\n ),\n });\n }\n\n it('lists at most twenty components and summarizes the rest, keeping the exact total', () => {\n const rendered = body(100);\n expect(rendered).to.include('component-with-a-realistic-name-19');\n expect(rendered).to.not.include('component-with-a-realistic-name-20');\n expect(rendered).to.include('and 80 more');\n expect(rendered).to.include('Components on the lane (100):');\n expect(rendered).to.include(`lane head: \\`${LANE_HEAD}\\``);\n });\n\n it('stays far inside a git host body limit for a lane of any size', () => {\n expect(body(100).length).to.be.below(60000);\n expect(body(5000).length).to.be.below(60000);\n });\n\n it('lists a small lane in full, with no summary line', () => {\n const rendered = body(3);\n expect(rendered).to.include('component-with-a-realistic-name-2');\n expect(rendered).to.not.include('more');\n expect(rendered).to.include('Components on the lane (3):');\n });\n\n it('says so explicitly when the lane has no components', () => {\n expect(body(0)).to.include('_none_');\n });\n});\n\ndescribe('cross-scope outcome messages', () => {\n const DEFAULT_SCOPE = 'acme.shop';\n const FOREIGN = ['other.scope/comp2'];\n\n it('an enumerated lane is SKIPPED, in the vocabulary of a healthy run', () => {\n const summary = crossScopeSkipSummary('my-lane', FOREIGN, DEFAULT_SCOPE);\n expect(summary).to.match(/^my-lane -> skipped \\(cross-scope lane: /);\n expect(summary).to.include('no branch created');\n // A HALTED/REFUSED marker in this line would flip the exit code of a healthy repository.\n expect(summary).to.not.include('HALTED');\n expect(summary).to.not.include('REFUSED');\n });\n\n it('an explicitly requested lane is REFUSED, with the reason and the \"nothing was written\" promise', () => {\n const refusal = crossScopeRefusal(FOREIGN, DEFAULT_SCOPE);\n expect(refusal).to.include('cross-scope lane: components from scope(s) other.scope');\n expect(refusal).to.include(\"not supported yet — see the docs' Cross-scope lanes section\");\n expect(refusal).to.include('No branch was created and nothing was written');\n });\n\n it('the refusal does not claim it created no branch when a branch already exists', () => {\n const refusal = crossScopeRefusal(FOREIGN, DEFAULT_SCOPE, 'my-lane');\n expect(refusal).to.include('Nothing was written; the existing branch my-lane was left untouched');\n expect(refusal).to.not.include('No branch was created');\n });\n\n it('a lane that became cross-scope mid-flight names the branch it can no longer converge with', () => {\n const reason = crossScopeMidFlightHaltReason('my-lane', FOREIGN, DEFAULT_SCOPE);\n expect(reason).to.include('lane became cross-scope after it was mirrored onto my-lane');\n expect(reason).to.include('can no longer be reconciled automatically');\n });\n});\n\ndescribe('branchMirrorsOtherLaneReason', () => {\n it('names the branch, the lane that owns it, and the lane that was refused', () => {\n const reason = branchMirrorsOtherLaneReason('release', 'other.scope/release', 'acme.shop/release');\n expect(reason).to.include('branch release mirrors lane other.scope/release');\n expect(reason).to.include('refusing to plan for acme.shop/release');\n expect(reason).to.include(\"overwrite the other lane's mirror\");\n });\n\n it('the PR comment tells the branch owner their lane is fine, and not to run the usual steps', () => {\n const note = branchMirrorsOtherLaneNote('other.scope/release', 'acme.shop/release');\n expect(note).to.include('belongs to lane `other.scope/release`');\n expect(note).to.include('nothing is wrong with it');\n expect(note).to.include('acme.shop/release');\n expect(note).to.match(/Do NOT run the usual \"bit lane import\" resolution steps/);\n expect(note).to.include('rename one of the two lanes');\n expect(note).to.include('`branches`');\n });\n});\n\n// The executor is real; `getDefaultBranchName` throwing is the seam — the first dependency\n// `reconcileLane` awaits after the fetch, so the throw reaches the outer catch with no git/network work.\ndescribe('syncLane outer catch under --dry-run', () => {\n function throwingExecutor(gitHostCalls: string[]): LaneSyncExecutor {\n const noopLogger = { console: () => {}, consoleWarning: () => {}, error: () => {}, debug: () => {} };\n const executor = new LaneSyncExecutor({\n lanes: {} as any,\n ci: {\n getDefaultBranchName: async () => {\n throw new Error('boom');\n },\n } as any,\n logger: noopLogger as any,\n gitHost: {\n name: 'stub',\n findPrByBranch: async () => {\n gitHostCalls.push('findPrByBranch');\n return { number: 7, htmlUrl: 'https://example.test/pr/7', labels: [] };\n },\n addLabel: async () => {\n gitHostCalls.push('addLabel');\n },\n comment: async () => {\n gitHostCalls.push('comment');\n },\n } as any,\n cfg: resolveSyncConfig({}),\n defaultScope: 'acme.shop',\n });\n // Mark the fetch done so the spec never touches a repository or the network.\n (executor as any).fetched = true;\n return executor;\n }\n\n it('reports the halt without reading, labelling or commenting on the PR', async () => {\n const gitHostCalls: string[] = [];\n const summary = await throwingExecutor(gitHostCalls).syncLane(\n { hostScope: 'acme.shop', name: 'my-lane' },\n { dryRun: true }\n );\n expect(summary).to.equal('HALTED my-lane -> unexpected error: boom');\n expect(gitHostCalls).to.deep.equal([]);\n });\n\n it('is non-vacuous: without --dry-run the same failure does read, label and comment the PR', async () => {\n const gitHostCalls: string[] = [];\n const summary = await throwingExecutor(gitHostCalls).syncLane({ hostScope: 'acme.shop', name: 'my-lane' });\n expect(summary).to.equal('HALTED my-lane -> unexpected error: boom');\n expect(gitHostCalls).to.deep.equal(['findPrByBranch', 'addLabel', 'comment']);\n });\n\n // '-hostile' is a legal bit lane name (the charset allows a leading '-') that can never be a branch.\n it('a lane whose name cannot map to a branch halts report-only instead of throwing', async () => {\n const gitHostCalls: string[] = [];\n const summary = await throwingExecutor(gitHostCalls).syncLane({ hostScope: 'acme.shop', name: '-hostile' });\n expect(summary).to.match(/^HALTED -hostile -> unexpected error: .*not a valid git branch name/);\n expect(gitHostCalls).to.deep.equal([]);\n });\n});\n\n// bit's lane-name charset admits `$`, `-`, `_` and `!`, so an unquoted runbook shell-expands when pasted.\ndescribe('haltCommentBody', () => {\n const LANE_NAME = 'fix-$home-and-!bang';\n\n it('single-quotes every value it interpolates into a command', () => {\n const body = haltCommentBody({\n reason: 'merge conflicts in: acme.shop/comp1',\n branch: LANE_NAME,\n laneId: `acme.shop/${LANE_NAME}`,\n });\n expect(body).to.include(`git fetch origin && git checkout '${LANE_NAME}'`);\n expect(body).to.include(`bit lane import 'acme.shop/${LANE_NAME}'`);\n expect(body).to.include(`git push origin '${LANE_NAME}'`);\n // the reason is prose, not a command, and the runbook still reads as one\n expect(body).to.include('merge conflicts in: acme.shop/comp1');\n expect(body).to.include('Remove the `bit-sync-conflict` label to resume syncing.');\n });\n\n // A configured `branches` override only has to be a valid git ref, and git accepts a quote in one.\n it('escapes a value that itself contains a quote, rather than ending the quoting early', () => {\n const body = haltCommentBody({ reason: 'x', branch: \"it's-a-branch\", laneId: 'acme.shop/lane' });\n expect(body).to.include(`git checkout 'it'\\\\''s-a-branch'`);\n });\n\n it('leaves an overriding note alone: it carries no commands to quote', () => {\n const body = haltCommentBody({ reason: 'x', branch: LANE_NAME, laneId: 'acme.shop/lane', note: 'nothing to do' });\n expect(body).to.include('nothing to do');\n expect(body).to.not.include('git checkout');\n });\n});\n\n// `summarizeSync` decides the exit code by scanning for the prefix and nothing else, so a prefix-less\n// line makes a dry run report success on a plan the real run would have halted on.\ndescribe('dryRunSummaryLine', () => {\n it('carries the HALTED prefix and the reason for a planned halt, so the run exits non-zero', () => {\n const line = dryRunSummaryLine('my-lane', { type: 'halt', reason: 'cannot tell which side is newer' });\n expect(line).to.equal('HALTED my-lane -> cannot tell which side is newer');\n });\n\n it('leaves every other planned action unprefixed — those runs are healthy', () => {\n (['import-lane', 'export-branch', 'merge-diverged'] as const).forEach((type) => {\n const line = dryRunSummaryLine('my-lane', { type });\n expect(line, type).to.equal(`my-lane -> ${type}`);\n expect(line, type).to.not.contain('HALTED');\n expect(line, type).to.not.contain('REFUSED');\n });\n expect(dryRunSummaryLine('my-lane', { type: 'noop', reason: 'converged' })).to.equal('my-lane -> noop');\n expect(dryRunSummaryLine('my-lane', { type: 'close-pr', deleteBranch: true })).to.equal('my-lane -> close-pr');\n });\n});\n\n// The deletion decision is computed from refs fetched once per run; on an `--all` run the branch can\n// advance while earlier lanes are reconciled. Both seams are stubbed, so no repository is touched.\ndescribe('close-pr re-verifies the tip before retiring a branch', () => {\n const EVIDENCE_SHA = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1';\n const MOVED_SHA = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2';\n\n function retirer(currentTip: string | undefined, pushError?: Error) {\n const { executor, warnings } = stubExecutor();\n const pushes: string[][] = [];\n (executor as any).currentBranchTip = async () => currentTip;\n (executor as any).pushBranchDeletion = async (branch: string, sha: string) => {\n pushes.push([branch, sha]);\n if (pushError) throw pushError;\n };\n const closePr = () =>\n (executor as any).executeClosePr({\n laneName: 'my-lane',\n laneIdStr: 'acme.shop/my-lane',\n branch: 'my-lane',\n defaultBranch: 'main',\n deleteBranch: true,\n expectedTipSha: EVIDENCE_SHA,\n }) as Promise<string>;\n return { closePr, warnings, pushes };\n }\n\n it('deletes at the evidence sha while the branch is still there', async () => {\n const { closePr, pushes } = retirer(EVIDENCE_SHA);\n expect(await closePr()).to.equal('my-lane -> close-pr (no open PR, branch my-lane deleted)');\n expect(pushes).to.deep.equal([['my-lane', EVIDENCE_SHA]]);\n });\n\n it('KEEPS the branch when the tip moved during the run, pushing nothing at all', async () => {\n const { closePr, warnings, pushes } = retirer(MOVED_SHA);\n const summary = await closePr();\n expect(summary).to.contain('branch my-lane kept: its tip advanced after the ownership evidence was read');\n expect(pushes).to.deep.equal([]);\n expect(warnings.join('\\n')).to.contain(`its tip is now ${MOVED_SHA} rather than the ${EVIDENCE_SHA}`);\n });\n\n it('keeps the branch when the tip cannot be re-read at all, rather than trusting the stale answer', async () => {\n const { closePr, pushes } = retirer(undefined);\n expect(await closePr()).to.contain('branch my-lane kept: its tip advanced');\n expect(pushes).to.deep.equal([]);\n });\n\n // The re-read and the push are not atomic; the server gets the last word, and it is not a crash.\n it('reports a lease refusal as the same kept outcome', async () => {\n const { closePr, warnings } = retirer(\n EVIDENCE_SHA,\n new Error('! [rejected] (delete) -> my-lane (stale info)\\nerror: failed to push some refs')\n );\n expect(await closePr()).to.contain('branch my-lane kept: its tip advanced');\n expect(warnings.join('\\n')).to.contain('the remote refused the lease');\n });\n\n it('an unrelated push failure still reads as \"left in place\", not as a race', async () => {\n const { closePr } = retirer(EVIDENCE_SHA, new Error('remote: GH006: Protected branch update failed'));\n expect(await closePr()).to.equal('my-lane -> close-pr (no open PR, branch my-lane left in place)');\n });\n});\n\ndescribe('differentLaneStillClaims uses .bitmap blob equality, not commit reachability', () => {\n function executorWithInheritance(inherited: boolean) {\n const executor = new LaneSyncExecutor({\n lanes: {} as any,\n ci: {} as any,\n logger: { console: () => {}, consoleWarning: () => {}, error: () => {} } as any,\n gitHost: undefined,\n cfg: resolveSyncConfig({}),\n defaultScope: 'acme.shop',\n });\n (executor as any).branchInheritsBitmapFromDefault = async () => inherited;\n return (mirroredLane: string | undefined, laneIdStr: string) =>\n (executor as any).differentLaneStillClaims(mirroredLane, laneIdStr, 'my-branch', 'main') as Promise<boolean>;\n }\n\n it('does not claim when there is no mirrored lane pointer at all — never even checks the blob', async () => {\n const differentLaneStillClaims = executorWithInheritance(true);\n expect(await differentLaneStillClaims(undefined, 'acme.shop/my-lane')).to.equal(false);\n });\n\n it(\"does not claim for this lane's own pointer — never even checks the blob\", async () => {\n const differentLaneStillClaims = executorWithInheritance(true);\n expect(await differentLaneStillClaims('acme.shop/my-lane', 'acme.shop/my-lane')).to.equal(false);\n });\n\n it(\"does not claim when the different-lane .bitmap is byte-identical to the default branch's — inherited\", async () => {\n const differentLaneStillClaims = executorWithInheritance(true);\n expect(await differentLaneStillClaims('acme.shop/other-lane', 'acme.shop/my-lane')).to.equal(false);\n });\n\n it(\"STILL claims when the different-lane .bitmap has diverged from the default branch's — halt, not adopt\", async () => {\n const differentLaneStillClaims = executorWithInheritance(false);\n expect(await differentLaneStillClaims('acme.shop/other-lane', 'acme.shop/my-lane')).to.equal(true);\n });\n});\n\ndescribe('computeHasIndependentHistory gates the ancestry check to own-live claims with a state commit', () => {\n function executorWithAncestryResult(result: boolean) {\n const calls: Array<[string, string]> = [];\n const executor = new LaneSyncExecutor({\n lanes: {} as any,\n ci: {} as any,\n logger: { console: () => {}, consoleWarning: () => {}, error: () => {} } as any,\n gitHost: undefined,\n cfg: resolveSyncConfig({}),\n defaultScope: 'acme.shop',\n });\n (executor as any).hasIndependentHistoryBelowStateCommit = async (stateCommit: string, defaultBranch: string) => {\n calls.push([stateCommit, defaultBranch]);\n return result;\n };\n const compute = (ownership: LaneOwnershipEvidence, stateCommit: string | undefined, defaultBranch: string) =>\n (executor as any).computeHasIndependentHistory(ownership, stateCommit, defaultBranch) as Promise<boolean>;\n return { compute, calls };\n }\n\n it('skips the ancestry check entirely for a reachable claim (own-merged)', async () => {\n const { compute, calls } = executorWithAncestryResult(true);\n expect(await compute('own-merged', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1', 'main')).to.equal(false);\n expect(calls).to.deep.equal([]);\n });\n\n it('skips the ancestry check entirely for own-superseded too', async () => {\n const { compute, calls } = executorWithAncestryResult(true);\n expect(await compute('own-superseded', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1', 'main')).to.equal(false);\n expect(calls).to.deep.equal([]);\n });\n\n it('skips the check when there is no state commit to inspect, even for an own-live claim', async () => {\n const { compute, calls } = executorWithAncestryResult(true);\n expect(await compute('own-live', undefined, 'main')).to.equal(false);\n expect(calls).to.deep.equal([]);\n });\n\n it('defers to the ancestry check for an own-live claim with a state commit', async () => {\n const { compute, calls } = executorWithAncestryResult(true);\n expect(await compute('own-live', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1', 'main')).to.equal(true);\n expect(calls).to.deep.equal([['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1', 'main']]);\n });\n});\n\ndescribe('classifyPushRejection confirms a race before calling it one', () => {\n const BASE_SHA = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1';\n const MOVED_SHA = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb2';\n const REJECTION = new Error('! [rejected] HEAD -> feature (fetch first)\\nerror: failed to push some refs');\n\n function classifier(currentTip: string | undefined) {\n const { executor } = stubExecutor();\n (executor as any).currentBranchTip = async () => currentTip;\n return (baseSha: string | undefined, e: Error) =>\n (executor as any).classifyPushRejection('my-branch', baseSha, e) as Promise<'confirmed-race' | 'not-a-race'>;\n }\n\n it('confirms the race when the branch actually moved off the base we pushed against', async () => {\n const classify = classifier(MOVED_SHA);\n expect(await classify(BASE_SHA, REJECTION)).to.equal('confirmed-race');\n });\n\n it('confirms the race for a brand-new branch that now exists on the remote', async () => {\n const classify = classifier(MOVED_SHA);\n expect(await classify(undefined, REJECTION)).to.equal('confirmed-race');\n });\n\n // Message-text matching alone is not proof: a persistent, unrelated rejection could repeat the same\n // wording forever. Without this re-fetch-and-compare, that would go permanently green.\n it('answers not-a-race when the branch did NOT move — the wording matched but nothing raced', async () => {\n const classify = classifier(BASE_SHA);\n expect(await classify(BASE_SHA, REJECTION)).to.equal('not-a-race');\n });\n\n it('answers not-a-race when a brand-new branch still does not exist on the remote', async () => {\n const classify = classifier(undefined);\n expect(await classify(undefined, REJECTION)).to.equal('not-a-race');\n });\n\n // The polarity bug this guards: `currentTip === undefined` here means the re-fetch FAILED (network\n // blip, auth hiccup) — unknown, not evidence the branch moved. `undefined !== baseSha` reads as\n // truthy if compared naively, which would misreport an unanswerable check as a confirmed race and\n // paper over a real, persistent failure. Withhold like every other unknown-answer path in this file.\n it('answers not-a-race when the re-fetch itself fails, even though a base sha is known', async () => {\n const classify = classifier(undefined);\n expect(await classify(BASE_SHA, REJECTION)).to.equal('not-a-race');\n });\n\n it('answers not-a-race for a rejection whose wording is not a non-fast-forward race at all', async () => {\n const classify = classifier(MOVED_SHA);\n const unrelated = new Error('remote: GH006: Protected branch update failed');\n expect(await classify(BASE_SHA, unrelated)).to.equal('not-a-race');\n });\n});\n\n// The live incident's actual shape: the snap/export onto the lane already succeeded — the lane truly\n// moved — and only the branch's OWN ledger-commit push (recordLaneHeadOnBranch) lost the race. Nothing\n// exercised `racedLedgerPushSummary` before this; a wording regression there would have gone unnoticed.\ndescribe('executeExportBranch reports the ledger-race wording when only the ledger push races', () => {\n it('surfaces \"lane updated; branch ledger commit lost the push race\" without halting', async () => {\n const { executor } = stubExecutor();\n (executor as any).lastNonSyncCommitMessage = async () => 'feat: some change';\n (executor as any).checkoutFromRemote = async () => {};\n (executor as any).restoreWorkspace = async () => {};\n // The export half already succeeded; only the ledger commit that follows raced.\n (executor as any).snapAndExportOntoLane = async () => ({ status: 'exported' });\n (executor as any).recordLaneHeadOnBranch = async () => ({ status: 'raced' });\n\n const summary = await (executor as any).executeExportBranch({\n target: { hostScope: 'acme.shop', name: 'my-lane' },\n laneIdStr: 'acme.shop/my-lane',\n branch: 'my-lane',\n defaultBranch: 'main',\n });\n\n expect(summary).to.equal(\n 'my-lane -> raced (lane updated; branch ledger commit lost the push race — next run re-plans)'\n );\n expect(summary).to.not.include('HALTED');\n });\n});\n\n// Adoption never snaps or exports, so its raced line must NOT claim the lane was updated — the lane\n// is untouched and only the branch's pointer commit lost the race.\ndescribe('executeAdoptBranch reports a lane-untouched race when its ledger push races', () => {\n it('surfaces \"lane untouched; adoption ledger commit lost the push race\" without halting', async () => {\n const { executor } = stubExecutor();\n (executor as any).deps.ci = { hasUnsyncedWorkChanges: async () => false };\n (executor as any).checkoutFromRemote = async () => {};\n (executor as any).restoreWorkspace = async () => {};\n (executor as any).materializeLane = async () => undefined;\n (executor as any).recordLaneHeadOnBranch = async () => ({ status: 'raced' });\n\n const summary = await (executor as any).executeAdoptBranch({\n target: { hostScope: 'acme.shop', name: 'my-lane' },\n laneIdStr: 'acme.shop/my-lane',\n branch: 'my-lane',\n defaultBranch: 'main',\n });\n\n expect(summary).to.equal(\n 'my-lane -> raced (lane untouched; adoption ledger commit lost the push race — next run re-plans)'\n );\n expect(summary).to.not.include('lane updated');\n expect(summary).to.not.include('HALTED');\n });\n});\n\n// A destructive auto-resolution (onConflict git-wins/lane-wins) that already exported must not vanish\n// from the summary just because the ledger push raced.\ndescribe('racedLedgerPushSummary keeps the conflict-policy clause', () => {\n it('carries the merge path’s policyClause through the raced ledger line', () => {\n expect(racedLedgerPushSummary('my-lane', 'conflicts auto-resolved: git-wins on 3 file(s); ')).to.equal(\n 'my-lane -> raced (conflicts auto-resolved: git-wins on 3 file(s); lane updated; branch ledger commit ' +\n 'lost the push race — next run re-plans)'\n );\n });\n});\n\ndescribe('isProtectedBranch', () => {\n it('refuses the default branch and the main sync branch', () => {\n expect(isProtectedBranch('develop', 'develop', 'bit-sync/main')).to.equal(true);\n expect(isProtectedBranch('bit-sync/main', 'develop', 'bit-sync/main')).to.equal(true);\n });\n\n it('permits an ordinary lane branch', () => {\n expect(isProtectedBranch('my-lane', 'develop', 'bit-sync/main')).to.equal(false);\n });\n});\n"],"mappings":";;AAAA,SAAAA,MAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,KAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAE,kBAAA;EAAA,MAAAF,IAAA,GAAAC,OAAA;EAAAC,iBAAA,YAAAA,CAAA;IAAA,OAAAF,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAiBA,SAAAG,YAAA;EAAA,MAAAH,IAAA,GAAAC,OAAA;EAAAE,WAAA,YAAAA,CAAA;IAAA,OAAAH,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA;AACA;AACA;AACA;AACA,SAASI,YAAYA,CAAA,EAAuD;EAC1E,MAAMC,QAAkB,GAAG,EAAE;EAC7B,MAAMC,QAAQ,GAAG,KAAIC,oCAAgB,EAAC;IACpCC,KAAK,EAAE,CAAC,CAAQ;IAChBC,EAAE,EAAE,CAAC,CAAQ;IACbC,MAAM,EAAE;MAAEC,OAAO,EAAEA,CAAA,KAAM,CAAC,CAAC;MAAEC,cAAc,EAAGC,GAAW,IAAKR,QAAQ,CAACS,IAAI,CAACD,GAAG,CAAC;MAAEE,KAAK,EAAEA,CAAA,KAAM,CAAC;IAAE,CAAQ;IAC1GC,OAAO,EAAEC,SAAS;IAClBC,GAAG,EAAE,IAAAC,+BAAiB,EAAC,CAAC,CAAC,CAAC;IAC1BC,YAAY,EAAE;EAChB,CAAC,CAAC;EACF,OAAO;IAAEd,QAAQ;IAAED;EAAS,CAAC;AAC/B;AAIA;AACA,SAASgB,IAAIA,CAACC,EAAU,EAAEC,IAAY,EAA0B;EAC9D,OAAO;IACLD,EAAE,EAAE;MAAEE,sBAAsB,EAAEA,CAAA,KAAMF,EAAE;MAAEG,KAAK,EAAEH,EAAE,CAACI,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAAE,CAAC;IACpEH;EACF,CAAC;AACH;AAEAI,QAAQ,CAAC,qBAAqB,EAAE,MAAM;EACpC,MAAMC,CAAC,GAAGP,IAAI,CAAC,iBAAiB,EAAE,0CAA0C,CAAC;EAC7E,MAAMQ,CAAC,GAAGR,IAAI,CAAC,iBAAiB,EAAE,0CAA0C,CAAC;EAE7ES,EAAE,CAAC,+FAA+F,EAAE,MAAM;IACxG,MAAMC,WAAW,GAAG,IAAAC,uCAAmB,EAAC,CAACJ,CAAC,EAAEC,CAAC,CAAC,CAAC;IAC/C,IAAAI,cAAM,EAACF,WAAW,CAAC,CAACG,EAAE,CAACC,KAAK,CAAC,gBAAgB,CAAC;EAChD,CAAC,CAAC;EAEFL,EAAE,CAAC,wFAAwF,EAAE,MAAM;IACjG,IAAAG,cAAM,EAAC,IAAAD,uCAAmB,EAAC,CAACJ,CAAC,EAAEC,CAAC,CAAC,CAAC,CAAC,CAACK,EAAE,CAACE,KAAK,CAAC,IAAAJ,uCAAmB,EAAC,CAACH,CAAC,EAAED,CAAC,CAAC,CAAC,CAAC;EAC3E,CAAC,CAAC;EAEFE,EAAE,CAAC,uCAAuC,EAAE,MAAM;IAChD,MAAMO,KAAK,GAAGhB,IAAI,CAAC,iBAAiB,EAAE,0CAA0C,CAAC;IACjF,IAAAY,cAAM,EAAC,IAAAD,uCAAmB,EAAC,CAACJ,CAAC,EAAES,KAAK,CAAC,CAAC,CAAC,CAACH,EAAE,CAACI,GAAG,CAACF,KAAK,CAAC,IAAAJ,uCAAmB,EAAC,CAACJ,CAAC,EAAEC,CAAC,CAAC,CAAC,CAAC;EACnF,CAAC,CAAC;EAEFC,EAAE,CAAC,8CAA8C,EAAE,MAAM;IACvD,IAAAG,cAAM,EAAC,IAAAD,uCAAmB,EAAC,CAACJ,CAAC,CAAC,CAAC,CAAC,CAACM,EAAE,CAACI,GAAG,CAACF,KAAK,CAAC,IAAAJ,uCAAmB,EAAC,CAACJ,CAAC,EAAEC,CAAC,CAAC,CAAC,CAAC;IAC1E,IAAAI,cAAM,EAAC,IAAAD,uCAAmB,EAAC,EAAE,CAAC,CAAC,CAACE,EAAE,CAACI,GAAG,CAACF,KAAK,CAAC,IAAAJ,uCAAmB,EAAC,CAACJ,CAAC,CAAC,CAAC,CAAC;EACxE,CAAC,CAAC;EAEFE,EAAE,CAAC,yDAAyD,EAAE,MAAM;IAClE,IAAAG,cAAM,EAAC,IAAAD,uCAAmB,EAAC,CAACJ,CAAC,EAAEC,CAAC,CAAC,CAAC,CAAC,CAACK,EAAE,CAACE,KAAK,CAAC,IAAAJ,uCAAmB,EAAC,CAACX,IAAI,CAAC,iBAAiB,EAAEO,CAAC,CAACL,IAAI,CAAC,EAAEM,CAAC,CAAC,CAAC,CAAC;EACzG,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFF,QAAQ,CAAC,uBAAuB,EAAE,MAAM;EACtC,MAAMY,aAAa,GAAG,WAAW;EACjC,MAAMC,IAAI,GAAGnB,IAAI,CAAC,iBAAiB,EAAE,0CAA0C,CAAC;EAChF,MAAMoB,MAAM,GAAGpB,IAAI,CAAC,mBAAmB,EAAE,0CAA0C,CAAC;EAEpFS,EAAE,CAAC,sEAAsE,EAAE,MAAM;IAC/E,IAAAG,cAAM,EAAC,IAAAS,yCAAqB,EAAC,CAACF,IAAI,CAAC,EAAED,aAAa,CAAC,CAAC,CAACL,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;IACtE,IAAAH,cAAM,EAAC,IAAAS,yCAAqB,EAAC,EAAE,EAAEH,aAAa,CAAC,CAAC,CAACL,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EACpE,CAAC,CAAC;EAEFN,EAAE,CAAC,oDAAoD,EAAE,MAAM;IAC7D,IAAAG,cAAM,EAAC,IAAAS,yCAAqB,EAAC,CAACF,IAAI,EAAEC,MAAM,CAAC,EAAEF,aAAa,CAAC,CAAC,CAACL,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,CAAC,mBAAmB,CAAC,CAAC;EACnG,CAAC,CAAC;EAEFN,EAAE,CAAC,oFAAoF,EAAE,MAAM;IAC7F;IACA,MAAMc,UAAU,GAAGvB,IAAI,CAAC,qBAAqB,EAAE,0CAA0C,CAAC;IAC1F,IAAAY,cAAM,EAAC,IAAAS,yCAAqB,EAAC,CAACE,UAAU,CAAC,EAAEL,aAAa,CAAC,CAAC,CAACL,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EAC9E,CAAC,CAAC;EAEFN,EAAE,CAAC,4FAA4F,EAAE,MAAM;IACrG,IAAAG,cAAM,EAAC,IAAAS,yCAAqB,EAAC,CAACF,IAAI,CAAC,EAAED,aAAa,CAAC,CAAC,CAACL,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EACxE,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFT,QAAQ,CAAC,uBAAuB,EAAE,MAAM;EACtC,MAAMY,aAAa,GAAG,WAAW;EAEjCT,EAAE,CAAC,oDAAoD,EAAE,MAAM;IAC7D,MAAMe,WAAW,GAAG,IAAAC,yCAAqB,EAAC,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,EAAEP,aAAa,CAAC;IACpG,IAAAN,cAAM,EAACY,WAAW,CAAC,CAACX,EAAE,CAACa,OAAO,CAAC,mDAAmD,CAAC;IACnF,IAAAd,cAAM,EAACY,WAAW,CAAC,CAACX,EAAE,CAACa,OAAO,CAAC,yBAAyBR,aAAa,GAAG,CAAC;IACzE,IAAAN,cAAM,EAACY,WAAW,CAAC,CAACX,EAAE,CAACa,OAAO,CAAC,0DAA0D,CAAC;EAC5F,CAAC,CAAC;EAEFjB,EAAE,CAAC,+DAA+D,EAAE,MAAM;IACxE,MAAMkB,GAAG,GAAGC,KAAK,CAACC,IAAI,CAAC;MAAEC,MAAM,EAAE;IAAE,CAAC,EAAE,CAACC,CAAC,EAAEC,KAAK,KAAK,mBAAmBA,KAAK,EAAE,CAAC;IAC/E,MAAMR,WAAW,GAAG,IAAAC,yCAAqB,EAACE,GAAG,EAAET,aAAa,CAAC;IAC7D,IAAAN,cAAM,EAACY,WAAW,CAAC,CAACX,EAAE,CAACa,OAAO,CAAC,mBAAmB,CAAC;IACnD,IAAAd,cAAM,EAACY,WAAW,CAAC,CAACX,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,mBAAmB,CAAC;IACvD,IAAAd,cAAM,EAACY,WAAW,CAAC,CAACX,EAAE,CAACa,OAAO,CAAC,aAAa,CAAC;EAC/C,CAAC,CAAC;EAEFjB,EAAE,CAAC,mDAAmD,EAAE,MAAM;IAC5D,IAAAG,cAAM,EAAC,IAAAa,yCAAqB,EAAC,CAAC,mBAAmB,CAAC,EAAEP,aAAa,CAAC,CAAC,CAACL,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,MAAM,CAAC;EAC5F,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACApB,QAAQ,CAAC,gBAAgB,EAAE,MAAM;EAC/B,MAAM2B,SAAS,GAAG,0CAA0C;EAE5D,SAASC,IAAIA,CAACC,cAAsB,EAAE;IACpC,OAAO,IAAAC,kCAAc,EAAC;MACpBC,SAAS,EAAE,mBAAmB;MAC9BC,OAAO,EAAE,2CAA2C;MACpDC,MAAM,EAAE,SAAS;MACjBC,QAAQ,EAAEP,SAAS;MACnBQ,UAAU,EAAEb,KAAK,CAACC,IAAI,CAAC;QAAEC,MAAM,EAAEK;MAAe,CAAC,EAAE,CAACJ,CAAC,EAAEC,KAAK,KAC1DhC,IAAI,CAAC,uDAAuDgC,KAAK,EAAE,EAAE,GAAG,GAAG,CAACU,MAAM,CAAC,EAAE,CAAC,GAAGV,KAAK,GAAG,EAAE,EAAE,CACvG;IACF,CAAC,CAAC;EACJ;EAEAvB,EAAE,CAAC,kFAAkF,EAAE,MAAM;IAC3F,MAAMkC,QAAQ,GAAGT,IAAI,CAAC,GAAG,CAAC;IAC1B,IAAAtB,cAAM,EAAC+B,QAAQ,CAAC,CAAC9B,EAAE,CAACa,OAAO,CAAC,oCAAoC,CAAC;IACjE,IAAAd,cAAM,EAAC+B,QAAQ,CAAC,CAAC9B,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,oCAAoC,CAAC;IACrE,IAAAd,cAAM,EAAC+B,QAAQ,CAAC,CAAC9B,EAAE,CAACa,OAAO,CAAC,aAAa,CAAC;IAC1C,IAAAd,cAAM,EAAC+B,QAAQ,CAAC,CAAC9B,EAAE,CAACa,OAAO,CAAC,+BAA+B,CAAC;IAC5D,IAAAd,cAAM,EAAC+B,QAAQ,CAAC,CAAC9B,EAAE,CAACa,OAAO,CAAC,gBAAgBO,SAAS,IAAI,CAAC;EAC5D,CAAC,CAAC;EAEFxB,EAAE,CAAC,+DAA+D,EAAE,MAAM;IACxE,IAAAG,cAAM,EAACsB,IAAI,CAAC,GAAG,CAAC,CAACJ,MAAM,CAAC,CAACjB,EAAE,CAAC+B,EAAE,CAACC,KAAK,CAAC,KAAK,CAAC;IAC3C,IAAAjC,cAAM,EAACsB,IAAI,CAAC,IAAI,CAAC,CAACJ,MAAM,CAAC,CAACjB,EAAE,CAAC+B,EAAE,CAACC,KAAK,CAAC,KAAK,CAAC;EAC9C,CAAC,CAAC;EAEFpC,EAAE,CAAC,kDAAkD,EAAE,MAAM;IAC3D,MAAMkC,QAAQ,GAAGT,IAAI,CAAC,CAAC,CAAC;IACxB,IAAAtB,cAAM,EAAC+B,QAAQ,CAAC,CAAC9B,EAAE,CAACa,OAAO,CAAC,mCAAmC,CAAC;IAChE,IAAAd,cAAM,EAAC+B,QAAQ,CAAC,CAAC9B,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,MAAM,CAAC;IACvC,IAAAd,cAAM,EAAC+B,QAAQ,CAAC,CAAC9B,EAAE,CAACa,OAAO,CAAC,6BAA6B,CAAC;EAC5D,CAAC,CAAC;EAEFjB,EAAE,CAAC,oDAAoD,EAAE,MAAM;IAC7D,IAAAG,cAAM,EAACsB,IAAI,CAAC,CAAC,CAAC,CAAC,CAACrB,EAAE,CAACa,OAAO,CAAC,QAAQ,CAAC;EACtC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFpB,QAAQ,CAAC,8BAA8B,EAAE,MAAM;EAC7C,MAAMY,aAAa,GAAG,WAAW;EACjC,MAAM4B,OAAO,GAAG,CAAC,mBAAmB,CAAC;EAErCrC,EAAE,CAAC,mEAAmE,EAAE,MAAM;IAC5E,MAAMsC,OAAO,GAAG,IAAAC,yCAAqB,EAAC,SAAS,EAAEF,OAAO,EAAE5B,aAAa,CAAC;IACxE,IAAAN,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACC,KAAK,CAAC,0CAA0C,CAAC;IACpE,IAAAF,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACa,OAAO,CAAC,mBAAmB,CAAC;IAC/C;IACA,IAAAd,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,QAAQ,CAAC;IACxC,IAAAd,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,SAAS,CAAC;EAC3C,CAAC,CAAC;EAEFjB,EAAE,CAAC,gGAAgG,EAAE,MAAM;IACzG,MAAMwC,OAAO,GAAG,IAAAC,qCAAiB,EAACJ,OAAO,EAAE5B,aAAa,CAAC;IACzD,IAAAN,cAAM,EAACqC,OAAO,CAAC,CAACpC,EAAE,CAACa,OAAO,CAAC,wDAAwD,CAAC;IACpF,IAAAd,cAAM,EAACqC,OAAO,CAAC,CAACpC,EAAE,CAACa,OAAO,CAAC,6DAA6D,CAAC;IACzF,IAAAd,cAAM,EAACqC,OAAO,CAAC,CAACpC,EAAE,CAACa,OAAO,CAAC,+CAA+C,CAAC;EAC7E,CAAC,CAAC;EAEFjB,EAAE,CAAC,8EAA8E,EAAE,MAAM;IACvF,MAAMwC,OAAO,GAAG,IAAAC,qCAAiB,EAACJ,OAAO,EAAE5B,aAAa,EAAE,SAAS,CAAC;IACpE,IAAAN,cAAM,EAACqC,OAAO,CAAC,CAACpC,EAAE,CAACa,OAAO,CAAC,qEAAqE,CAAC;IACjG,IAAAd,cAAM,EAACqC,OAAO,CAAC,CAACpC,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,uBAAuB,CAAC;EACzD,CAAC,CAAC;EAEFjB,EAAE,CAAC,2FAA2F,EAAE,MAAM;IACpG,MAAM0C,MAAM,GAAG,IAAAC,iDAA6B,EAAC,SAAS,EAAEN,OAAO,EAAE5B,aAAa,CAAC;IAC/E,IAAAN,cAAM,EAACuC,MAAM,CAAC,CAACtC,EAAE,CAACa,OAAO,CAAC,4DAA4D,CAAC;IACvF,IAAAd,cAAM,EAACuC,MAAM,CAAC,CAACtC,EAAE,CAACa,OAAO,CAAC,2CAA2C,CAAC;EACxE,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFpB,QAAQ,CAAC,8BAA8B,EAAE,MAAM;EAC7CG,EAAE,CAAC,wEAAwE,EAAE,MAAM;IACjF,MAAM0C,MAAM,GAAG,IAAAE,gDAA4B,EAAC,SAAS,EAAE,qBAAqB,EAAE,mBAAmB,CAAC;IAClG,IAAAzC,cAAM,EAACuC,MAAM,CAAC,CAACtC,EAAE,CAACa,OAAO,CAAC,iDAAiD,CAAC;IAC5E,IAAAd,cAAM,EAACuC,MAAM,CAAC,CAACtC,EAAE,CAACa,OAAO,CAAC,wCAAwC,CAAC;IACnE,IAAAd,cAAM,EAACuC,MAAM,CAAC,CAACtC,EAAE,CAACa,OAAO,CAAC,mCAAmC,CAAC;EAChE,CAAC,CAAC;EAEFjB,EAAE,CAAC,0FAA0F,EAAE,MAAM;IACnG,MAAM6C,IAAI,GAAG,IAAAC,8CAA0B,EAAC,qBAAqB,EAAE,mBAAmB,CAAC;IACnF,IAAA3C,cAAM,EAAC0C,IAAI,CAAC,CAACzC,EAAE,CAACa,OAAO,CAAC,uCAAuC,CAAC;IAChE,IAAAd,cAAM,EAAC0C,IAAI,CAAC,CAACzC,EAAE,CAACa,OAAO,CAAC,0BAA0B,CAAC;IACnD,IAAAd,cAAM,EAAC0C,IAAI,CAAC,CAACzC,EAAE,CAACa,OAAO,CAAC,mBAAmB,CAAC;IAC5C,IAAAd,cAAM,EAAC0C,IAAI,CAAC,CAACzC,EAAE,CAACC,KAAK,CAAC,yDAAyD,CAAC;IAChF,IAAAF,cAAM,EAAC0C,IAAI,CAAC,CAACzC,EAAE,CAACa,OAAO,CAAC,6BAA6B,CAAC;IACtD,IAAAd,cAAM,EAAC0C,IAAI,CAAC,CAACzC,EAAE,CAACa,OAAO,CAAC,YAAY,CAAC;EACvC,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACApB,QAAQ,CAAC,sCAAsC,EAAE,MAAM;EACrD,SAASkD,gBAAgBA,CAACC,YAAsB,EAAoB;IAClE,MAAMC,UAAU,GAAG;MAAEpE,OAAO,EAAEA,CAAA,KAAM,CAAC,CAAC;MAAEC,cAAc,EAAEA,CAAA,KAAM,CAAC,CAAC;MAAEG,KAAK,EAAEA,CAAA,KAAM,CAAC,CAAC;MAAEiE,KAAK,EAAEA,CAAA,KAAM,CAAC;IAAE,CAAC;IACpG,MAAM1E,QAAQ,GAAG,KAAIC,oCAAgB,EAAC;MACpCC,KAAK,EAAE,CAAC,CAAQ;MAChBC,EAAE,EAAE;QACFwE,oBAAoB,EAAE,MAAAA,CAAA,KAAY;UAChC,MAAM,IAAIC,KAAK,CAAC,MAAM,CAAC;QACzB;MACF,CAAQ;MACRxE,MAAM,EAAEqE,UAAiB;MACzB/D,OAAO,EAAE;QACPmE,IAAI,EAAE,MAAM;QACZC,cAAc,EAAE,MAAAA,CAAA,KAAY;UAC1BN,YAAY,CAAChE,IAAI,CAAC,gBAAgB,CAAC;UACnC,OAAO;YAAEuE,MAAM,EAAE,CAAC;YAAEC,OAAO,EAAE,2BAA2B;YAAEC,MAAM,EAAE;UAAG,CAAC;QACxE,CAAC;QACDC,QAAQ,EAAE,MAAAA,CAAA,KAAY;UACpBV,YAAY,CAAChE,IAAI,CAAC,UAAU,CAAC;QAC/B,CAAC;QACD2E,OAAO,EAAE,MAAAA,CAAA,KAAY;UACnBX,YAAY,CAAChE,IAAI,CAAC,SAAS,CAAC;QAC9B;MACF,CAAQ;MACRI,GAAG,EAAE,IAAAC,+BAAiB,EAAC,CAAC,CAAC,CAAC;MAC1BC,YAAY,EAAE;IAChB,CAAC,CAAC;IACF;IACCd,QAAQ,CAASoF,OAAO,GAAG,IAAI;IAChC,OAAOpF,QAAQ;EACjB;EAEAwB,EAAE,CAAC,qEAAqE,EAAE,YAAY;IACpF,MAAMgD,YAAsB,GAAG,EAAE;IACjC,MAAMV,OAAO,GAAG,MAAMS,gBAAgB,CAACC,YAAY,CAAC,CAACa,QAAQ,CAC3D;MAAEC,SAAS,EAAE,WAAW;MAAET,IAAI,EAAE;IAAU,CAAC,EAC3C;MAAEU,MAAM,EAAE;IAAK,CACjB,CAAC;IACD,IAAA5D,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACE,KAAK,CAAC,0CAA0C,CAAC;IACpE,IAAAH,cAAM,EAAC6C,YAAY,CAAC,CAAC5C,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EACxC,CAAC,CAAC;EAEFN,EAAE,CAAC,wFAAwF,EAAE,YAAY;IACvG,MAAMgD,YAAsB,GAAG,EAAE;IACjC,MAAMV,OAAO,GAAG,MAAMS,gBAAgB,CAACC,YAAY,CAAC,CAACa,QAAQ,CAAC;MAAEC,SAAS,EAAE,WAAW;MAAET,IAAI,EAAE;IAAU,CAAC,CAAC;IAC1G,IAAAlD,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACE,KAAK,CAAC,0CAA0C,CAAC;IACpE,IAAAH,cAAM,EAAC6C,YAAY,CAAC,CAAC5C,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,CAAC,gBAAgB,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;EAC/E,CAAC,CAAC;;EAEF;EACAN,EAAE,CAAC,gFAAgF,EAAE,YAAY;IAC/F,MAAMgD,YAAsB,GAAG,EAAE;IACjC,MAAMV,OAAO,GAAG,MAAMS,gBAAgB,CAACC,YAAY,CAAC,CAACa,QAAQ,CAAC;MAAEC,SAAS,EAAE,WAAW;MAAET,IAAI,EAAE;IAAW,CAAC,CAAC;IAC3G,IAAAlD,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACC,KAAK,CAAC,qEAAqE,CAAC;IAC/F,IAAAF,cAAM,EAAC6C,YAAY,CAAC,CAAC5C,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EACxC,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACAT,QAAQ,CAAC,iBAAiB,EAAE,MAAM;EAChC,MAAMmE,SAAS,GAAG,qBAAqB;EAEvChE,EAAE,CAAC,0DAA0D,EAAE,MAAM;IACnE,MAAMyB,IAAI,GAAG,IAAAwC,mCAAe,EAAC;MAC3BvB,MAAM,EAAE,qCAAqC;MAC7CZ,MAAM,EAAEkC,SAAS;MACjBE,MAAM,EAAE,aAAaF,SAAS;IAChC,CAAC,CAAC;IACF,IAAA7D,cAAM,EAACsB,IAAI,CAAC,CAACrB,EAAE,CAACa,OAAO,CAAC,qCAAqC+C,SAAS,GAAG,CAAC;IAC1E,IAAA7D,cAAM,EAACsB,IAAI,CAAC,CAACrB,EAAE,CAACa,OAAO,CAAC,8BAA8B+C,SAAS,GAAG,CAAC;IACnE,IAAA7D,cAAM,EAACsB,IAAI,CAAC,CAACrB,EAAE,CAACa,OAAO,CAAC,oBAAoB+C,SAAS,GAAG,CAAC;IACzD;IACA,IAAA7D,cAAM,EAACsB,IAAI,CAAC,CAACrB,EAAE,CAACa,OAAO,CAAC,qCAAqC,CAAC;IAC9D,IAAAd,cAAM,EAACsB,IAAI,CAAC,CAACrB,EAAE,CAACa,OAAO,CAAC,yDAAyD,CAAC;EACpF,CAAC,CAAC;;EAEF;EACAjB,EAAE,CAAC,oFAAoF,EAAE,MAAM;IAC7F,MAAMyB,IAAI,GAAG,IAAAwC,mCAAe,EAAC;MAAEvB,MAAM,EAAE,GAAG;MAAEZ,MAAM,EAAE,eAAe;MAAEoC,MAAM,EAAE;IAAiB,CAAC,CAAC;IAChG,IAAA/D,cAAM,EAACsB,IAAI,CAAC,CAACrB,EAAE,CAACa,OAAO,CAAC,kCAAkC,CAAC;EAC7D,CAAC,CAAC;EAEFjB,EAAE,CAAC,kEAAkE,EAAE,MAAM;IAC3E,MAAMyB,IAAI,GAAG,IAAAwC,mCAAe,EAAC;MAAEvB,MAAM,EAAE,GAAG;MAAEZ,MAAM,EAAEkC,SAAS;MAAEE,MAAM,EAAE,gBAAgB;MAAErB,IAAI,EAAE;IAAgB,CAAC,CAAC;IACjH,IAAA1C,cAAM,EAACsB,IAAI,CAAC,CAACrB,EAAE,CAACa,OAAO,CAAC,eAAe,CAAC;IACxC,IAAAd,cAAM,EAACsB,IAAI,CAAC,CAACrB,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,cAAc,CAAC;EAC7C,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACApB,QAAQ,CAAC,mBAAmB,EAAE,MAAM;EAClCG,EAAE,CAAC,wFAAwF,EAAE,MAAM;IACjG,MAAMmE,IAAI,GAAG,IAAAC,qCAAiB,EAAC,SAAS,EAAE;MAAEC,IAAI,EAAE,MAAM;MAAE3B,MAAM,EAAE;IAAkC,CAAC,CAAC;IACtG,IAAAvC,cAAM,EAACgE,IAAI,CAAC,CAAC/D,EAAE,CAACE,KAAK,CAAC,mDAAmD,CAAC;EAC5E,CAAC,CAAC;EAEFN,EAAE,CAAC,uEAAuE,EAAE,MAAM;IAC/E,CAAC,aAAa,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAWsE,OAAO,CAAED,IAAI,IAAK;MAC9E,MAAMF,IAAI,GAAG,IAAAC,qCAAiB,EAAC,SAAS,EAAE;QAAEC;MAAK,CAAC,CAAC;MACnD,IAAAlE,cAAM,EAACgE,IAAI,EAAEE,IAAI,CAAC,CAACjE,EAAE,CAACE,KAAK,CAAC,cAAc+D,IAAI,EAAE,CAAC;MACjD,IAAAlE,cAAM,EAACgE,IAAI,EAAEE,IAAI,CAAC,CAACjE,EAAE,CAACI,GAAG,CAAC+D,OAAO,CAAC,QAAQ,CAAC;MAC3C,IAAApE,cAAM,EAACgE,IAAI,EAAEE,IAAI,CAAC,CAACjE,EAAE,CAACI,GAAG,CAAC+D,OAAO,CAAC,SAAS,CAAC;IAC9C,CAAC,CAAC;IACF,IAAApE,cAAM,EAAC,IAAAiE,qCAAiB,EAAC,SAAS,EAAE;MAAEC,IAAI,EAAE,MAAM;MAAE3B,MAAM,EAAE;IAAY,CAAC,CAAC,CAAC,CAACtC,EAAE,CAACE,KAAK,CAAC,iBAAiB,CAAC;IACvG,IAAAH,cAAM,EAAC,IAAAiE,qCAAiB,EAAC,SAAS,EAAE;MAAEC,IAAI,EAAE,UAAU;MAAEG,YAAY,EAAE;IAAK,CAAC,CAAC,CAAC,CAACpE,EAAE,CAACE,KAAK,CAAC,qBAAqB,CAAC;EAChH,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACAT,QAAQ,CAAC,uDAAuD,EAAE,MAAM;EACtE,MAAM4E,YAAY,GAAG,0CAA0C;EAC/D,MAAMC,SAAS,GAAG,0CAA0C;EAE5D,SAASC,OAAOA,CAACC,UAA8B,EAAEC,SAAiB,EAAE;IAClE,MAAM;MAAErG,QAAQ;MAAED;IAAS,CAAC,GAAGD,YAAY,CAAC,CAAC;IAC7C,MAAMwG,MAAkB,GAAG,EAAE;IAC5BtG,QAAQ,CAASuG,gBAAgB,GAAG,YAAYH,UAAU;IAC1DpG,QAAQ,CAASwG,kBAAkB,GAAG,OAAOlD,MAAc,EAAEmD,GAAW,KAAK;MAC5EH,MAAM,CAAC9F,IAAI,CAAC,CAAC8C,MAAM,EAAEmD,GAAG,CAAC,CAAC;MAC1B,IAAIJ,SAAS,EAAE,MAAMA,SAAS;IAChC,CAAC;IACD,MAAMK,OAAO,GAAGA,CAAA,KACb1G,QAAQ,CAAS2G,cAAc,CAAC;MAC/BC,QAAQ,EAAE,SAAS;MACnBxD,SAAS,EAAE,mBAAmB;MAC9BE,MAAM,EAAE,SAAS;MACjBuD,aAAa,EAAE,MAAM;MACrBb,YAAY,EAAE,IAAI;MAClBc,cAAc,EAAEb;IAClB,CAAC,CAAoB;IACvB,OAAO;MAAES,OAAO;MAAE3G,QAAQ;MAAEuG;IAAO,CAAC;EACtC;EAEA9E,EAAE,CAAC,6DAA6D,EAAE,YAAY;IAC5E,MAAM;MAAEkF,OAAO;MAAEJ;IAAO,CAAC,GAAGH,OAAO,CAACF,YAAY,CAAC;IACjD,IAAAtE,cAAM,EAAC,MAAM+E,OAAO,CAAC,CAAC,CAAC,CAAC9E,EAAE,CAACE,KAAK,CAAC,0DAA0D,CAAC;IAC5F,IAAAH,cAAM,EAAC2E,MAAM,CAAC,CAAC1E,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,CAAC,CAAC,SAAS,EAAEmE,YAAY,CAAC,CAAC,CAAC;EAC3D,CAAC,CAAC;EAEFzE,EAAE,CAAC,4EAA4E,EAAE,YAAY;IAC3F,MAAM;MAAEkF,OAAO;MAAE3G,QAAQ;MAAEuG;IAAO,CAAC,GAAGH,OAAO,CAACD,SAAS,CAAC;IACxD,MAAMpC,OAAO,GAAG,MAAM4C,OAAO,CAAC,CAAC;IAC/B,IAAA/E,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACmE,OAAO,CAAC,6EAA6E,CAAC;IACzG,IAAApE,cAAM,EAAC2E,MAAM,CAAC,CAAC1E,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;IAChC,IAAAH,cAAM,EAAC5B,QAAQ,CAACgH,IAAI,CAAC,IAAI,CAAC,CAAC,CAACnF,EAAE,CAACmE,OAAO,CAAC,kBAAkBG,SAAS,oBAAoBD,YAAY,EAAE,CAAC;EACvG,CAAC,CAAC;EAEFzE,EAAE,CAAC,+FAA+F,EAAE,YAAY;IAC9G,MAAM;MAAEkF,OAAO;MAAEJ;IAAO,CAAC,GAAGH,OAAO,CAACxF,SAAS,CAAC;IAC9C,IAAAgB,cAAM,EAAC,MAAM+E,OAAO,CAAC,CAAC,CAAC,CAAC9E,EAAE,CAACmE,OAAO,CAAC,uCAAuC,CAAC;IAC3E,IAAApE,cAAM,EAAC2E,MAAM,CAAC,CAAC1E,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EAClC,CAAC,CAAC;;EAEF;EACAN,EAAE,CAAC,kDAAkD,EAAE,YAAY;IACjE,MAAM;MAAEkF,OAAO;MAAE3G;IAAS,CAAC,GAAGoG,OAAO,CACnCF,YAAY,EACZ,IAAIrB,KAAK,CAAC,gFAAgF,CAC5F,CAAC;IACD,IAAAjD,cAAM,EAAC,MAAM+E,OAAO,CAAC,CAAC,CAAC,CAAC9E,EAAE,CAACmE,OAAO,CAAC,uCAAuC,CAAC;IAC3E,IAAApE,cAAM,EAAC5B,QAAQ,CAACgH,IAAI,CAAC,IAAI,CAAC,CAAC,CAACnF,EAAE,CAACmE,OAAO,CAAC,8BAA8B,CAAC;EACxE,CAAC,CAAC;EAEFvE,EAAE,CAAC,yEAAyE,EAAE,YAAY;IACxF,MAAM;MAAEkF;IAAQ,CAAC,GAAGP,OAAO,CAACF,YAAY,EAAE,IAAIrB,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACrG,IAAAjD,cAAM,EAAC,MAAM+E,OAAO,CAAC,CAAC,CAAC,CAAC9E,EAAE,CAACE,KAAK,CAAC,gEAAgE,CAAC;EACpG,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFT,QAAQ,CAAC,8EAA8E,EAAE,MAAM;EAC7F,SAAS2F,uBAAuBA,CAACC,SAAkB,EAAE;IACnD,MAAMjH,QAAQ,GAAG,KAAIC,oCAAgB,EAAC;MACpCC,KAAK,EAAE,CAAC,CAAQ;MAChBC,EAAE,EAAE,CAAC,CAAQ;MACbC,MAAM,EAAE;QAAEC,OAAO,EAAEA,CAAA,KAAM,CAAC,CAAC;QAAEC,cAAc,EAAEA,CAAA,KAAM,CAAC,CAAC;QAAEG,KAAK,EAAEA,CAAA,KAAM,CAAC;MAAE,CAAQ;MAC/EC,OAAO,EAAEC,SAAS;MAClBC,GAAG,EAAE,IAAAC,+BAAiB,EAAC,CAAC,CAAC,CAAC;MAC1BC,YAAY,EAAE;IAChB,CAAC,CAAC;IACDd,QAAQ,CAASkH,+BAA+B,GAAG,YAAYD,SAAS;IACzE,OAAO,CAACE,YAAgC,EAAE/D,SAAiB,KACxDpD,QAAQ,CAASoH,wBAAwB,CAACD,YAAY,EAAE/D,SAAS,EAAE,WAAW,EAAE,MAAM,CAAqB;EAChH;EAEA5B,EAAE,CAAC,2FAA2F,EAAE,YAAY;IAC1G,MAAM4F,wBAAwB,GAAGJ,uBAAuB,CAAC,IAAI,CAAC;IAC9D,IAAArF,cAAM,EAAC,MAAMyF,wBAAwB,CAACzG,SAAS,EAAE,mBAAmB,CAAC,CAAC,CAACiB,EAAE,CAACE,KAAK,CAAC,KAAK,CAAC;EACxF,CAAC,CAAC;EAEFN,EAAE,CAAC,yEAAyE,EAAE,YAAY;IACxF,MAAM4F,wBAAwB,GAAGJ,uBAAuB,CAAC,IAAI,CAAC;IAC9D,IAAArF,cAAM,EAAC,MAAMyF,wBAAwB,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAAC,CAACxF,EAAE,CAACE,KAAK,CAAC,KAAK,CAAC;EAClG,CAAC,CAAC;EAEFN,EAAE,CAAC,sGAAsG,EAAE,YAAY;IACrH,MAAM4F,wBAAwB,GAAGJ,uBAAuB,CAAC,IAAI,CAAC;IAC9D,IAAArF,cAAM,EAAC,MAAMyF,wBAAwB,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,CAAC,CAACxF,EAAE,CAACE,KAAK,CAAC,KAAK,CAAC;EACrG,CAAC,CAAC;EAEFN,EAAE,CAAC,uGAAuG,EAAE,YAAY;IACtH,MAAM4F,wBAAwB,GAAGJ,uBAAuB,CAAC,KAAK,CAAC;IAC/D,IAAArF,cAAM,EAAC,MAAMyF,wBAAwB,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,CAAC,CAACxF,EAAE,CAACE,KAAK,CAAC,IAAI,CAAC;EACpG,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFT,QAAQ,CAAC,8FAA8F,EAAE,MAAM;EAC7G,SAASgG,0BAA0BA,CAACC,MAAe,EAAE;IACnD,MAAMC,KAA8B,GAAG,EAAE;IACzC,MAAMvH,QAAQ,GAAG,KAAIC,oCAAgB,EAAC;MACpCC,KAAK,EAAE,CAAC,CAAQ;MAChBC,EAAE,EAAE,CAAC,CAAQ;MACbC,MAAM,EAAE;QAAEC,OAAO,EAAEA,CAAA,KAAM,CAAC,CAAC;QAAEC,cAAc,EAAEA,CAAA,KAAM,CAAC,CAAC;QAAEG,KAAK,EAAEA,CAAA,KAAM,CAAC;MAAE,CAAQ;MAC/EC,OAAO,EAAEC,SAAS;MAClBC,GAAG,EAAE,IAAAC,+BAAiB,EAAC,CAAC,CAAC,CAAC;MAC1BC,YAAY,EAAE;IAChB,CAAC,CAAC;IACDd,QAAQ,CAASwH,qCAAqC,GAAG,OAAOC,WAAmB,EAAEZ,aAAqB,KAAK;MAC9GU,KAAK,CAAC/G,IAAI,CAAC,CAACiH,WAAW,EAAEZ,aAAa,CAAC,CAAC;MACxC,OAAOS,MAAM;IACf,CAAC;IACD,MAAMI,OAAO,GAAGA,CAACC,SAAgC,EAAEF,WAA+B,EAAEZ,aAAqB,KACtG7G,QAAQ,CAAS4H,4BAA4B,CAACD,SAAS,EAAEF,WAAW,EAAEZ,aAAa,CAAqB;IAC3G,OAAO;MAAEa,OAAO;MAAEH;IAAM,CAAC;EAC3B;EAEA/F,EAAE,CAAC,sEAAsE,EAAE,YAAY;IACrF,MAAM;MAAEkG,OAAO;MAAEH;IAAM,CAAC,GAAGF,0BAA0B,CAAC,IAAI,CAAC;IAC3D,IAAA1F,cAAM,EAAC,MAAM+F,OAAO,CAAC,YAAY,EAAE,0CAA0C,EAAE,MAAM,CAAC,CAAC,CAAC9F,EAAE,CAACE,KAAK,CAAC,KAAK,CAAC;IACvG,IAAAH,cAAM,EAAC4F,KAAK,CAAC,CAAC3F,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EACjC,CAAC,CAAC;EAEFN,EAAE,CAAC,0DAA0D,EAAE,YAAY;IACzE,MAAM;MAAEkG,OAAO;MAAEH;IAAM,CAAC,GAAGF,0BAA0B,CAAC,IAAI,CAAC;IAC3D,IAAA1F,cAAM,EAAC,MAAM+F,OAAO,CAAC,gBAAgB,EAAE,0CAA0C,EAAE,MAAM,CAAC,CAAC,CAAC9F,EAAE,CAACE,KAAK,CAAC,KAAK,CAAC;IAC3G,IAAAH,cAAM,EAAC4F,KAAK,CAAC,CAAC3F,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EACjC,CAAC,CAAC;EAEFN,EAAE,CAAC,sFAAsF,EAAE,YAAY;IACrG,MAAM;MAAEkG,OAAO;MAAEH;IAAM,CAAC,GAAGF,0BAA0B,CAAC,IAAI,CAAC;IAC3D,IAAA1F,cAAM,EAAC,MAAM+F,OAAO,CAAC,UAAU,EAAE/G,SAAS,EAAE,MAAM,CAAC,CAAC,CAACiB,EAAE,CAACE,KAAK,CAAC,KAAK,CAAC;IACpE,IAAAH,cAAM,EAAC4F,KAAK,CAAC,CAAC3F,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,EAAE,CAAC;EACjC,CAAC,CAAC;EAEFN,EAAE,CAAC,wEAAwE,EAAE,YAAY;IACvF,MAAM;MAAEkG,OAAO;MAAEH;IAAM,CAAC,GAAGF,0BAA0B,CAAC,IAAI,CAAC;IAC3D,IAAA1F,cAAM,EAAC,MAAM+F,OAAO,CAAC,UAAU,EAAE,0CAA0C,EAAE,MAAM,CAAC,CAAC,CAAC9F,EAAE,CAACE,KAAK,CAAC,IAAI,CAAC;IACpG,IAAAH,cAAM,EAAC4F,KAAK,CAAC,CAAC3F,EAAE,CAACS,IAAI,CAACP,KAAK,CAAC,CAAC,CAAC,0CAA0C,EAAE,MAAM,CAAC,CAAC,CAAC;EACrF,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFT,QAAQ,CAAC,6DAA6D,EAAE,MAAM;EAC5E,MAAMwG,QAAQ,GAAG,0CAA0C;EAC3D,MAAM3B,SAAS,GAAG,0CAA0C;EAC5D,MAAM4B,SAAS,GAAG,IAAIlD,KAAK,CAAC,oFAAoF,CAAC;EAEjH,SAASmD,UAAUA,CAAC3B,UAA8B,EAAE;IAClD,MAAM;MAAEpG;IAAS,CAAC,GAAGF,YAAY,CAAC,CAAC;IAClCE,QAAQ,CAASuG,gBAAgB,GAAG,YAAYH,UAAU;IAC3D,OAAO,CAAC4B,OAA2B,EAAEC,CAAQ,KAC1CjI,QAAQ,CAASkI,qBAAqB,CAAC,WAAW,EAAEF,OAAO,EAAEC,CAAC,CAA6C;EAChH;EAEAzG,EAAE,CAAC,iFAAiF,EAAE,YAAY;IAChG,MAAM2G,QAAQ,GAAGJ,UAAU,CAAC7B,SAAS,CAAC;IACtC,IAAAvE,cAAM,EAAC,MAAMwG,QAAQ,CAACN,QAAQ,EAAEC,SAAS,CAAC,CAAC,CAAClG,EAAE,CAACE,KAAK,CAAC,gBAAgB,CAAC;EACxE,CAAC,CAAC;EAEFN,EAAE,CAAC,wEAAwE,EAAE,YAAY;IACvF,MAAM2G,QAAQ,GAAGJ,UAAU,CAAC7B,SAAS,CAAC;IACtC,IAAAvE,cAAM,EAAC,MAAMwG,QAAQ,CAACxH,SAAS,EAAEmH,SAAS,CAAC,CAAC,CAAClG,EAAE,CAACE,KAAK,CAAC,gBAAgB,CAAC;EACzE,CAAC,CAAC;;EAEF;EACA;EACAN,EAAE,CAAC,yFAAyF,EAAE,YAAY;IACxG,MAAM2G,QAAQ,GAAGJ,UAAU,CAACF,QAAQ,CAAC;IACrC,IAAAlG,cAAM,EAAC,MAAMwG,QAAQ,CAACN,QAAQ,EAAEC,SAAS,CAAC,CAAC,CAAClG,EAAE,CAACE,KAAK,CAAC,YAAY,CAAC;EACpE,CAAC,CAAC;EAEFN,EAAE,CAAC,+EAA+E,EAAE,YAAY;IAC9F,MAAM2G,QAAQ,GAAGJ,UAAU,CAACpH,SAAS,CAAC;IACtC,IAAAgB,cAAM,EAAC,MAAMwG,QAAQ,CAACxH,SAAS,EAAEmH,SAAS,CAAC,CAAC,CAAClG,EAAE,CAACE,KAAK,CAAC,YAAY,CAAC;EACrE,CAAC,CAAC;;EAEF;EACA;EACA;EACA;EACAN,EAAE,CAAC,oFAAoF,EAAE,YAAY;IACnG,MAAM2G,QAAQ,GAAGJ,UAAU,CAACpH,SAAS,CAAC;IACtC,IAAAgB,cAAM,EAAC,MAAMwG,QAAQ,CAACN,QAAQ,EAAEC,SAAS,CAAC,CAAC,CAAClG,EAAE,CAACE,KAAK,CAAC,YAAY,CAAC;EACpE,CAAC,CAAC;EAEFN,EAAE,CAAC,wFAAwF,EAAE,YAAY;IACvG,MAAM2G,QAAQ,GAAGJ,UAAU,CAAC7B,SAAS,CAAC;IACtC,MAAMkC,SAAS,GAAG,IAAIxD,KAAK,CAAC,+CAA+C,CAAC;IAC5E,IAAAjD,cAAM,EAAC,MAAMwG,QAAQ,CAACN,QAAQ,EAAEO,SAAS,CAAC,CAAC,CAACxG,EAAE,CAACE,KAAK,CAAC,YAAY,CAAC;EACpE,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACA;AACAT,QAAQ,CAAC,qFAAqF,EAAE,MAAM;EACpGG,EAAE,CAAC,kFAAkF,EAAE,YAAY;IACjG,MAAM;MAAExB;IAAS,CAAC,GAAGF,YAAY,CAAC,CAAC;IAClCE,QAAQ,CAASqI,wBAAwB,GAAG,YAAY,mBAAmB;IAC3ErI,QAAQ,CAASsI,kBAAkB,GAAG,YAAY,CAAC,CAAC;IACpDtI,QAAQ,CAASuI,gBAAgB,GAAG,YAAY,CAAC,CAAC;IACnD;IACCvI,QAAQ,CAASwI,qBAAqB,GAAG,aAAa;MAAEC,MAAM,EAAE;IAAW,CAAC,CAAC;IAC7EzI,QAAQ,CAAS0I,sBAAsB,GAAG,aAAa;MAAED,MAAM,EAAE;IAAQ,CAAC,CAAC;IAE5E,MAAM3E,OAAO,GAAG,MAAO9D,QAAQ,CAAS2I,mBAAmB,CAAC;MAC1DC,MAAM,EAAE;QAAEtD,SAAS,EAAE,WAAW;QAAET,IAAI,EAAE;MAAU,CAAC;MACnDzB,SAAS,EAAE,mBAAmB;MAC9BE,MAAM,EAAE,SAAS;MACjBuD,aAAa,EAAE;IACjB,CAAC,CAAC;IAEF,IAAAlF,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACE,KAAK,CACtB,8FACF,CAAC;IACD,IAAAH,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,QAAQ,CAAC;EAC1C,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACApB,QAAQ,CAAC,6EAA6E,EAAE,MAAM;EAC5FG,EAAE,CAAC,sFAAsF,EAAE,YAAY;IACrG,MAAM;MAAExB;IAAS,CAAC,GAAGF,YAAY,CAAC,CAAC;IAClCE,QAAQ,CAAS6I,IAAI,CAAC1I,EAAE,GAAG;MAAE2I,sBAAsB,EAAE,MAAAA,CAAA,KAAY;IAAM,CAAC;IACxE9I,QAAQ,CAASsI,kBAAkB,GAAG,YAAY,CAAC,CAAC;IACpDtI,QAAQ,CAASuI,gBAAgB,GAAG,YAAY,CAAC,CAAC;IAClDvI,QAAQ,CAAS+I,eAAe,GAAG,YAAYpI,SAAS;IACxDX,QAAQ,CAAS0I,sBAAsB,GAAG,aAAa;MAAED,MAAM,EAAE;IAAQ,CAAC,CAAC;IAE5E,MAAM3E,OAAO,GAAG,MAAO9D,QAAQ,CAASgJ,kBAAkB,CAAC;MACzDJ,MAAM,EAAE;QAAEtD,SAAS,EAAE,WAAW;QAAET,IAAI,EAAE;MAAU,CAAC;MACnDzB,SAAS,EAAE,mBAAmB;MAC9BE,MAAM,EAAE,SAAS;MACjBuD,aAAa,EAAE;IACjB,CAAC,CAAC;IAEF,IAAAlF,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACE,KAAK,CACtB,kGACF,CAAC;IACD,IAAAH,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,cAAc,CAAC;IAC9C,IAAAd,cAAM,EAACmC,OAAO,CAAC,CAAClC,EAAE,CAACI,GAAG,CAACS,OAAO,CAAC,QAAQ,CAAC;EAC1C,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACApB,QAAQ,CAAC,yDAAyD,EAAE,MAAM;EACxEG,EAAE,CAAC,qEAAqE,EAAE,MAAM;IAC9E,IAAAG,cAAM,EAAC,IAAAsH,0CAAsB,EAAC,SAAS,EAAE,kDAAkD,CAAC,CAAC,CAACrH,EAAE,CAACE,KAAK,CACpG,uGAAuG,GACrG,yCACJ,CAAC;EACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFT,QAAQ,CAAC,mBAAmB,EAAE,MAAM;EAClCG,EAAE,CAAC,qDAAqD,EAAE,MAAM;IAC9D,IAAAG,cAAM,EAAC,IAAAuH,qCAAiB,EAAC,SAAS,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC,CAACtH,EAAE,CAACE,KAAK,CAAC,IAAI,CAAC;IAC/E,IAAAH,cAAM,EAAC,IAAAuH,qCAAiB,EAAC,eAAe,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC,CAACtH,EAAE,CAACE,KAAK,CAAC,IAAI,CAAC;EACvF,CAAC,CAAC;EAEFN,EAAE,CAAC,iCAAiC,EAAE,MAAM;IAC1C,IAAAG,cAAM,EAAC,IAAAuH,qCAAiB,EAAC,SAAS,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC,CAACtH,EAAE,CAACE,KAAK,CAAC,KAAK,CAAC;EAClF,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
|
@@ -28,7 +28,14 @@ export type LaneSyncInput = {
|
|
|
28
28
|
* with `isSyncAuthoredMessage`, not the loop guard's substring match.
|
|
29
29
|
*/
|
|
30
30
|
tipIsSyncCommit: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The branch had real (non-bit) commits before this reconciler touched it — it was adopted, not
|
|
33
|
+
* manufactured. Can only withhold a delete, never authorize one.
|
|
34
|
+
*/
|
|
35
|
+
hasIndependentHistory?: boolean;
|
|
31
36
|
conflictLabelPresent: boolean;
|
|
37
|
+
/** The branch's committed `.bitmap` names a DIFFERENT lane — another lane's claim, never adopted. */
|
|
38
|
+
branchNamesDifferentLane?: boolean;
|
|
32
39
|
/** @see LaneOwnershipEvidence — consulted only on the "lane is gone" path. */
|
|
33
40
|
ownership: LaneOwnershipEvidence;
|
|
34
41
|
};
|
|
@@ -36,7 +43,7 @@ export type LaneSyncInput = {
|
|
|
36
43
|
* Why a `close-pr` is keeping the branch rather than deleting it. `tip-advanced-during-run` is the one
|
|
37
44
|
* the planner never emits: it is discovered when the executor re-reads the branch just before deleting.
|
|
38
45
|
*/
|
|
39
|
-
export type BranchKeepReason = 'unmerged-commits' | 'tip-not-a-sync-commit' | 'tip-advanced-during-run';
|
|
46
|
+
export type BranchKeepReason = 'unmerged-commits' | 'tip-not-a-sync-commit' | 'tip-advanced-during-run' | 'adopted-branch';
|
|
40
47
|
export type LaneSyncAction = {
|
|
41
48
|
type: 'noop';
|
|
42
49
|
reason: string;
|
|
@@ -46,6 +53,8 @@ export type LaneSyncAction = {
|
|
|
46
53
|
type: 'export-branch';
|
|
47
54
|
} | {
|
|
48
55
|
type: 'merge-diverged';
|
|
56
|
+
} | {
|
|
57
|
+
type: 'adopt-branch';
|
|
49
58
|
} | {
|
|
50
59
|
type: 'close-pr';
|
|
51
60
|
deleteBranch: true;
|
|
@@ -32,7 +32,9 @@ function planLaneSync(input) {
|
|
|
32
32
|
ownership
|
|
33
33
|
} = input;
|
|
34
34
|
const {
|
|
35
|
-
tipIsSyncCommit
|
|
35
|
+
tipIsSyncCommit,
|
|
36
|
+
hasIndependentHistory,
|
|
37
|
+
branchNamesDifferentLane
|
|
36
38
|
} = input;
|
|
37
39
|
if (conflictLabelPresent) {
|
|
38
40
|
return {
|
|
@@ -47,18 +49,34 @@ function planLaneSync(input) {
|
|
|
47
49
|
};
|
|
48
50
|
switch (ownership) {
|
|
49
51
|
case 'own-live':
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
// Each check is a separate reason to withhold a delete: dev commits are work that exists
|
|
53
|
+
// nowhere else; a non-sync tip may be a developer's own `.bitmap` write; an adopted branch's
|
|
54
|
+
// pre-existing history was never proven disposable. A false keep is harmless, a false delete
|
|
55
|
+
// destroys the only copy.
|
|
56
|
+
if (hasDevCommits) {
|
|
57
|
+
return {
|
|
58
|
+
type: 'close-pr',
|
|
59
|
+
deleteBranch: false,
|
|
60
|
+
keepReason: 'unmerged-commits'
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (!tipIsSyncCommit) {
|
|
64
|
+
return {
|
|
65
|
+
type: 'close-pr',
|
|
66
|
+
deleteBranch: false,
|
|
67
|
+
keepReason: 'tip-not-a-sync-commit'
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (hasIndependentHistory) {
|
|
71
|
+
return {
|
|
72
|
+
type: 'close-pr',
|
|
73
|
+
deleteBranch: false,
|
|
74
|
+
keepReason: 'adopted-branch'
|
|
75
|
+
};
|
|
76
|
+
}
|
|
58
77
|
return {
|
|
59
78
|
type: 'close-pr',
|
|
60
|
-
deleteBranch:
|
|
61
|
-
keepReason: hasDevCommits ? 'unmerged-commits' : 'tip-not-a-sync-commit'
|
|
79
|
+
deleteBranch: true
|
|
62
80
|
};
|
|
63
81
|
case 'own-merged':
|
|
64
82
|
// No marker conjunction needed: the tip being an ancestor of the default branch is unforgeable
|
|
@@ -86,9 +104,15 @@ function planLaneSync(input) {
|
|
|
86
104
|
};
|
|
87
105
|
if (!lastSyncedHead) {
|
|
88
106
|
if (hasDevCommits) {
|
|
107
|
+
if (branchNamesDifferentLane) {
|
|
108
|
+
return {
|
|
109
|
+
type: 'halt',
|
|
110
|
+
reason: 'branch has commits but its .bitmap names a different lane; cannot tell which side is newer'
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// The lane exists but the pair has no sync history: first contact, not a conflict.
|
|
89
114
|
return {
|
|
90
|
-
type: '
|
|
91
|
-
reason: 'branch has commits but its .bitmap records no state for this lane; cannot tell which side is newer'
|
|
115
|
+
type: 'adopt-branch'
|
|
92
116
|
};
|
|
93
117
|
}
|
|
94
118
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["planLaneSync","input","laneHead","branchExists","lastSyncedHead","hasDevCommits","conflictLabelPresent","ownership","tipIsSyncCommit","type","reason","deleteBranch","keepReason","laneMoved"],"sources":["sync-planner.ts"],"sourcesContent":["/**\n * How much of a claim this lane/branch pair has on `origin/<branch>` — the only thing that licenses\n * retiring it, because `close-pr` deletes the branch. Under the default config every branch name maps\n * to a same-named lane, and branches cut after a merged sync PR inherit its `.bitmap`, so \"looks\n * bit-managed\" is not enough. Evidence = attribution (the branch's `.bitmap` lane pointer) plus\n * reachability of the state commit / tip from the default branch:\n *\n * - `own-live` — names this lane; state commit not in the default branch (real, unmerged lane branch).\n * - `own-merged` — names this lane; branch tip already in the default branch (deleting loses nothing).\n * - `own-superseded` — state commit merged but tip not: close the PR, KEEP the branch.\n * - `inherited-or-none` — no pointer, another lane's, or unreadable: not ours, touch nothing.\n */\nexport type LaneOwnershipEvidence = 'own-live' | 'own-merged' | 'own-superseded' | 'inherited-or-none';\n\nexport type LaneSyncInput = {\n /** fingerprint of the lane's component heads on bit.cloud; undefined when the lane is gone */\n laneHead?: string;\n branchExists: boolean;\n /**\n * The lane-component fingerprint as the branch's committed `.bitmap` records it; undefined when the\n * branch holds no state for this lane. Equality with `laneHead` is the definition of converged.\n */\n lastSyncedHead?: string;\n /** whether the branch carries commits on top of the commit that last wrote its `.bitmap` */\n hasDevCommits: boolean;\n /**\n * Whether the reconciler itself wrote the tip commit. The one exception to \"markers are annotations\":\n * consulted only on the branch-deletion path, and only ever to WITHHOLD a deletion. Must be computed\n * with `isSyncAuthoredMessage`, not the loop guard's substring match.\n */\n tipIsSyncCommit: boolean;\n conflictLabelPresent: boolean;\n /** @see LaneOwnershipEvidence — consulted only on the \"lane is gone\" path. */\n ownership: LaneOwnershipEvidence;\n};\n\n/**\n * Why a `close-pr` is keeping the branch rather than deleting it. `tip-advanced-during-run` is the one\n * the planner never emits: it is discovered when the executor re-reads the branch just before deleting.\n */\nexport type BranchKeepReason
|
|
1
|
+
{"version":3,"names":["planLaneSync","input","laneHead","branchExists","lastSyncedHead","hasDevCommits","conflictLabelPresent","ownership","tipIsSyncCommit","hasIndependentHistory","branchNamesDifferentLane","type","reason","deleteBranch","keepReason","laneMoved"],"sources":["sync-planner.ts"],"sourcesContent":["/**\n * How much of a claim this lane/branch pair has on `origin/<branch>` — the only thing that licenses\n * retiring it, because `close-pr` deletes the branch. Under the default config every branch name maps\n * to a same-named lane, and branches cut after a merged sync PR inherit its `.bitmap`, so \"looks\n * bit-managed\" is not enough. Evidence = attribution (the branch's `.bitmap` lane pointer) plus\n * reachability of the state commit / tip from the default branch:\n *\n * - `own-live` — names this lane; state commit not in the default branch (real, unmerged lane branch).\n * - `own-merged` — names this lane; branch tip already in the default branch (deleting loses nothing).\n * - `own-superseded` — state commit merged but tip not: close the PR, KEEP the branch.\n * - `inherited-or-none` — no pointer, another lane's, or unreadable: not ours, touch nothing.\n */\nexport type LaneOwnershipEvidence = 'own-live' | 'own-merged' | 'own-superseded' | 'inherited-or-none';\n\nexport type LaneSyncInput = {\n /** fingerprint of the lane's component heads on bit.cloud; undefined when the lane is gone */\n laneHead?: string;\n branchExists: boolean;\n /**\n * The lane-component fingerprint as the branch's committed `.bitmap` records it; undefined when the\n * branch holds no state for this lane. Equality with `laneHead` is the definition of converged.\n */\n lastSyncedHead?: string;\n /** whether the branch carries commits on top of the commit that last wrote its `.bitmap` */\n hasDevCommits: boolean;\n /**\n * Whether the reconciler itself wrote the tip commit. The one exception to \"markers are annotations\":\n * consulted only on the branch-deletion path, and only ever to WITHHOLD a deletion. Must be computed\n * with `isSyncAuthoredMessage`, not the loop guard's substring match.\n */\n tipIsSyncCommit: boolean;\n /**\n * The branch had real (non-bit) commits before this reconciler touched it — it was adopted, not\n * manufactured. Can only withhold a delete, never authorize one.\n */\n hasIndependentHistory?: boolean;\n conflictLabelPresent: boolean;\n /** The branch's committed `.bitmap` names a DIFFERENT lane — another lane's claim, never adopted. */\n branchNamesDifferentLane?: boolean;\n /** @see LaneOwnershipEvidence — consulted only on the \"lane is gone\" path. */\n ownership: LaneOwnershipEvidence;\n};\n\n/**\n * Why a `close-pr` is keeping the branch rather than deleting it. `tip-advanced-during-run` is the one\n * the planner never emits: it is discovered when the executor re-reads the branch just before deleting.\n */\nexport type BranchKeepReason =\n | 'unmerged-commits'\n | 'tip-not-a-sync-commit'\n | 'tip-advanced-during-run'\n | 'adopted-branch';\n\nexport type LaneSyncAction =\n | { type: 'noop'; reason: string }\n | { type: 'import-lane' }\n | { type: 'export-branch' }\n | { type: 'merge-diverged' }\n | { type: 'adopt-branch' }\n // Two variants rather than an optional `keepReason` so the type enforces that a keep always says why.\n | { type: 'close-pr'; deleteBranch: true }\n | { type: 'close-pr'; deleteBranch: false; keepReason: BranchKeepReason }\n | { type: 'halt'; reason: string };\n\nexport function planLaneSync(input: LaneSyncInput): LaneSyncAction {\n const { laneHead, branchExists, lastSyncedHead, hasDevCommits, conflictLabelPresent, ownership } = input;\n const { tipIsSyncCommit, hasIndependentHistory, branchNamesDifferentLane } = input;\n if (conflictLabelPresent) {\n return { type: 'noop', reason: 'PR is labeled bit-sync-conflict; resolve and remove the label to resume' };\n }\n if (!laneHead) {\n if (!branchExists) return { type: 'noop', reason: 'lane and branch both absent' };\n switch (ownership) {\n case 'own-live':\n // Each check is a separate reason to withhold a delete: dev commits are work that exists\n // nowhere else; a non-sync tip may be a developer's own `.bitmap` write; an adopted branch's\n // pre-existing history was never proven disposable. A false keep is harmless, a false delete\n // destroys the only copy.\n if (hasDevCommits) {\n return { type: 'close-pr', deleteBranch: false, keepReason: 'unmerged-commits' };\n }\n if (!tipIsSyncCommit) {\n return { type: 'close-pr', deleteBranch: false, keepReason: 'tip-not-a-sync-commit' };\n }\n if (hasIndependentHistory) {\n return { type: 'close-pr', deleteBranch: false, keepReason: 'adopted-branch' };\n }\n return { type: 'close-pr', deleteBranch: true };\n case 'own-merged':\n // No marker conjunction needed: the tip being an ancestor of the default branch is unforgeable\n // proof that deleting loses nothing.\n return { type: 'close-pr', deleteBranch: true };\n case 'own-superseded':\n // Those commits are in no other ref.\n return { type: 'close-pr', deleteBranch: false, keepReason: 'unmerged-commits' };\n default:\n return { type: 'noop', reason: 'branch maps to no lane and has no sync history of its own; ignoring' };\n }\n }\n if (!branchExists) return { type: 'import-lane' };\n if (!lastSyncedHead) {\n if (hasDevCommits) {\n if (branchNamesDifferentLane) {\n return {\n type: 'halt',\n reason: 'branch has commits but its .bitmap names a different lane; cannot tell which side is newer',\n };\n }\n // The lane exists but the pair has no sync history: first contact, not a conflict.\n return { type: 'adopt-branch' };\n }\n return { type: 'import-lane' };\n }\n const laneMoved = laneHead !== lastSyncedHead;\n if (laneMoved && hasDevCommits) return { type: 'merge-diverged' };\n if (laneMoved) return { type: 'import-lane' };\n if (hasDevCommits) return { type: 'export-branch' };\n return { type: 'noop', reason: 'converged' };\n}\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAgCA;AACA;AACA;AACA;;AAkBO,SAASA,YAAYA,CAACC,KAAoB,EAAkB;EACjE,MAAM;IAAEC,QAAQ;IAAEC,YAAY;IAAEC,cAAc;IAAEC,aAAa;IAAEC,oBAAoB;IAAEC;EAAU,CAAC,GAAGN,KAAK;EACxG,MAAM;IAAEO,eAAe;IAAEC,qBAAqB;IAAEC;EAAyB,CAAC,GAAGT,KAAK;EAClF,IAAIK,oBAAoB,EAAE;IACxB,OAAO;MAAEK,IAAI,EAAE,MAAM;MAAEC,MAAM,EAAE;IAA0E,CAAC;EAC5G;EACA,IAAI,CAACV,QAAQ,EAAE;IACb,IAAI,CAACC,YAAY,EAAE,OAAO;MAAEQ,IAAI,EAAE,MAAM;MAAEC,MAAM,EAAE;IAA8B,CAAC;IACjF,QAAQL,SAAS;MACf,KAAK,UAAU;QACb;QACA;QACA;QACA;QACA,IAAIF,aAAa,EAAE;UACjB,OAAO;YAAEM,IAAI,EAAE,UAAU;YAAEE,YAAY,EAAE,KAAK;YAAEC,UAAU,EAAE;UAAmB,CAAC;QAClF;QACA,IAAI,CAACN,eAAe,EAAE;UACpB,OAAO;YAAEG,IAAI,EAAE,UAAU;YAAEE,YAAY,EAAE,KAAK;YAAEC,UAAU,EAAE;UAAwB,CAAC;QACvF;QACA,IAAIL,qBAAqB,EAAE;UACzB,OAAO;YAAEE,IAAI,EAAE,UAAU;YAAEE,YAAY,EAAE,KAAK;YAAEC,UAAU,EAAE;UAAiB,CAAC;QAChF;QACA,OAAO;UAAEH,IAAI,EAAE,UAAU;UAAEE,YAAY,EAAE;QAAK,CAAC;MACjD,KAAK,YAAY;QACf;QACA;QACA,OAAO;UAAEF,IAAI,EAAE,UAAU;UAAEE,YAAY,EAAE;QAAK,CAAC;MACjD,KAAK,gBAAgB;QACnB;QACA,OAAO;UAAEF,IAAI,EAAE,UAAU;UAAEE,YAAY,EAAE,KAAK;UAAEC,UAAU,EAAE;QAAmB,CAAC;MAClF;QACE,OAAO;UAAEH,IAAI,EAAE,MAAM;UAAEC,MAAM,EAAE;QAAsE,CAAC;IAC1G;EACF;EACA,IAAI,CAACT,YAAY,EAAE,OAAO;IAAEQ,IAAI,EAAE;EAAc,CAAC;EACjD,IAAI,CAACP,cAAc,EAAE;IACnB,IAAIC,aAAa,EAAE;MACjB,IAAIK,wBAAwB,EAAE;QAC5B,OAAO;UACLC,IAAI,EAAE,MAAM;UACZC,MAAM,EAAE;QACV,CAAC;MACH;MACA;MACA,OAAO;QAAED,IAAI,EAAE;MAAe,CAAC;IACjC;IACA,OAAO;MAAEA,IAAI,EAAE;IAAc,CAAC;EAChC;EACA,MAAMI,SAAS,GAAGb,QAAQ,KAAKE,cAAc;EAC7C,IAAIW,SAAS,IAAIV,aAAa,EAAE,OAAO;IAAEM,IAAI,EAAE;EAAiB,CAAC;EACjE,IAAII,SAAS,EAAE,OAAO;IAAEJ,IAAI,EAAE;EAAc,CAAC;EAC7C,IAAIN,aAAa,EAAE,OAAO;IAAEM,IAAI,EAAE;EAAgB,CAAC;EACnD,OAAO;IAAEA,IAAI,EAAE,MAAM;IAAEC,MAAM,EAAE;EAAY,CAAC;AAC9C","ignoreList":[]}
|
|
@@ -104,6 +104,18 @@ const table = [{
|
|
|
104
104
|
deleteBranch: false,
|
|
105
105
|
keepReason: 'unmerged-commits'
|
|
106
106
|
}
|
|
107
|
+
}, {
|
|
108
|
+
// Adoption proved content matched, never that the branch's pre-existing history is disposable.
|
|
109
|
+
name: 'own-live, no dev commits, OUR tip, but it is the adoption ledger commit -> KEEP, never delete',
|
|
110
|
+
input: _objectSpread(_objectSpread({}, laneGone('own-live')), {}, {
|
|
111
|
+
hasIndependentHistory: true
|
|
112
|
+
}),
|
|
113
|
+
type: 'close-pr',
|
|
114
|
+
action: {
|
|
115
|
+
type: 'close-pr',
|
|
116
|
+
deleteBranch: false,
|
|
117
|
+
keepReason: 'adopted-branch'
|
|
118
|
+
}
|
|
107
119
|
}, {
|
|
108
120
|
name: 'own-merged (branch tip already in the default branch) -> close-pr AND delete',
|
|
109
121
|
input: laneGone('own-merged'),
|
|
@@ -124,6 +136,16 @@ const table = [{
|
|
|
124
136
|
type: 'close-pr',
|
|
125
137
|
deleteBranch: true
|
|
126
138
|
}
|
|
139
|
+
}, {
|
|
140
|
+
name: 'own-merged deletes even when the tip is the adoption ledger commit — reachability is enough',
|
|
141
|
+
input: _objectSpread(_objectSpread({}, laneGone('own-merged')), {}, {
|
|
142
|
+
hasIndependentHistory: true
|
|
143
|
+
}),
|
|
144
|
+
type: 'close-pr',
|
|
145
|
+
action: {
|
|
146
|
+
type: 'close-pr',
|
|
147
|
+
deleteBranch: true
|
|
148
|
+
}
|
|
127
149
|
}, {
|
|
128
150
|
name: 'own-superseded (PR merged, then more commits pushed) -> close-pr but KEEP the branch',
|
|
129
151
|
input: laneGone('own-superseded'),
|
|
@@ -182,13 +204,33 @@ const table = [{
|
|
|
182
204
|
},
|
|
183
205
|
type: 'import-lane'
|
|
184
206
|
}, {
|
|
185
|
-
name: 'existing branch, never synced, has dev commits, lane EXISTS ->
|
|
207
|
+
name: 'existing branch, never synced, has dev commits, lane EXISTS -> adopt-branch (first contact)',
|
|
186
208
|
input: {
|
|
187
209
|
lastSyncedHead: undefined,
|
|
188
210
|
ownership: 'inherited-or-none',
|
|
189
211
|
hasDevCommits: true
|
|
190
212
|
},
|
|
191
|
-
type: '
|
|
213
|
+
type: 'adopt-branch'
|
|
214
|
+
}, {
|
|
215
|
+
name: 'existing branch, never synced, has dev commits, but .bitmap names a DIFFERENT lane -> halt',
|
|
216
|
+
input: {
|
|
217
|
+
lastSyncedHead: undefined,
|
|
218
|
+
ownership: 'inherited-or-none',
|
|
219
|
+
hasDevCommits: true,
|
|
220
|
+
branchNamesDifferentLane: true
|
|
221
|
+
},
|
|
222
|
+
type: 'halt',
|
|
223
|
+
reason: 'names a different lane'
|
|
224
|
+
}, {
|
|
225
|
+
// The executor resolves an inherited (merged) different-lane pointer to `false` — history, not a claim.
|
|
226
|
+
name: 'existing branch, has dev commits, .bitmap names a MERGED-AND-INHERITED different lane -> adopt-branch',
|
|
227
|
+
input: {
|
|
228
|
+
lastSyncedHead: undefined,
|
|
229
|
+
ownership: 'inherited-or-none',
|
|
230
|
+
hasDevCommits: true,
|
|
231
|
+
branchNamesDifferentLane: false
|
|
232
|
+
},
|
|
233
|
+
type: 'adopt-branch'
|
|
192
234
|
}];
|
|
193
235
|
describe('planLaneSync', () => {
|
|
194
236
|
table.forEach(({
|