@webpieces/pr-gate 0.3.360 → 0.3.362
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/package.json +2 -4
- package/src/dashboard/dashboard.js +2 -2
- package/src/dashboard/dashboard.js.map +1 -1
- package/src/scripts/commands/finish-update-command.js +2 -2
- package/src/scripts/commands/finish-update-command.js.map +1 -1
- package/src/scripts/commands/finish-upsert-pr-command.js +2 -2
- package/src/scripts/commands/finish-upsert-pr-command.js.map +1 -1
- package/src/scripts/commands/start-update-command.js +2 -2
- package/src/scripts/commands/start-update-command.js.map +1 -1
- package/src/scripts/commands/start-upsert-pr-command.js +2 -2
- package/src/scripts/commands/start-upsert-pr-command.js.map +1 -1
- package/src/scripts/git-gatherInfo.js +2 -2
- package/src/scripts/git-gatherInfo.js.map +1 -1
- package/src/scripts/pr-gate-app.js +4 -4
- package/src/scripts/pr-gate-app.js.map +1 -1
- package/src/scripts/workflow/branch-naming.js +2 -2
- package/src/scripts/workflow/branch-naming.js.map +1 -1
- package/src/scripts/workflow/build-affected.js +2 -2
- package/src/scripts/workflow/build-affected.js.map +1 -1
- package/src/scripts/workflow/cleanTmp.js +2 -2
- package/src/scripts/workflow/cleanTmp.js.map +1 -1
- package/src/scripts/workflow/git-exec.js +2 -2
- package/src/scripts/workflow/git-exec.js.map +1 -1
- package/src/scripts/workflow/git-findForkPoint.js +2 -2
- package/src/scripts/workflow/git-findForkPoint.js.map +1 -1
- package/src/scripts/workflow/git-readAiBranchName.js +2 -2
- package/src/scripts/workflow/git-readAiBranchName.js.map +1 -1
- package/src/scripts/workflow/merge-end.js +2 -2
- package/src/scripts/workflow/merge-end.js.map +1 -1
- package/src/scripts/workflow/merge-start.js +2 -2
- package/src/scripts/workflow/merge-start.js.map +1 -1
- package/src/scripts/workflow/merge-state.js +2 -2
- package/src/scripts/workflow/merge-state.js.map +1 -1
- package/src/scripts/workflow/open-pr-check.js +2 -2
- package/src/scripts/workflow/open-pr-check.js.map +1 -1
- package/src/scripts/workflow/run-update.js +2 -2
- package/src/scripts/workflow/run-update.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-state.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/merge-state.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport {\n WEBPIECES_TMP_DIR,\n MERGE_INFO_DIR,\n MERGE_IN_PROGRESS_FILE,\n MERGE_EXPLANATION_FILE,\n} from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\n\n// Proof-obligation marker written when a 3-point squash-merge hits conflicts. Its mere\n// presence (with validated=false) is what the merge-in-progress-guard hook uses to block\n// commit/push/PR until `wp-finish-upsert-pr` validates the resolution and flips it true.\nexport class MergeMarker {\n currentBranch: string;\n squashBranch: string;\n backupBranch: string;\n prNumber: string;\n conflictedFiles: string[];\n forkPoint: string;\n featureHead: string;\n mainHead: string;\n validated: boolean;\n\n constructor(\n currentBranch: string,\n squashBranch: string,\n backupBranch: string,\n prNumber: string,\n conflictedFiles: string[],\n forkPoint: string,\n featureHead: string,\n mainHead: string,\n validated: boolean,\n ) {\n this.currentBranch = currentBranch;\n this.squashBranch = squashBranch;\n this.backupBranch = backupBranch;\n this.prNumber = prNumber;\n this.conflictedFiles = conflictedFiles;\n this.forkPoint = forkPoint;\n this.featureHead = featureHead;\n this.mainHead = mainHead;\n this.validated = validated;\n }\n}\n\nexport class MarkerScanResult {\n clean: boolean;\n filesWithMarkers: string[];\n\n constructor(clean: boolean, filesWithMarkers: string[]) {\n this.clean = clean;\n this.filesWithMarkers = filesWithMarkers;\n }\n}\n\n// Data-only: the three commit points of a 3-point merge as persisted in `updatemain-hashes.json`\n// (the exact key shape the conflict path already writes), plus when it was recorded.\nexport class MergeHashRecord {\n hashForkPoint: string;\n hashFeatureHead: string;\n hashMainHead: string;\n timestamp: string;\n\n constructor(hashForkPoint: string, hashFeatureHead: string, hashMainHead: string, timestamp: string) {\n this.hashForkPoint = hashForkPoint;\n this.hashFeatureHead = hashFeatureHead;\n this.hashMainHead = hashMainHead;\n this.timestamp = timestamp;\n }\n}\n\nconst CONFLICT_MARKER_RE = /^(<{7}|={7}|>{7})/m;\n\n// Marker written for a CLEAN (no-conflict) sync so every merge — not just conflicted ones — leaves a\n// durable, self-describing record under `merge-info/<feature>/merge-<n>/`. A clean merge produces no\n// per-file `merge-explanation.md`; this file is the \"yes, a merge happened here, and it needed no\n// 3-point resolution\" proof, with the A/B/C shas kept so it stays auditable.\nexport const NO_CONFLICT_MARKER_FILE = 'no-3point-merge.md';\n\n/** Filesystem layout + read/write of the per-feature merge run dirs and their conflict markers. */\n@provideSingleton()\n@injectable()\nexport class MergeState {\n // The per-feature \"home\" dir `.webpieces/merge-info/<slug>/`. It no longer holds the marker/context\n // directly — each sync gets its own numbered `merge-<n>/` run dir underneath (mergeRunDirFor),\n // paired with the sync's `<feature>PreMerge<n>` backup branch. This keeps merge N from ever reusing\n // merge N-1's stale per-file context / merge-explanation.md.\n mergeDirFor(repoRoot: string, featureName: string): string {\n return path.join(repoRoot, WEBPIECES_TMP_DIR, MERGE_INFO_DIR, featureName);\n }\n\n // The run dir for sync number `n`: `<home>/merge-<n>/`. Holds this sync's marker + per-file\n // `updatemain-<file>/` context. Numbered to match the sync's `<feature>PreMerge<n>` backup branch.\n mergeRunDirFor(home: string, n: number): string {\n return path.join(home, `merge-${n}`);\n }\n\n // The next NEVER-REUSED merge slot number for a feature home: one past the highest existing\n // `merge-<n>/` dir (or 1 if none). Durable, monotonic source of truth for slot numbers — derived\n // from the audit dirs THEMSELVES, not from which transient `<feature>PreMerge<n>` branch exists.\n nextMergeSlotNumber(home: string): number {\n if (!fs.existsSync(home)) return 1;\n let max = 0;\n for (const entry of fs.readdirSync(home)) {\n const match = entry.match(/^merge-(\\d+)$/);\n if (match === null) continue;\n const n = parseInt(match[1], 10);\n if (n > max) max = n;\n }\n return max + 1;\n }\n\n // Write the clean-merge marker + a per-slot `updatemain-hashes.json` copy into the slot's own dir.\n writeCleanMergeMarker(mergeDir: string, forkPoint: string, featureHead: string, mainHead: string): void {\n fs.mkdirSync(mergeDir, { recursive: true });\n const body =\n '# Clean squash-merge — no 3-point conflict resolution needed\\n\\n' +\n 'This sync merged main into the feature with no conflicts, so the AI wrote no per-file\\n' +\n 'merge-explanation.md. The 3-point shas below are kept so the merge is still auditable.\\n\\n' +\n `3-point shas: A(fork)=${forkPoint} B(feature)=${featureHead} C(main)=${mainHead}\\n\\n` +\n 'Reconstruct what each side changed:\\n' +\n ` feature (B−A): git diff ${forkPoint} ${featureHead}\\n` +\n ` main (C−A): git diff ${forkPoint} ${mainHead}\\n`;\n fs.writeFileSync(path.join(mergeDir, NO_CONFLICT_MARKER_FILE), body);\n const record = new MergeHashRecord(forkPoint, featureHead, mainHead, new Date().toISOString());\n fs.writeFileSync(path.join(mergeDir, 'updatemain-hashes.json'), JSON.stringify(record, null, 2) + '\\n');\n }\n\n // Locate the in-progress merge's run dir: the `<home>/merge-*/` subdir holding a marker. There is\n // at most one; if more than one somehow exists, prefer an UNVALIDATED marker (the live conflict),\n // else return the first found. Null when none.\n findActiveMergeRunDir(home: string): string | null {\n if (!fs.existsSync(home)) return null;\n let fallback: string | null = null;\n for (const entry of fs.readdirSync(home)) {\n if (!entry.startsWith('merge-')) continue;\n const dir = path.join(home, entry);\n const marker = this.readMergeMarker(dir);\n if (marker === null) continue;\n if (!marker.validated) return dir;\n if (fallback === null) fallback = dir;\n }\n return fallback;\n }\n\n // Per-conflicted-file context dir holding A-forkpoint.txt / B-feature.txt / C-main.txt /\n // B-A.diff / C-A.diff (and the AI's merge-explanation.md). Shared so writer and reader agree on the\n // layout: the conflict file path with `/` → `__`, prefixed `updatemain-`.\n perFileContextDir(mergeDir: string, file: string): string {\n return path.join(mergeDir, `updatemain-${file.replace(/\\//g, '__')}`);\n }\n\n markerPath(mergeDir: string): string {\n return path.join(mergeDir, MERGE_IN_PROGRESS_FILE);\n }\n\n readMergeMarker(mergeDir: string): MergeMarker | null {\n const filePath = this.markerPath(mergeDir);\n if (!fs.existsSync(filePath)) return null;\n const raw = JSON.parse(fs.readFileSync(filePath, 'utf8')) as MergeMarker;\n return new MergeMarker(\n raw.currentBranch,\n raw.squashBranch,\n raw.backupBranch,\n raw.prNumber,\n raw.conflictedFiles ?? [],\n raw.forkPoint,\n raw.featureHead,\n raw.mainHead,\n raw.validated === true,\n );\n }\n\n writeMergeMarker(mergeDir: string, marker: MergeMarker): void {\n fs.mkdirSync(mergeDir, { recursive: true });\n fs.writeFileSync(this.markerPath(mergeDir), JSON.stringify(marker, null, 2) + '\\n');\n }\n\n clearMergeMarker(mergeDir: string): void {\n const filePath = this.markerPath(mergeDir);\n if (fs.existsSync(filePath)) fs.rmSync(filePath);\n }\n\n /**\n * Scoped conflict-marker scan: reads ONLY the given conflicted files (relative to repo root),\n * never the whole repo — stays O(conflicts) regardless of monorepo size.\n */\n scanConflictMarkers(repoRoot: string, files: string[]): MarkerScanResult {\n const filesWithMarkers: string[] = [];\n for (const file of files) {\n const abs = path.join(repoRoot, file);\n if (!fs.existsSync(abs)) continue;\n const content = fs.readFileSync(abs, 'utf8');\n if (CONFLICT_MARKER_RE.test(content)) filesWithMarkers.push(file);\n }\n return new MarkerScanResult(filesWithMarkers.length === 0, filesWithMarkers);\n }\n\n /**\n * Explanation scan: every conflicted file the AI resolved must have a non-empty\n * MERGE_EXPLANATION_FILE in its per-file context dir (next to the diffs), proving the AI\n * deliberately 3-point merged it and recording HOW. Returns files whose explanation is missing or\n * empty. Works for every conflicted file type — including comment-less files (JSON) and files\n * resolved by deletion (no working-tree file to inspect).\n */\n scanMergeExplanations(mergeDir: string, files: string[]): MarkerScanResult {\n const filesMissingExplanation: string[] = [];\n for (const file of files) {\n const explPath = path.join(this.perFileContextDir(mergeDir, file), MERGE_EXPLANATION_FILE);\n const present = fs.existsSync(explPath) && fs.readFileSync(explPath, 'utf8').trim() !== '';\n if (!present) filesMissingExplanation.push(file);\n }\n return new MarkerScanResult(filesMissingExplanation.length === 0, filesMissingExplanation);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"merge-state.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/merge-state.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport {\n WEBPIECES_TMP_DIR,\n MERGE_INFO_DIR,\n MERGE_IN_PROGRESS_FILE,\n MERGE_EXPLANATION_FILE,\n} from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/rules-config';\nimport { injectable } from 'inversify';\n\n// Proof-obligation marker written when a 3-point squash-merge hits conflicts. Its mere\n// presence (with validated=false) is what the merge-in-progress-guard hook uses to block\n// commit/push/PR until `wp-finish-upsert-pr` validates the resolution and flips it true.\nexport class MergeMarker {\n currentBranch: string;\n squashBranch: string;\n backupBranch: string;\n prNumber: string;\n conflictedFiles: string[];\n forkPoint: string;\n featureHead: string;\n mainHead: string;\n validated: boolean;\n\n constructor(\n currentBranch: string,\n squashBranch: string,\n backupBranch: string,\n prNumber: string,\n conflictedFiles: string[],\n forkPoint: string,\n featureHead: string,\n mainHead: string,\n validated: boolean,\n ) {\n this.currentBranch = currentBranch;\n this.squashBranch = squashBranch;\n this.backupBranch = backupBranch;\n this.prNumber = prNumber;\n this.conflictedFiles = conflictedFiles;\n this.forkPoint = forkPoint;\n this.featureHead = featureHead;\n this.mainHead = mainHead;\n this.validated = validated;\n }\n}\n\nexport class MarkerScanResult {\n clean: boolean;\n filesWithMarkers: string[];\n\n constructor(clean: boolean, filesWithMarkers: string[]) {\n this.clean = clean;\n this.filesWithMarkers = filesWithMarkers;\n }\n}\n\n// Data-only: the three commit points of a 3-point merge as persisted in `updatemain-hashes.json`\n// (the exact key shape the conflict path already writes), plus when it was recorded.\nexport class MergeHashRecord {\n hashForkPoint: string;\n hashFeatureHead: string;\n hashMainHead: string;\n timestamp: string;\n\n constructor(hashForkPoint: string, hashFeatureHead: string, hashMainHead: string, timestamp: string) {\n this.hashForkPoint = hashForkPoint;\n this.hashFeatureHead = hashFeatureHead;\n this.hashMainHead = hashMainHead;\n this.timestamp = timestamp;\n }\n}\n\nconst CONFLICT_MARKER_RE = /^(<{7}|={7}|>{7})/m;\n\n// Marker written for a CLEAN (no-conflict) sync so every merge — not just conflicted ones — leaves a\n// durable, self-describing record under `merge-info/<feature>/merge-<n>/`. A clean merge produces no\n// per-file `merge-explanation.md`; this file is the \"yes, a merge happened here, and it needed no\n// 3-point resolution\" proof, with the A/B/C shas kept so it stays auditable.\nexport const NO_CONFLICT_MARKER_FILE = 'no-3point-merge.md';\n\n/** Filesystem layout + read/write of the per-feature merge run dirs and their conflict markers. */\n@provideSingleton()\n@injectable()\nexport class MergeState {\n // The per-feature \"home\" dir `.webpieces/merge-info/<slug>/`. It no longer holds the marker/context\n // directly — each sync gets its own numbered `merge-<n>/` run dir underneath (mergeRunDirFor),\n // paired with the sync's `<feature>PreMerge<n>` backup branch. This keeps merge N from ever reusing\n // merge N-1's stale per-file context / merge-explanation.md.\n mergeDirFor(repoRoot: string, featureName: string): string {\n return path.join(repoRoot, WEBPIECES_TMP_DIR, MERGE_INFO_DIR, featureName);\n }\n\n // The run dir for sync number `n`: `<home>/merge-<n>/`. Holds this sync's marker + per-file\n // `updatemain-<file>/` context. Numbered to match the sync's `<feature>PreMerge<n>` backup branch.\n mergeRunDirFor(home: string, n: number): string {\n return path.join(home, `merge-${n}`);\n }\n\n // The next NEVER-REUSED merge slot number for a feature home: one past the highest existing\n // `merge-<n>/` dir (or 1 if none). Durable, monotonic source of truth for slot numbers — derived\n // from the audit dirs THEMSELVES, not from which transient `<feature>PreMerge<n>` branch exists.\n nextMergeSlotNumber(home: string): number {\n if (!fs.existsSync(home)) return 1;\n let max = 0;\n for (const entry of fs.readdirSync(home)) {\n const match = entry.match(/^merge-(\\d+)$/);\n if (match === null) continue;\n const n = parseInt(match[1], 10);\n if (n > max) max = n;\n }\n return max + 1;\n }\n\n // Write the clean-merge marker + a per-slot `updatemain-hashes.json` copy into the slot's own dir.\n writeCleanMergeMarker(mergeDir: string, forkPoint: string, featureHead: string, mainHead: string): void {\n fs.mkdirSync(mergeDir, { recursive: true });\n const body =\n '# Clean squash-merge — no 3-point conflict resolution needed\\n\\n' +\n 'This sync merged main into the feature with no conflicts, so the AI wrote no per-file\\n' +\n 'merge-explanation.md. The 3-point shas below are kept so the merge is still auditable.\\n\\n' +\n `3-point shas: A(fork)=${forkPoint} B(feature)=${featureHead} C(main)=${mainHead}\\n\\n` +\n 'Reconstruct what each side changed:\\n' +\n ` feature (B−A): git diff ${forkPoint} ${featureHead}\\n` +\n ` main (C−A): git diff ${forkPoint} ${mainHead}\\n`;\n fs.writeFileSync(path.join(mergeDir, NO_CONFLICT_MARKER_FILE), body);\n const record = new MergeHashRecord(forkPoint, featureHead, mainHead, new Date().toISOString());\n fs.writeFileSync(path.join(mergeDir, 'updatemain-hashes.json'), JSON.stringify(record, null, 2) + '\\n');\n }\n\n // Locate the in-progress merge's run dir: the `<home>/merge-*/` subdir holding a marker. There is\n // at most one; if more than one somehow exists, prefer an UNVALIDATED marker (the live conflict),\n // else return the first found. Null when none.\n findActiveMergeRunDir(home: string): string | null {\n if (!fs.existsSync(home)) return null;\n let fallback: string | null = null;\n for (const entry of fs.readdirSync(home)) {\n if (!entry.startsWith('merge-')) continue;\n const dir = path.join(home, entry);\n const marker = this.readMergeMarker(dir);\n if (marker === null) continue;\n if (!marker.validated) return dir;\n if (fallback === null) fallback = dir;\n }\n return fallback;\n }\n\n // Per-conflicted-file context dir holding A-forkpoint.txt / B-feature.txt / C-main.txt /\n // B-A.diff / C-A.diff (and the AI's merge-explanation.md). Shared so writer and reader agree on the\n // layout: the conflict file path with `/` → `__`, prefixed `updatemain-`.\n perFileContextDir(mergeDir: string, file: string): string {\n return path.join(mergeDir, `updatemain-${file.replace(/\\//g, '__')}`);\n }\n\n markerPath(mergeDir: string): string {\n return path.join(mergeDir, MERGE_IN_PROGRESS_FILE);\n }\n\n readMergeMarker(mergeDir: string): MergeMarker | null {\n const filePath = this.markerPath(mergeDir);\n if (!fs.existsSync(filePath)) return null;\n const raw = JSON.parse(fs.readFileSync(filePath, 'utf8')) as MergeMarker;\n return new MergeMarker(\n raw.currentBranch,\n raw.squashBranch,\n raw.backupBranch,\n raw.prNumber,\n raw.conflictedFiles ?? [],\n raw.forkPoint,\n raw.featureHead,\n raw.mainHead,\n raw.validated === true,\n );\n }\n\n writeMergeMarker(mergeDir: string, marker: MergeMarker): void {\n fs.mkdirSync(mergeDir, { recursive: true });\n fs.writeFileSync(this.markerPath(mergeDir), JSON.stringify(marker, null, 2) + '\\n');\n }\n\n clearMergeMarker(mergeDir: string): void {\n const filePath = this.markerPath(mergeDir);\n if (fs.existsSync(filePath)) fs.rmSync(filePath);\n }\n\n /**\n * Scoped conflict-marker scan: reads ONLY the given conflicted files (relative to repo root),\n * never the whole repo — stays O(conflicts) regardless of monorepo size.\n */\n scanConflictMarkers(repoRoot: string, files: string[]): MarkerScanResult {\n const filesWithMarkers: string[] = [];\n for (const file of files) {\n const abs = path.join(repoRoot, file);\n if (!fs.existsSync(abs)) continue;\n const content = fs.readFileSync(abs, 'utf8');\n if (CONFLICT_MARKER_RE.test(content)) filesWithMarkers.push(file);\n }\n return new MarkerScanResult(filesWithMarkers.length === 0, filesWithMarkers);\n }\n\n /**\n * Explanation scan: every conflicted file the AI resolved must have a non-empty\n * MERGE_EXPLANATION_FILE in its per-file context dir (next to the diffs), proving the AI\n * deliberately 3-point merged it and recording HOW. Returns files whose explanation is missing or\n * empty. Works for every conflicted file type — including comment-less files (JSON) and files\n * resolved by deletion (no working-tree file to inspect).\n */\n scanMergeExplanations(mergeDir: string, files: string[]): MarkerScanResult {\n const filesMissingExplanation: string[] = [];\n for (const file of files) {\n const explPath = path.join(this.perFileContextDir(mergeDir, file), MERGE_EXPLANATION_FILE);\n const present = fs.existsSync(explPath) && fs.readFileSync(explPath, 'utf8').trim() !== '';\n if (!present) filesMissingExplanation.push(file);\n }\n return new MarkerScanResult(filesMissingExplanation.length === 0, filesMissingExplanation);\n }\n}\n"]}
|
|
@@ -4,7 +4,7 @@ exports.OpenPrCheck = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const child_process_1 = require("child_process");
|
|
6
6
|
const rules_config_1 = require("@webpieces/rules-config");
|
|
7
|
-
const
|
|
7
|
+
const rules_config_2 = require("@webpieces/rules-config");
|
|
8
8
|
const inversify_1 = require("inversify");
|
|
9
9
|
const branch_naming_1 = require("./branch-naming");
|
|
10
10
|
const SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
|
@@ -35,7 +35,7 @@ let OpenPrCheck = class OpenPrCheck {
|
|
|
35
35
|
};
|
|
36
36
|
exports.OpenPrCheck = OpenPrCheck;
|
|
37
37
|
exports.OpenPrCheck = OpenPrCheck = tslib_1.__decorate([
|
|
38
|
-
(0,
|
|
38
|
+
(0, rules_config_2.provideSingleton)(),
|
|
39
39
|
(0, inversify_1.injectable)(),
|
|
40
40
|
tslib_1.__metadata("design:paramtypes", [branch_naming_1.BranchNaming])
|
|
41
41
|
], OpenPrCheck);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open-pr-check.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/open-pr-check.ts"],"names":[],"mappings":";;;;AAAA,iDAA0C;AAC1C,0DAAuD;AACvD,0DAA2D;AAC3D,yCAAuC;AACvC,mDAA+C;AAE/C,MAAM,GAAG,GAAG,0DAA0D,CAAC;AAEvE,+FAA+F;AAGxF,IAAM,WAAW,GAAjB,MAAM,WAAW;IACS;IAA7B,YAA6B,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAE3D,qGAAqG;IACrG,+FAA+F;IAC/F,gGAAgG;IAChG,wGAAwG;IACxG,eAAe,CAAC,QAAgB,EAAE,aAAqB;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAA,yBAAS,EACpB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAClG,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CACtC,CAAC;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;YAC5G,MAAM,IAAI,2BAAY,CAAC,CAAC,EACpB,IAAI,GAAG,GAAG,GAAG,oEAAoE,GAAG,GAAG,GAAG,IAAI;gBAC9F,8BAA8B,IAAI,MAAM,MAAM,MAAM;gBACpD,6FAA6F;gBAC7F,8FAA8F;gBAC9F,4FAA4F;gBAC5F,+EAA+E,CAClF,CAAC;QACN,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;CACJ,CAAA;AA1BY,kCAAW;sBAAX,WAAW;IAFvB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;6CAEkC,4BAAY;GAD9C,WAAW,CA0BvB","sourcesContent":["import { spawnSync } from 'child_process';\nimport { CliExitError } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/
|
|
1
|
+
{"version":3,"file":"open-pr-check.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/open-pr-check.ts"],"names":[],"mappings":";;;;AAAA,iDAA0C;AAC1C,0DAAuD;AACvD,0DAA2D;AAC3D,yCAAuC;AACvC,mDAA+C;AAE/C,MAAM,GAAG,GAAG,0DAA0D,CAAC;AAEvE,+FAA+F;AAGxF,IAAM,WAAW,GAAjB,MAAM,WAAW;IACS;IAA7B,YAA6B,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAE3D,qGAAqG;IACrG,+FAA+F;IAC/F,gGAAgG;IAChG,wGAAwG;IACxG,eAAe,CAAC,QAAgB,EAAE,aAAqB;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAA,yBAAS,EACpB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAClG,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CACtC,CAAC;QACF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC;YAC5G,MAAM,IAAI,2BAAY,CAAC,CAAC,EACpB,IAAI,GAAG,GAAG,GAAG,oEAAoE,GAAG,GAAG,GAAG,IAAI;gBAC9F,8BAA8B,IAAI,MAAM,MAAM,MAAM;gBACpD,6FAA6F;gBAC7F,8FAA8F;gBAC9F,4FAA4F;gBAC5F,+EAA+E,CAClF,CAAC;QACN,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;CACJ,CAAA;AA1BY,kCAAW;sBAAX,WAAW;IAFvB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;6CAEkC,4BAAY;GAD9C,WAAW,CA0BvB","sourcesContent":["import { spawnSync } from 'child_process';\nimport { CliExitError } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/rules-config';\nimport { injectable } from 'inversify';\nimport { BranchNaming } from './branch-naming';\n\nconst SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n';\n\n/** Hard gate: whether an OPEN PR already tracks a feature branch (by its stable base name). */\n@provideSingleton()\n@injectable()\nexport class OpenPrCheck {\n constructor(private readonly branchNaming: BranchNaming) {}\n\n // The open PR (if any) tracking a feature branch, looked up by its STABLE base name. Returns '' ONLY\n // when GitHub answered and there is genuinely no open PR. HARD GATE: FAILS FAST if `gh` cannot\n // answer — we must NOT degrade \"couldn't ask GitHub\" into \"no PR\" (a 3-point update makes a new\n // branch generation and the existing PR would be stranded on the OLD branch). Refuse rather than guess.\n openPrForBranch(repoRoot: string, currentBranch: string): string {\n const base = this.branchNaming.baseBranchName(currentBranch);\n const result = spawnSync(\n 'gh', ['pr', 'list', '--head', base, '--state', 'open', '--json', 'number', '--jq', '.[0].number'],\n { cwd: repoRoot, encoding: 'utf8' },\n );\n if (result.status !== 0) {\n const detail = (result.stderr ?? '').trim() || (result.error ? result.error.message : 'gh exited non-zero');\n throw new CliExitError(2,\n '\\n' + SEP + '❌ Could not ask GitHub whether an open PR exists for this branch\\n' + SEP + '\\n' +\n `gh failed for base branch \"${base}\": ${detail}\\n\\n` +\n 'This check must NOT be skipped: a 3-point update creates a NEW branch generation, so if a\\n' +\n 'PR already exists, wp-start-update would leave it pointing at the OLD branch. Fix gh first\\n' +\n '(install / `gh auth login` / restore network), then re-run — or, if a PR does exist, use\\n' +\n 'the PR flow: pnpm wp-start-upsert-pr → /wp-merge → pnpm wp-finish-upsert-pr\\n',\n );\n }\n return (result.stdout ?? '').trim();\n }\n}\n"]}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RunUpdate = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const rules_config_1 = require("@webpieces/rules-config");
|
|
6
|
-
const
|
|
6
|
+
const rules_config_2 = require("@webpieces/rules-config");
|
|
7
7
|
const inversify_1 = require("inversify");
|
|
8
8
|
const git_readAiBranchName_1 = require("./git-readAiBranchName");
|
|
9
9
|
const merge_state_1 = require("./merge-state");
|
|
@@ -59,7 +59,7 @@ let RunUpdate = class RunUpdate {
|
|
|
59
59
|
};
|
|
60
60
|
exports.RunUpdate = RunUpdate;
|
|
61
61
|
exports.RunUpdate = RunUpdate = tslib_1.__decorate([
|
|
62
|
-
(0,
|
|
62
|
+
(0, rules_config_2.provideSingleton)(),
|
|
63
63
|
(0, inversify_1.injectable)(),
|
|
64
64
|
tslib_1.__metadata("design:paramtypes", [git_readAiBranchName_1.AiBranchName,
|
|
65
65
|
merge_state_1.MergeState,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-update.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/run-update.ts"],"names":[],"mappings":";;;;AAAA,0DAA+F;AAC/F,0DAA2D;AAC3D,yCAAuC;AACvC,iEAAsD;AACtD,+CAA2C;AAC3C,+CAAyD;AACzD,2CAAuC;AAIvC,mGAAmG;AACnG,uGAAuG;AACvG,gGAAgG;AAChG,gGAAgG;AAGzF,IAAM,SAAS,GAAf,MAAM,SAAS;IAEG;IACA;IACA;IACA;IAJrB,YACqB,YAA0B,EAC1B,UAAsB,EACtB,UAAsB,EACtB,QAAkB;QAHlB,iBAAY,GAAZ,YAAY,CAAc;QAC1B,eAAU,GAAV,UAAU,CAAY;QACtB,eAAU,GAAV,UAAU,CAAY;QACtB,aAAQ,GAAR,QAAQ,CAAU;IACpC,CAAC;IAEJ,oGAAoG;IACpG,qGAAqG;IACrG,gFAAgF;IAChF,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,IAAkB,EAAE,aAAqB;QAC/E,IAAA,gCAAiB,EAAC,QAAQ,EAAE,IAAI,kCAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,kCAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACjD,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;QACtB,IAAA,gCAAiB,EAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACjC,OAAO,OAAO,CAAC;IACnB,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,QAAgB,EAAE,IAAkB,EAAE,aAAqB;QAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC;QAEvF,qFAAqF;QACrF,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC9D,IAAI,SAAS,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;YAC5D,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS;gBAAE,OAAO,mBAAmB,CAAC;YACzE,mFAAmF;YACnF,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CACxB,QAAQ,EAAE,IAAI,EAAE,SAAS,EACzB,IAAI,0BAAY,CAAC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,EACzG,IAAI,CACP,CAAC;YACF,OAAO,WAAW,CAAC;QACvB,CAAC;QAED,4FAA4F;QAC5F,uDAAuD;QACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACrF,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1D,OAAO,UAAU,CAAC;QACtB,CAAC;QACD,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAClF,OAAO,WAAW,CAAC;IACvB,CAAC;CACJ,CAAA;AA9CY,8BAAS;oBAAT,SAAS;IAFrB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;6CAG0B,mCAAY;QACd,wBAAU;QACV,wBAAU;QACZ,oBAAQ;GAL9B,SAAS,CA8CrB","sourcesContent":["import { MutationVerb, BranchMutationEvent, logBranchMutation } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/
|
|
1
|
+
{"version":3,"file":"run-update.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/run-update.ts"],"names":[],"mappings":";;;;AAAA,0DAA+F;AAC/F,0DAA2D;AAC3D,yCAAuC;AACvC,iEAAsD;AACtD,+CAA2C;AAC3C,+CAAyD;AACzD,2CAAuC;AAIvC,mGAAmG;AACnG,uGAAuG;AACvG,gGAAgG;AAChG,gGAAgG;AAGzF,IAAM,SAAS,GAAf,MAAM,SAAS;IAEG;IACA;IACA;IACA;IAJrB,YACqB,YAA0B,EAC1B,UAAsB,EACtB,UAAsB,EACtB,QAAkB;QAHlB,iBAAY,GAAZ,YAAY,CAAc;QAC1B,eAAU,GAAV,UAAU,CAAY;QACtB,eAAU,GAAV,UAAU,CAAY;QACtB,aAAQ,GAAR,QAAQ,CAAU;IACpC,CAAC;IAEJ,oGAAoG;IACpG,qGAAqG;IACrG,gFAAgF;IAChF,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,IAAkB,EAAE,aAAqB;QAC/E,IAAA,gCAAiB,EAAC,QAAQ,EAAE,IAAI,kCAAmB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,kCAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACjD,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;QACtB,IAAA,gCAAiB,EAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACjC,OAAO,OAAO,CAAC;IACnB,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,QAAgB,EAAE,IAAkB,EAAE,aAAqB;QAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC;QAEvF,qFAAqF;QACrF,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC9D,IAAI,SAAS,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;YAC5D,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS;gBAAE,OAAO,mBAAmB,CAAC;YACzE,mFAAmF;YACnF,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CACxB,QAAQ,EAAE,IAAI,EAAE,SAAS,EACzB,IAAI,0BAAY,CAAC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,QAAQ,CAAC,EACzG,IAAI,CACP,CAAC;YACF,OAAO,WAAW,CAAC;QACvB,CAAC;QAED,4FAA4F;QAC5F,uDAAuD;QACvD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACrF,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1D,OAAO,UAAU,CAAC;QACtB,CAAC;QACD,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAClF,OAAO,WAAW,CAAC;IACvB,CAAC;CACJ,CAAA;AA9CY,8BAAS;oBAAT,SAAS;IAFrB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;6CAG0B,mCAAY;QACd,wBAAU;QACV,wBAAU;QACZ,oBAAQ;GAL9B,SAAS,CA8CrB","sourcesContent":["import { MutationVerb, BranchMutationEvent, logBranchMutation } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/rules-config';\nimport { injectable } from 'inversify';\nimport { AiBranchName } from './git-readAiBranchName';\nimport { MergeState } from './merge-state';\nimport { MergeStart, MergeContext } from './merge-start';\nimport { MergeEnd } from './merge-end';\n\nexport type UpdateOutcome = 'finalized' | 'conflict' | 'unvalidatedResume';\n\n// The shared \"sync this feature branch from main\" engine — a thin composition of the two lifecycle\n// primitives (merge-START brings main in, merge-END finalizes). INTERNAL, not a bin: `wp-start-update`\n// (standalone) and `wp-start-upsert-pr` (PR flow) both call it. It NEVER creates a PR and NEVER\n// process.exits; it RETURNS an outcome so each caller prints the handoff that fits its context.\n@provideSingleton()\n@injectable()\nexport class RunUpdate {\n constructor(\n private readonly aiBranchName: AiBranchName,\n private readonly mergeState: MergeState,\n private readonly mergeStart: MergeStart,\n private readonly mergeEnd: MergeEnd,\n ) {}\n\n // `finishCommand` is the command the AI is told to run after resolving conflicts (standalone passes\n // `wp-finish-update`, PR flow passes `wp-finish-upsert-pr`). `verb` is the invoking bin, threaded so\n // every branch mutation is recorded in `.webpieces/hooks/branch-mutations.log`.\n async runUpdateFromMain(repoRoot: string, verb: MutationVerb, finishCommand: string): Promise<UpdateOutcome> {\n logBranchMutation(repoRoot, new BranchMutationEvent(verb, 'START'));\n const outcome = await this.runUpdate(repoRoot, verb, finishCommand);\n const end = new BranchMutationEvent(verb, 'END');\n end.outcome = outcome;\n logBranchMutation(repoRoot, end);\n return outcome;\n }\n\n private async runUpdate(repoRoot: string, verb: MutationVerb, finishCommand: string): Promise<UpdateOutcome> {\n const home = this.mergeState.mergeDirFor(repoRoot, this.aiBranchName.getFeatureName());\n\n // Resume path: an in-progress merge is the `merge-<n>/` run dir that holds a marker.\n const activeDir = this.mergeState.findActiveMergeRunDir(home);\n if (activeDir) {\n const existing = this.mergeState.readMergeMarker(activeDir);\n if (existing === null || !existing.validated) return 'unvalidatedResume';\n // Already validated → just finalize the branch swap (reads THIS run dir's marker).\n await this.mergeEnd.mergeEnd(\n repoRoot, verb, activeDir,\n new MergeContext(existing.currentBranch, existing.squashBranch, existing.backupBranch, existing.prNumber),\n null,\n );\n return 'finalized';\n }\n\n // Fresh update: mergeStart picks the slot number, creates its own `merge-<n>/` run dir, and\n // returns that path for merge-END to finalize against.\n const result = await this.mergeStart.mergeStart(repoRoot, verb, home, finishCommand);\n if (result.status === 'conflict' || result.context === null) {\n return 'conflict';\n }\n await this.mergeEnd.mergeEnd(repoRoot, verb, result.runDir, result.context, null);\n return 'finalized';\n }\n}\n"]}
|