@webpieces/rules-config 0.3.359 → 0.3.360

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/rules-config",
3
- "version": "0.3.359",
3
+ "version": "0.3.360",
4
4
  "description": "Shared webpieces.config.json loader. Single source of truth for validation rule configuration consumed by @webpieces/ai-hook-rules, @webpieces/code-rules, and @webpieces/nx-webpieces-rules.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -14,8 +14,8 @@
14
14
  "README.md"
15
15
  ],
16
16
  "dependencies": {
17
- "@webpieces/core-context": "0.3.359",
18
- "@webpieces/core-util": "0.3.359",
17
+ "@webpieces/core-context": "0.3.360",
18
+ "@webpieces/core-util": "0.3.360",
19
19
  "@inversifyjs/binding-decorators": "1.1.5",
20
20
  "inversify": "7.10.4",
21
21
  "reflect-metadata": "0.2.2",
package/src/index.d.ts CHANGED
@@ -29,7 +29,7 @@ export { METHOD_LIMIT_MODES, FILE_LIMIT_MODES, RETURN_TYPE_MODES, INLINE_TYPE_MO
29
29
  export type { MethodLimitMode, FileLimitMode, ReturnTypeMode, InlineTypeMode, ModifiedCodeMode, ProjectMode, PrismaValidateDtosMode, PrismaConverterMode, DirectApiResolverMode, ThrowCauseMode, OnOffMode, StructuralMode, ValidateTsMode, } from './rule-configs';
30
30
  export { GateDefinition, PrGateConfig, defaultGates, defaultPrGateConfig, buildPrGateConfig, } from './pr-gate-config';
31
31
  export { ReviewJson, ReviewJsonService, loadReviewJson, prDirFor, reviewJsonPath, reviewJsonSchemaHint, } from './review-json';
32
- export { MainSyncStatus, MainSyncLock, DEFAULT_HANG_TIMEOUT_MINUTES, mainSyncStatusPath, mainSyncLockPath, readMainSyncStatus, writeMainSyncStatus, readMainSyncLock, writeMainSyncLock, isLockStale, isRefreshInProgress, inProcessLock, finishedLock, computeMainSyncStatus, stampCleanMainSyncStatus, squashRecoverySteps, } from './main-sync-status';
32
+ export { MainSyncStatus, MainSyncLock, MainSyncStatusService, DEFAULT_HANG_TIMEOUT_MINUTES, mainSyncStatusPath, mainSyncLockPath, readMainSyncStatus, writeMainSyncStatus, readMainSyncLock, writeMainSyncLock, isLockStale, isRefreshInProgress, inProcessLock, finishedLock, computeMainSyncStatus, stampCleanMainSyncStatus, squashRecoverySteps, } from './main-sync-status';
33
33
  export type { MutationVerb, MutationPhase } from './branch-mutation-log';
34
34
  export { BranchMutationEvent, BranchMutationLog, branchMutationLogPath, logBranchMutation, } from './branch-mutation-log';
35
35
  export { CommandsConfig, buildCommandsConfig, DEFAULT_UPSERT_PR_COMMAND, DEFAULT_MERGE_COMPLETE_COMMAND, } from './commands-config';
package/src/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findNewMethodSignaturesInDiff = exports.getChangedLineNumbers = exports.getFileDiff = exports.getChangedFiles = exports.resolveBase = exports.detectBase = exports.getCurrentBranch = exports.shouldSkipRule = exports.FieldDef = exports.sectionForRule = exports.isHookGuard = exports.HOOK_GUARD_NAMES = exports.DEFAULT_MATCH_RULES = exports.renderMatchRuleMessage = exports.compileMatchRulePatterns = exports.isMatchRuleAllowedPath = exports.findMatchRuleViolations = exports.MatchRuleViolation = exports.MatchRuleConfig = exports.allRuleNames = exports.validateMatchRulesSection = exports.validateExcludePaths = exports.validateCommandsSection = exports.validateSectionPlacement = exports.validatePrGateSection = exports.validateWebpiecesConfig = exports.TemplateWriter = exports.writeTemplate = exports.writeTemplateIfMissing = exports.loadTemplate = exports.defaultRulesDir = exports.defaultRules = exports.isPathExcluded = exports.ExcludePaths = exports.RulesConfigDesign = exports.INSTRUCT_AI_DIR = exports.RepoRootFinder = exports.ConfigFile = exports.CONFIG_FILENAME = exports.findConfigFile = exports.ConfigLoader = exports.LoadedConfig = exports.loadAndValidate = exports.toError = exports.runMain = exports.CliExitError = exports.RuleFailError = exports.InformAiError = exports.ResolvedRuleConfig = exports.ResolvedConfig = void 0;
4
4
  exports.RETURN_TYPE_MODES = exports.FILE_LIMIT_MODES = exports.METHOD_LIMIT_MODES = exports.BaseRuleConfig = exports.ValidateTsInSrcConfig = exports.NoJsFilesConfig = exports.DiGraphConfig = exports.NxWiringConfig = exports.RuntimeArchitectureConfig = exports.NoFileImportCyclesConfig = exports.FeatureBranchGuardConfig = exports.RedirectHowToMergeMainConfig = exports.PrMergeGuardConfig = exports.MergeInProgressGuardConfig = exports.PrCreationOrPushGuardConfig = exports.BranchCreationGuardConfig = exports.RoleTagConfig = exports.FrameworkTagConfig = exports.InjectAnnotationNotNeededForConcreteClassConfig = exports.NoFunctionOutsideClassConfig = exports.NoProcessExitOutsideMainConfig = exports.NoSymbolDiTokensConfig = exports.AngularNoDirectApiInResolverConfig = exports.ThrowCauseRequiredConfig = exports.CatchErrorPatternConfig = exports.NoUnmanagedExceptionsConfig = exports.NoDestructureConfig = exports.PrismaConverterConfig = exports.PrismaValidateDtosConfig = exports.NoImplicitAnyConfig = exports.NoAnyUnknownConfig = exports.NoInlineTypeLiteralsConfig = exports.RequireReturnTypeConfig = exports.MaxFileLinesConfig = exports.MaxMethodLinesConfig = exports.WebpiecesRulesConfig = exports.MERGE_EXPLANATION_FILE = exports.MERGE_IN_PROGRESS_FILE = exports.PR_REVIEW_DIR = exports.MERGE_INFO_DIR = exports.WEBPIECES_TMP_DIR = exports.hasDisable = exports.RULE_NAMES = exports.WEBPIECES_DISABLE = exports.AbstractRule = exports.ChangedFilesOptions = exports.DiffRange = exports.DiffScope = exports.isNewOrModified = exports.hasChangesInRange = void 0;
5
- exports.DEFAULT_MERGE_COMPLETE_COMMAND = exports.DEFAULT_UPSERT_PR_COMMAND = exports.buildCommandsConfig = exports.CommandsConfig = exports.logBranchMutation = exports.branchMutationLogPath = exports.BranchMutationLog = exports.BranchMutationEvent = exports.squashRecoverySteps = exports.stampCleanMainSyncStatus = exports.computeMainSyncStatus = exports.finishedLock = exports.inProcessLock = exports.isRefreshInProgress = exports.isLockStale = exports.writeMainSyncLock = exports.readMainSyncLock = exports.writeMainSyncStatus = exports.readMainSyncStatus = exports.mainSyncLockPath = exports.mainSyncStatusPath = exports.DEFAULT_HANG_TIMEOUT_MINUTES = exports.MainSyncLock = exports.MainSyncStatus = exports.reviewJsonSchemaHint = exports.reviewJsonPath = exports.prDirFor = exports.loadReviewJson = exports.ReviewJsonService = exports.ReviewJson = exports.buildPrGateConfig = exports.defaultPrGateConfig = exports.defaultGates = exports.PrGateConfig = exports.GateDefinition = exports.VALIDATE_TS_MODES = exports.STRUCTURAL_MODES = exports.ON_OFF_MODES = exports.THROW_CAUSE_MODES = exports.DIRECT_API_RESOLVER_MODES = exports.PRISMA_CONVERTER_MODES = exports.PRISMA_DTOS_MODES = exports.PROJECT_MODES = exports.MODIFIED_CODE_MODES = exports.INLINE_TYPE_MODES = void 0;
5
+ exports.DEFAULT_MERGE_COMPLETE_COMMAND = exports.DEFAULT_UPSERT_PR_COMMAND = exports.buildCommandsConfig = exports.CommandsConfig = exports.logBranchMutation = exports.branchMutationLogPath = exports.BranchMutationLog = exports.BranchMutationEvent = exports.squashRecoverySteps = exports.stampCleanMainSyncStatus = exports.computeMainSyncStatus = exports.finishedLock = exports.inProcessLock = exports.isRefreshInProgress = exports.isLockStale = exports.writeMainSyncLock = exports.readMainSyncLock = exports.writeMainSyncStatus = exports.readMainSyncStatus = exports.mainSyncLockPath = exports.mainSyncStatusPath = exports.DEFAULT_HANG_TIMEOUT_MINUTES = exports.MainSyncStatusService = exports.MainSyncLock = exports.MainSyncStatus = exports.reviewJsonSchemaHint = exports.reviewJsonPath = exports.prDirFor = exports.loadReviewJson = exports.ReviewJsonService = exports.ReviewJson = exports.buildPrGateConfig = exports.defaultPrGateConfig = exports.defaultGates = exports.PrGateConfig = exports.GateDefinition = exports.VALIDATE_TS_MODES = exports.STRUCTURAL_MODES = exports.ON_OFF_MODES = exports.THROW_CAUSE_MODES = exports.DIRECT_API_RESOLVER_MODES = exports.PRISMA_CONVERTER_MODES = exports.PRISMA_DTOS_MODES = exports.PROJECT_MODES = exports.MODIFIED_CODE_MODES = exports.INLINE_TYPE_MODES = void 0;
6
6
  var types_1 = require("./types");
7
7
  Object.defineProperty(exports, "ResolvedConfig", { enumerable: true, get: function () { return types_1.ResolvedConfig; } });
8
8
  Object.defineProperty(exports, "ResolvedRuleConfig", { enumerable: true, get: function () { return types_1.ResolvedRuleConfig; } });
@@ -155,6 +155,7 @@ Object.defineProperty(exports, "reviewJsonSchemaHint", { enumerable: true, get:
155
155
  var main_sync_status_1 = require("./main-sync-status");
156
156
  Object.defineProperty(exports, "MainSyncStatus", { enumerable: true, get: function () { return main_sync_status_1.MainSyncStatus; } });
157
157
  Object.defineProperty(exports, "MainSyncLock", { enumerable: true, get: function () { return main_sync_status_1.MainSyncLock; } });
158
+ Object.defineProperty(exports, "MainSyncStatusService", { enumerable: true, get: function () { return main_sync_status_1.MainSyncStatusService; } });
158
159
  Object.defineProperty(exports, "DEFAULT_HANG_TIMEOUT_MINUTES", { enumerable: true, get: function () { return main_sync_status_1.DEFAULT_HANG_TIMEOUT_MINUTES; } });
159
160
  Object.defineProperty(exports, "mainSyncStatusPath", { enumerable: true, get: function () { return main_sync_status_1.mainSyncStatusPath; } });
160
161
  Object.defineProperty(exports, "mainSyncLockPath", { enumerable: true, get: function () { return main_sync_status_1.mainSyncLockPath; } });
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/index.ts"],"names":[],"mappings":";;;;;AAAA,iCAA0E;AAAjE,uGAAA,cAAc,OAAA;AAAE,2GAAA,kBAAkB,OAAA;AAC3C,qDAAkD;AAAzC,gHAAA,aAAa,OAAA;AACtB,qDAAkD;AAAzC,gHAAA,aAAa,OAAA;AACtB,mDAAgD;AAAvC,8GAAA,YAAY,OAAA;AACrB,uCAAqC;AAA5B,mGAAA,OAAO,OAAA;AAChB,uCAAqC;AAA5B,mGAAA,OAAO,OAAA;AAChB,6CAA4E;AAAnE,8GAAA,eAAe,OAAA;AAAE,2GAAA,YAAY,OAAA;AAAE,2GAAA,YAAY,OAAA;AACpD,6CAA4E;AAAnE,6GAAA,cAAc,OAAA;AAAE,8GAAA,eAAe,OAAA;AAAE,yGAAA,UAAU,OAAA;AACpD,yCAA8D;AAArD,2GAAA,cAAc,OAAA;AAAE,4GAAA,eAAe,OAAA;AACxC,6DAA0D;AAAjD,wHAAA,iBAAiB,OAAA;AAC1B,2DAAoD;AAA3C,kHAAA,YAAY,OAAA;AACrB,iDAAiD;AAAxC,+GAAA,cAAc,OAAA;AACvB,iDAAgE;AAAvD,6GAAA,YAAY,OAAA;AAAE,gHAAA,eAAe,OAAA;AACtC,iDAAsG;AAA7F,6GAAA,YAAY,OAAA;AAAE,uHAAA,sBAAsB,OAAA;AAAE,8GAAA,aAAa,OAAA;AAAE,+GAAA,cAAc,OAAA;AAC5E,qDAAqM;AAA5L,0HAAA,uBAAuB,OAAA;AAAE,wHAAA,qBAAqB,OAAA;AAAE,2HAAA,wBAAwB,OAAA;AAAE,0HAAA,uBAAuB,OAAA;AAAE,uHAAA,oBAAoB,OAAA;AAAE,4HAAA,yBAAyB,OAAA;AAAE,+GAAA,YAAY,OAAA;AACzK,2DAQ8B;AAP1B,qHAAA,eAAe,OAAA;AACf,wHAAA,kBAAkB,OAAA;AAClB,6HAAA,uBAAuB,OAAA;AACvB,4HAAA,sBAAsB,OAAA;AACtB,8HAAA,wBAAwB,OAAA;AACxB,4HAAA,sBAAsB,OAAA;AACtB,yHAAA,mBAAmB,OAAA;AAGvB,uCAA2E;AAAlE,4GAAA,gBAAgB,OAAA;AAAE,uGAAA,WAAW,OAAA;AAAE,0GAAA,cAAc,OAAA;AACtD,yCAAuC;AAA9B,qGAAA,QAAQ,OAAA;AAEjB,yCAA+D;AAAtD,2GAAA,cAAc,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAEzC,2CAYsB;AAXlB,wGAAA,UAAU,OAAA;AACV,yGAAA,WAAW,OAAA;AACX,6GAAA,eAAe,OAAA;AACf,yGAAA,WAAW,OAAA;AACX,mHAAA,qBAAqB,OAAA;AACrB,2HAAA,6BAA6B,OAAA;AAC7B,+GAAA,iBAAiB,OAAA;AACjB,6GAAA,eAAe,OAAA;AACf,uGAAA,SAAS,OAAA;AACT,uGAAA,SAAS,OAAA;AACT,iHAAA,mBAAmB,OAAA;AAEvB,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AACrB,yCASqB;AARjB,8GAAA,iBAAiB,OAAA;AACjB,uGAAA,UAAU,OAAA;AACV,uGAAA,UAAU,OAAA;AACV,8GAAA,iBAAiB,OAAA;AACjB,2GAAA,cAAc,OAAA;AACd,0GAAA,aAAa,OAAA;AACb,mHAAA,sBAAsB,OAAA;AACtB,mHAAA,sBAAsB,OAAA;AAE1B,+DAA8D;AAArD,4HAAA,oBAAoB,OAAA;AAC7B,+CAiCwB;AAhCpB,oHAAA,oBAAoB,OAAA;AACpB,kHAAA,kBAAkB,OAAA;AAClB,uHAAA,uBAAuB,OAAA;AACvB,0HAAA,0BAA0B,OAAA;AAC1B,kHAAA,kBAAkB,OAAA;AAClB,mHAAA,mBAAmB,OAAA;AACnB,wHAAA,wBAAwB,OAAA;AACxB,qHAAA,qBAAqB,OAAA;AACrB,mHAAA,mBAAmB,OAAA;AACnB,2HAAA,2BAA2B,OAAA;AAC3B,uHAAA,uBAAuB,OAAA;AACvB,wHAAA,wBAAwB,OAAA;AACxB,kIAAA,kCAAkC,OAAA;AAClC,sHAAA,sBAAsB,OAAA;AACtB,8HAAA,8BAA8B,OAAA;AAC9B,4HAAA,4BAA4B,OAAA;AAC5B,+IAAA,+CAA+C,OAAA;AAC/C,kHAAA,kBAAkB,OAAA;AAClB,6GAAA,aAAa,OAAA;AACb,yHAAA,yBAAyB,OAAA;AACzB,2HAAA,2BAA2B,OAAA;AAC3B,0HAAA,0BAA0B,OAAA;AAC1B,kHAAA,kBAAkB,OAAA;AAClB,4HAAA,4BAA4B,OAAA;AAC5B,wHAAA,wBAAwB,OAAA;AACxB,wHAAA,wBAAwB,OAAA;AACxB,yHAAA,yBAAyB,OAAA;AACzB,8GAAA,cAAc,OAAA;AACd,6GAAA,aAAa,OAAA;AACb,+GAAA,eAAe,OAAA;AACf,qHAAA,qBAAqB,OAAA;AACrB,8GAAA,cAAc,OAAA;AAElB,wFAAwF;AACxF,+CAcwB;AAbpB,kHAAA,kBAAkB,OAAA;AAClB,gHAAA,gBAAgB,OAAA;AAChB,iHAAA,iBAAiB,OAAA;AACjB,iHAAA,iBAAiB,OAAA;AACjB,mHAAA,mBAAmB,OAAA;AACnB,6GAAA,aAAa,OAAA;AACb,iHAAA,iBAAiB,OAAA;AACjB,sHAAA,sBAAsB,OAAA;AACtB,yHAAA,yBAAyB,OAAA;AACzB,iHAAA,iBAAiB,OAAA;AACjB,4GAAA,YAAY,OAAA;AACZ,gHAAA,gBAAgB,OAAA;AAChB,iHAAA,iBAAiB,OAAA;AAiBrB,mDAM0B;AALtB,gHAAA,cAAc,OAAA;AACd,8GAAA,YAAY,OAAA;AACZ,8GAAA,YAAY,OAAA;AACZ,qHAAA,mBAAmB,OAAA;AACnB,mHAAA,iBAAiB,OAAA;AAErB,6CAOuB;AANnB,yGAAA,UAAU,OAAA;AACV,gHAAA,iBAAiB,OAAA;AACjB,6GAAA,cAAc,OAAA;AACd,uGAAA,QAAQ,OAAA;AACR,6GAAA,cAAc,OAAA;AACd,mHAAA,oBAAoB,OAAA;AAExB,uDAiB4B;AAhBxB,kHAAA,cAAc,OAAA;AACd,gHAAA,YAAY,OAAA;AACZ,gIAAA,4BAA4B,OAAA;AAC5B,sHAAA,kBAAkB,OAAA;AAClB,oHAAA,gBAAgB,OAAA;AAChB,sHAAA,kBAAkB,OAAA;AAClB,uHAAA,mBAAmB,OAAA;AACnB,oHAAA,gBAAgB,OAAA;AAChB,qHAAA,iBAAiB,OAAA;AACjB,+GAAA,WAAW,OAAA;AACX,uHAAA,mBAAmB,OAAA;AACnB,iHAAA,aAAa,OAAA;AACb,gHAAA,YAAY,OAAA;AACZ,yHAAA,qBAAqB,OAAA;AACrB,4HAAA,wBAAwB,OAAA;AACxB,uHAAA,mBAAmB,OAAA;AAGvB,6DAK+B;AAJ3B,0HAAA,mBAAmB,OAAA;AACnB,wHAAA,iBAAiB,OAAA;AACjB,4HAAA,qBAAqB,OAAA;AACrB,wHAAA,iBAAiB,OAAA;AAErB,qDAK2B;AAJvB,iHAAA,cAAc,OAAA;AACd,sHAAA,mBAAmB,OAAA;AACnB,4HAAA,yBAAyB,OAAA;AACzB,iIAAA,8BAA8B,OAAA","sourcesContent":["export { ResolvedConfig, ResolvedRuleConfig, RuleOptions } from './types';\nexport { InformAiError } from './inform-ai-error';\nexport { RuleFailError } from './rule-fail-error';\nexport { CliExitError } from './cli-exit-error';\nexport { runMain } from './run-main';\nexport { toError } from './to-error';\nexport { loadAndValidate, LoadedConfig, ConfigLoader } from './load-config';\nexport { findConfigFile, CONFIG_FILENAME, ConfigFile } from './config-file';\nexport { RepoRootFinder, INSTRUCT_AI_DIR } from './repo-root';\nexport { RulesConfigDesign } from './rules-config-design';\nexport { ExcludePaths } from './exclude-hook-paths';\nexport { isPathExcluded } from './exclude-paths';\nexport { defaultRules, defaultRulesDir } from './default-rules';\nexport { loadTemplate, writeTemplateIfMissing, writeTemplate, TemplateWriter } from './load-template';\nexport { validateWebpiecesConfig, validatePrGateSection, validateSectionPlacement, validateCommandsSection, validateExcludePaths, validateMatchRulesSection, allRuleNames } from './validate-config';\nexport {\n MatchRuleConfig,\n MatchRuleViolation,\n findMatchRuleViolations,\n isMatchRuleAllowedPath,\n compileMatchRulePatterns,\n renderMatchRuleMessage,\n DEFAULT_MATCH_RULES,\n} from './match-rules-config';\nexport type { ConfigSection } from './sections';\nexport { HOOK_GUARD_NAMES, isHookGuard, sectionForRule } from './sections';\nexport { FieldDef } from './field-def';\nexport type { SchemaShape } from './field-def';\nexport { shouldSkipRule, getCurrentBranch } from './skip-rule';\nexport type { SkipRuleResult } from './skip-rule';\nexport {\n detectBase,\n resolveBase,\n getChangedFiles,\n getFileDiff,\n getChangedLineNumbers,\n findNewMethodSignaturesInDiff,\n hasChangesInRange,\n isNewOrModified,\n DiffScope,\n DiffRange,\n ChangedFilesOptions,\n} from './diff-scope';\nexport { AbstractRule } from './abstract-rule';\nexport {\n WEBPIECES_DISABLE,\n RULE_NAMES,\n hasDisable,\n WEBPIECES_TMP_DIR,\n MERGE_INFO_DIR,\n PR_REVIEW_DIR,\n MERGE_IN_PROGRESS_FILE,\n MERGE_EXPLANATION_FILE,\n} from './constants';\nexport { WebpiecesRulesConfig } from './WebpiecesRulesConfig';\nexport {\n MaxMethodLinesConfig,\n MaxFileLinesConfig,\n RequireReturnTypeConfig,\n NoInlineTypeLiteralsConfig,\n NoAnyUnknownConfig,\n NoImplicitAnyConfig,\n PrismaValidateDtosConfig,\n PrismaConverterConfig,\n NoDestructureConfig,\n NoUnmanagedExceptionsConfig,\n CatchErrorPatternConfig,\n ThrowCauseRequiredConfig,\n AngularNoDirectApiInResolverConfig,\n NoSymbolDiTokensConfig,\n NoProcessExitOutsideMainConfig,\n NoFunctionOutsideClassConfig,\n InjectAnnotationNotNeededForConcreteClassConfig,\n FrameworkTagConfig,\n RoleTagConfig,\n BranchCreationGuardConfig,\n PrCreationOrPushGuardConfig,\n MergeInProgressGuardConfig,\n PrMergeGuardConfig,\n RedirectHowToMergeMainConfig,\n FeatureBranchGuardConfig,\n NoFileImportCyclesConfig,\n RuntimeArchitectureConfig,\n NxWiringConfig,\n DiGraphConfig,\n NoJsFilesConfig,\n ValidateTsInSrcConfig,\n BaseRuleConfig,\n} from './rule-configs';\n// Mode unions + their value arrays — the single source of truth shared with code-rules.\nexport {\n METHOD_LIMIT_MODES,\n FILE_LIMIT_MODES,\n RETURN_TYPE_MODES,\n INLINE_TYPE_MODES,\n MODIFIED_CODE_MODES,\n PROJECT_MODES,\n PRISMA_DTOS_MODES,\n PRISMA_CONVERTER_MODES,\n DIRECT_API_RESOLVER_MODES,\n THROW_CAUSE_MODES,\n ON_OFF_MODES,\n STRUCTURAL_MODES,\n VALIDATE_TS_MODES,\n} from './rule-configs';\nexport type {\n MethodLimitMode,\n FileLimitMode,\n ReturnTypeMode,\n InlineTypeMode,\n ModifiedCodeMode,\n ProjectMode,\n PrismaValidateDtosMode,\n PrismaConverterMode,\n DirectApiResolverMode,\n ThrowCauseMode,\n OnOffMode,\n StructuralMode,\n ValidateTsMode,\n} from './rule-configs';\nexport {\n GateDefinition,\n PrGateConfig,\n defaultGates,\n defaultPrGateConfig,\n buildPrGateConfig,\n} from './pr-gate-config';\nexport {\n ReviewJson,\n ReviewJsonService,\n loadReviewJson,\n prDirFor,\n reviewJsonPath,\n reviewJsonSchemaHint,\n} from './review-json';\nexport {\n MainSyncStatus,\n MainSyncLock,\n DEFAULT_HANG_TIMEOUT_MINUTES,\n mainSyncStatusPath,\n mainSyncLockPath,\n readMainSyncStatus,\n writeMainSyncStatus,\n readMainSyncLock,\n writeMainSyncLock,\n isLockStale,\n isRefreshInProgress,\n inProcessLock,\n finishedLock,\n computeMainSyncStatus,\n stampCleanMainSyncStatus,\n squashRecoverySteps,\n} from './main-sync-status';\nexport type { MutationVerb, MutationPhase } from './branch-mutation-log';\nexport {\n BranchMutationEvent,\n BranchMutationLog,\n branchMutationLogPath,\n logBranchMutation,\n} from './branch-mutation-log';\nexport {\n CommandsConfig,\n buildCommandsConfig,\n DEFAULT_UPSERT_PR_COMMAND,\n DEFAULT_MERGE_COMPLETE_COMMAND,\n} from './commands-config';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { ResolvedConfig, ResolvedRuleConfig, RuleOptions } from './types';\nexport { InformAiError } from './inform-ai-error';\nexport { RuleFailError } from './rule-fail-error';\nexport { CliExitError } from './cli-exit-error';\nexport { runMain } from './run-main';\nexport { toError } from './to-error';\nexport { loadAndValidate, LoadedConfig, ConfigLoader } from './load-config';\nexport { findConfigFile, CONFIG_FILENAME, ConfigFile } from './config-file';\nexport { RepoRootFinder, INSTRUCT_AI_DIR } from './repo-root';\nexport { RulesConfigDesign } from './rules-config-design';\nexport { ExcludePaths } from './exclude-hook-paths';\nexport { isPathExcluded } from './exclude-paths';\nexport { defaultRules, defaultRulesDir } from './default-rules';\nexport { loadTemplate, writeTemplateIfMissing, writeTemplate, TemplateWriter } from './load-template';\nexport { validateWebpiecesConfig, validatePrGateSection, validateSectionPlacement, validateCommandsSection, validateExcludePaths, validateMatchRulesSection, allRuleNames } from './validate-config';\nexport {\n MatchRuleConfig,\n MatchRuleViolation,\n findMatchRuleViolations,\n isMatchRuleAllowedPath,\n compileMatchRulePatterns,\n renderMatchRuleMessage,\n DEFAULT_MATCH_RULES,\n} from './match-rules-config';\nexport type { ConfigSection } from './sections';\nexport { HOOK_GUARD_NAMES, isHookGuard, sectionForRule } from './sections';\nexport { FieldDef } from './field-def';\nexport type { SchemaShape } from './field-def';\nexport { shouldSkipRule, getCurrentBranch } from './skip-rule';\nexport type { SkipRuleResult } from './skip-rule';\nexport {\n detectBase,\n resolveBase,\n getChangedFiles,\n getFileDiff,\n getChangedLineNumbers,\n findNewMethodSignaturesInDiff,\n hasChangesInRange,\n isNewOrModified,\n DiffScope,\n DiffRange,\n ChangedFilesOptions,\n} from './diff-scope';\nexport { AbstractRule } from './abstract-rule';\nexport {\n WEBPIECES_DISABLE,\n RULE_NAMES,\n hasDisable,\n WEBPIECES_TMP_DIR,\n MERGE_INFO_DIR,\n PR_REVIEW_DIR,\n MERGE_IN_PROGRESS_FILE,\n MERGE_EXPLANATION_FILE,\n} from './constants';\nexport { WebpiecesRulesConfig } from './WebpiecesRulesConfig';\nexport {\n MaxMethodLinesConfig,\n MaxFileLinesConfig,\n RequireReturnTypeConfig,\n NoInlineTypeLiteralsConfig,\n NoAnyUnknownConfig,\n NoImplicitAnyConfig,\n PrismaValidateDtosConfig,\n PrismaConverterConfig,\n NoDestructureConfig,\n NoUnmanagedExceptionsConfig,\n CatchErrorPatternConfig,\n ThrowCauseRequiredConfig,\n AngularNoDirectApiInResolverConfig,\n NoSymbolDiTokensConfig,\n NoProcessExitOutsideMainConfig,\n NoFunctionOutsideClassConfig,\n InjectAnnotationNotNeededForConcreteClassConfig,\n FrameworkTagConfig,\n RoleTagConfig,\n BranchCreationGuardConfig,\n PrCreationOrPushGuardConfig,\n MergeInProgressGuardConfig,\n PrMergeGuardConfig,\n RedirectHowToMergeMainConfig,\n FeatureBranchGuardConfig,\n NoFileImportCyclesConfig,\n RuntimeArchitectureConfig,\n NxWiringConfig,\n DiGraphConfig,\n NoJsFilesConfig,\n ValidateTsInSrcConfig,\n BaseRuleConfig,\n} from './rule-configs';\n// Mode unions + their value arrays — the single source of truth shared with code-rules.\nexport {\n METHOD_LIMIT_MODES,\n FILE_LIMIT_MODES,\n RETURN_TYPE_MODES,\n INLINE_TYPE_MODES,\n MODIFIED_CODE_MODES,\n PROJECT_MODES,\n PRISMA_DTOS_MODES,\n PRISMA_CONVERTER_MODES,\n DIRECT_API_RESOLVER_MODES,\n THROW_CAUSE_MODES,\n ON_OFF_MODES,\n STRUCTURAL_MODES,\n VALIDATE_TS_MODES,\n} from './rule-configs';\nexport type {\n MethodLimitMode,\n FileLimitMode,\n ReturnTypeMode,\n InlineTypeMode,\n ModifiedCodeMode,\n ProjectMode,\n PrismaValidateDtosMode,\n PrismaConverterMode,\n DirectApiResolverMode,\n ThrowCauseMode,\n OnOffMode,\n StructuralMode,\n ValidateTsMode,\n} from './rule-configs';\nexport {\n GateDefinition,\n PrGateConfig,\n defaultGates,\n defaultPrGateConfig,\n buildPrGateConfig,\n} from './pr-gate-config';\nexport {\n ReviewJson,\n ReviewJsonService,\n loadReviewJson,\n prDirFor,\n reviewJsonPath,\n reviewJsonSchemaHint,\n} from './review-json';\nexport {\n MainSyncStatus,\n MainSyncLock,\n MainSyncStatusService,\n DEFAULT_HANG_TIMEOUT_MINUTES,\n mainSyncStatusPath,\n mainSyncLockPath,\n readMainSyncStatus,\n writeMainSyncStatus,\n readMainSyncLock,\n writeMainSyncLock,\n isLockStale,\n isRefreshInProgress,\n inProcessLock,\n finishedLock,\n computeMainSyncStatus,\n stampCleanMainSyncStatus,\n squashRecoverySteps,\n} from './main-sync-status';\nexport type { MutationVerb, MutationPhase } from './branch-mutation-log';\nexport {\n BranchMutationEvent,\n BranchMutationLog,\n branchMutationLogPath,\n logBranchMutation,\n} from './branch-mutation-log';\nexport {\n CommandsConfig,\n buildCommandsConfig,\n DEFAULT_UPSERT_PR_COMMAND,\n DEFAULT_MERGE_COMPLETE_COMMAND,\n} from './commands-config';\n"]}
@@ -19,6 +19,38 @@ export declare class MainSyncLock {
19
19
  pid: number;
20
20
  constructor(state: string, started: number, pid?: number);
21
21
  }
22
+ /**
23
+ * Reads/writes the main-sync cache + lock and computes the slow "is my branch healthy vs origin/main?"
24
+ * status. `@provideSingleton` so it's injectable and drawn in the rules-config DI design.
25
+ */
26
+ export declare class MainSyncStatusService {
27
+ mainSyncStatusPath(repoRoot: string): string;
28
+ mainSyncLockPath(repoRoot: string): string;
29
+ readMainSyncStatus(repoRoot: string): MainSyncStatus | null;
30
+ writeMainSyncStatus(repoRoot: string, status: MainSyncStatus): void;
31
+ readMainSyncLock(repoRoot: string): MainSyncLock | null;
32
+ writeMainSyncLock(repoRoot: string, lock: MainSyncLock): void;
33
+ isLockStale(lock: MainSyncLock, hangTimeoutMinutes: number, now?: number): boolean;
34
+ isRefreshInProgress(repoRoot: string, hangTimeoutMinutes: number, now?: number): boolean;
35
+ inProcessLock(now?: number, pid?: number): MainSyncLock;
36
+ finishedLock(started: number): MainSyncLock;
37
+ /**
38
+ * The SLOW path, run only inside the detached refresher. Computes every cached signal the
39
+ * feature-branch-guard needs. Never run on the hook's blocking path.
40
+ */
41
+ computeMainSyncStatus(repoRoot: string): MainSyncStatus;
42
+ squashRecoverySteps(currentBranch: string): string[];
43
+ stampCleanMainSyncStatus(repoRoot: string): void;
44
+ private ensureDir;
45
+ private isProcessAlive;
46
+ private capture;
47
+ private gitBranch;
48
+ private changedFiles;
49
+ private featureChangedFiles;
50
+ private detectMergedPr;
51
+ private detectOpenPr;
52
+ private benignStatus;
53
+ }
22
54
  export declare function mainSyncStatusPath(repoRoot: string): string;
23
55
  export declare function mainSyncLockPath(repoRoot: string): string;
24
56
  export declare function readMainSyncStatus(repoRoot: string): MainSyncStatus | null;
@@ -29,13 +61,6 @@ export declare function isLockStale(lock: MainSyncLock, hangTimeoutMinutes: numb
29
61
  export declare function isRefreshInProgress(repoRoot: string, hangTimeoutMinutes: number, now?: number): boolean;
30
62
  export declare function inProcessLock(now?: number, pid?: number): MainSyncLock;
31
63
  export declare function finishedLock(started: number): MainSyncLock;
32
- /**
33
- * The SLOW path, run only inside the detached refresher. Computes every cached signal the
34
- * feature-branch-guard needs: whether the branch is already merged (merged PR), whether a fork point
35
- * with origin/main still exists, and whether origin/main and this branch touched the SAME file since
36
- * the fork point (the deliberately-simple conflict heuristic — it over-blocks rather than miss a real
37
- * conflict). Never run on the hook's blocking path.
38
- */
39
64
  export declare function computeMainSyncStatus(repoRoot: string): MainSyncStatus;
40
65
  export declare function squashRecoverySteps(currentBranch: string): string[];
41
66
  export declare function stampCleanMainSyncStatus(repoRoot: string): void;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MainSyncLock = exports.MainSyncStatus = exports.DEFAULT_HANG_TIMEOUT_MINUTES = void 0;
3
+ exports.MainSyncStatusService = exports.MainSyncLock = exports.MainSyncStatus = exports.DEFAULT_HANG_TIMEOUT_MINUTES = void 0;
4
4
  exports.mainSyncStatusPath = mainSyncStatusPath;
5
5
  exports.mainSyncLockPath = mainSyncLockPath;
6
6
  exports.readMainSyncStatus = readMainSyncStatus;
@@ -18,24 +18,21 @@ const tslib_1 = require("tslib");
18
18
  const child_process_1 = require("child_process");
19
19
  const fs = tslib_1.__importStar(require("fs"));
20
20
  const path = tslib_1.__importStar(require("path"));
21
+ const core_context_1 = require("@webpieces/core-context");
22
+ const inversify_1 = require("inversify");
21
23
  const constants_1 = require("./constants");
22
24
  const to_error_1 = require("./to-error");
23
- // Shared "is my feature branch healthy relative to origin/main?" state. The SLOW signals (git fetch
24
- // + merge-base + same-file-overlap + a merged-PR lookup) are computed by the ai-hook-rules refresher
25
- // in a DETACHED background process so the PreToolUse hook never blocks on the network. The
26
- // feature-branch-guard then only READS this cached file (instant). pr-gate's merge flow also writes
27
- // it synchronously after a merge so the next edit is unblocked immediately. Lives here (the shared
28
- // dep of both packages) so neither depends on the other.
29
- // How long an `inprocess` refresher lock may sit before a new refresher assumes the prior run hung
30
- // and proceeds anyway. Overridable per-rule via FeatureBranchGuardConfig.hangTimeoutMinutes.
25
+ // Shared "is my feature branch healthy relative to origin/main?" state. The SLOW signals (git fetch +
26
+ // merge-base + same-file-overlap + a merged-PR lookup) are computed by the ai-hook-rules refresher in a
27
+ // DETACHED background process; the feature-branch-guard only READS this cached file. pr-gate's merge
28
+ // flow also writes it synchronously after a merge. Lives here (the shared dep of both).
29
+ // How long an `inprocess` refresher lock may sit before a new refresher assumes the prior run hung.
31
30
  exports.DEFAULT_HANG_TIMEOUT_MINUTES = 5;
32
31
  const MAIN_SYNC_STATUS_FILE = 'main-sync-status.json';
33
32
  const MAIN_SYNC_LOCK_FILE = 'main-sync.lock.json';
34
33
  const LOCK_STATE_INPROCESS = 'inprocess';
35
34
  const LOCK_STATE_FINISHED = 'finished';
36
- // Data-only (per CLAUDE.md, classes for data). `forkPoint` is null exactly when `hasForkPoint` is
37
- // false (no merge-base with origin/main). `branchAlreadyMerged` flags that this feature branch was
38
- // already merged into main (a merged PR exists) — the "you're working on a finished branch" case.
35
+ // Data-only (per CLAUDE.md, classes for data).
39
36
  class MainSyncStatus {
40
37
  branch;
41
38
  branchAlreadyMerged;
@@ -47,10 +44,7 @@ class MainSyncStatus {
47
44
  conflict;
48
45
  conflictFiles;
49
46
  timestamp;
50
- // An OPEN (not merged) PR tracking this branch, if any — '' = none or not-yet-known. Set by the
51
- // refresher (best-effort) and read by the feature-branch-guard so a mid-work conflict block can
52
- // steer straight to the PR flow instead of the update-only flow (which would just fail-fast when a
53
- // PR exists). Advisory only — the authoritative gate is wp-start-update's own fail-fast check.
47
+ // An OPEN (not merged) PR tracking this branch, if any — '' = none or not-yet-known. Advisory.
54
48
  // Kept OUT of the positional constructor (a defaulted field) so existing call sites don't churn.
55
49
  openPr = '';
56
50
  constructor(branch, branchAlreadyMerged, mergedPr, hasForkPoint, forkPoint, originMain, featureHead, conflict, conflictFiles, timestamp) {
@@ -67,10 +61,8 @@ class MainSyncStatus {
67
61
  }
68
62
  }
69
63
  exports.MainSyncStatus = MainSyncStatus;
70
- // Concurrency state machine for the detached refresher. `started` is epoch milliseconds. `pid` is
71
- // the refresher process's pid (0 = unknown, e.g. a lock written by an older version) used so a
72
- // refresher that was KILLED before writing its finished lock (SIGKILL skips the finally) doesn't
73
- // wedge `inprocess` for the whole hangTimeout: if its pid is gone, the lock is reclaimable now.
64
+ // Concurrency state machine for the detached refresher. `started` is epoch ms. `pid` is the refresher
65
+ // process's pid (0 = unknown) used so a KILLED refresher doesn't wedge `inprocess` for the timeout.
74
66
  class MainSyncLock {
75
67
  state;
76
68
  started;
@@ -82,237 +74,247 @@ class MainSyncLock {
82
74
  }
83
75
  }
84
76
  exports.MainSyncLock = MainSyncLock;
85
- function mainSyncStatusPath(repoRoot) {
86
- return path.join(repoRoot, constants_1.WEBPIECES_TMP_DIR, MAIN_SYNC_STATUS_FILE);
87
- }
88
- function mainSyncLockPath(repoRoot) {
89
- return path.join(repoRoot, constants_1.WEBPIECES_TMP_DIR, MAIN_SYNC_LOCK_FILE);
90
- }
91
- function ensureDir(filePath) {
92
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
93
- }
94
- // Pure read — any error (missing file, malformed JSON) returns null so the guard fails OPEN
95
- // (never block an edit because the cache is unreadable).
96
- function readMainSyncStatus(repoRoot) {
97
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
98
- try {
99
- const statusPath = mainSyncStatusPath(repoRoot);
100
- if (!fs.existsSync(statusPath))
77
+ /**
78
+ * Reads/writes the main-sync cache + lock and computes the slow "is my branch healthy vs origin/main?"
79
+ * status. `@provideSingleton` so it's injectable and drawn in the rules-config DI design.
80
+ */
81
+ let MainSyncStatusService = class MainSyncStatusService {
82
+ mainSyncStatusPath(repoRoot) {
83
+ return path.join(repoRoot, constants_1.WEBPIECES_TMP_DIR, MAIN_SYNC_STATUS_FILE);
84
+ }
85
+ mainSyncLockPath(repoRoot) {
86
+ return path.join(repoRoot, constants_1.WEBPIECES_TMP_DIR, MAIN_SYNC_LOCK_FILE);
87
+ }
88
+ // Pure read — any error (missing file, malformed JSON) returns null so the guard fails OPEN.
89
+ readMainSyncStatus(repoRoot) {
90
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
91
+ try {
92
+ const statusPath = this.mainSyncStatusPath(repoRoot);
93
+ if (!fs.existsSync(statusPath))
94
+ return null;
95
+ const raw = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
96
+ const status = new MainSyncStatus(raw.branch ?? '', raw.branchAlreadyMerged ?? false, raw.mergedPr ?? '', raw.hasForkPoint ?? true, raw.forkPoint ?? null, raw.originMain ?? '', raw.featureHead ?? '', raw.conflict ?? false, raw.conflictFiles ?? [], raw.timestamp ?? '');
97
+ status.openPr = raw.openPr ?? '';
98
+ return status;
99
+ }
100
+ catch (err) {
101
+ const error = (0, to_error_1.toError)(err);
102
+ void error;
101
103
  return null;
102
- const raw = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
103
- const status = new MainSyncStatus(raw.branch ?? '', raw.branchAlreadyMerged ?? false, raw.mergedPr ?? '', raw.hasForkPoint ?? true, raw.forkPoint ?? null, raw.originMain ?? '', raw.featureHead ?? '', raw.conflict ?? false, raw.conflictFiles ?? [], raw.timestamp ?? '');
104
- status.openPr = raw.openPr ?? '';
105
- return status;
104
+ }
106
105
  }
107
- catch (err) {
108
- const error = (0, to_error_1.toError)(err);
109
- void error;
110
- return null;
106
+ writeMainSyncStatus(repoRoot, status) {
107
+ const statusPath = this.mainSyncStatusPath(repoRoot);
108
+ this.ensureDir(statusPath);
109
+ fs.writeFileSync(statusPath, JSON.stringify(status, null, 2) + '\n');
111
110
  }
112
- }
113
- function writeMainSyncStatus(repoRoot, status) {
114
- const statusPath = mainSyncStatusPath(repoRoot);
115
- ensureDir(statusPath);
116
- fs.writeFileSync(statusPath, JSON.stringify(status, null, 2) + '\n');
117
- }
118
- function readMainSyncLock(repoRoot) {
119
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
120
- try {
121
- const lockPath = mainSyncLockPath(repoRoot);
122
- if (!fs.existsSync(lockPath))
111
+ readMainSyncLock(repoRoot) {
112
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
113
+ try {
114
+ const lockPath = this.mainSyncLockPath(repoRoot);
115
+ if (!fs.existsSync(lockPath))
116
+ return null;
117
+ const raw = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
118
+ return new MainSyncLock(raw.state ?? LOCK_STATE_FINISHED, raw.started ?? 0, raw.pid ?? 0);
119
+ }
120
+ catch (err) {
121
+ const error = (0, to_error_1.toError)(err);
122
+ void error;
123
123
  return null;
124
- const raw = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
125
- return new MainSyncLock(raw.state ?? LOCK_STATE_FINISHED, raw.started ?? 0, raw.pid ?? 0);
124
+ }
126
125
  }
127
- catch (err) {
128
- const error = (0, to_error_1.toError)(err);
129
- void error;
130
- return null;
126
+ writeMainSyncLock(repoRoot, lock) {
127
+ const lockPath = this.mainSyncLockPath(repoRoot);
128
+ this.ensureDir(lockPath);
129
+ fs.writeFileSync(lockPath, JSON.stringify(lock, null, 2) + '\n');
131
130
  }
132
- }
133
- function writeMainSyncLock(repoRoot, lock) {
134
- const lockPath = mainSyncLockPath(repoRoot);
135
- ensureDir(lockPath);
136
- fs.writeFileSync(lockPath, JSON.stringify(lock, null, 2) + '\n');
137
- }
138
- // A lock is stale (the prior refresher is assumed hung) once it has been `inprocess` longer than
139
- // hangTimeoutMinutes. `now` is injectable for tests; defaults to Date.now().
140
- function isLockStale(lock, hangTimeoutMinutes, now = Date.now()) {
141
- return now - lock.started > hangTimeoutMinutes * 60 * 1000;
142
- }
143
- // Liveness probe: is `pid` still a running process? `process.kill(pid, 0)` sends no signal, it only
144
- // tests existence — ESRCH means the process is gone, EPERM means it exists but isn't ours (alive).
145
- // pid <= 0 means "unknown" (an old lock with no pid) → assume alive and fall back to staleness only.
146
- function isProcessAlive(pid) {
147
- if (pid <= 0)
148
- return true;
149
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
150
- try {
151
- process.kill(pid, 0);
152
- return true;
131
+ // A lock is stale (prior refresher assumed hung) once `inprocess` longer than hangTimeoutMinutes.
132
+ isLockStale(lock, hangTimeoutMinutes, now = Date.now()) {
133
+ return now - lock.started > hangTimeoutMinutes * 60 * 1000;
153
134
  }
154
- catch (err) {
155
- const error = (0, to_error_1.toError)(err);
156
- // ESRCH = no such process (dead); anything else (e.g. EPERM = exists, not ours) = alive.
157
- return !error.message.includes('ESRCH');
135
+ // True when another refresher is actively running and we should NOT start a second one.
136
+ isRefreshInProgress(repoRoot, hangTimeoutMinutes, now = Date.now()) {
137
+ const lock = this.readMainSyncLock(repoRoot);
138
+ if (!lock)
139
+ return false;
140
+ if (lock.state !== LOCK_STATE_INPROCESS)
141
+ return false;
142
+ if (this.isLockStale(lock, hangTimeoutMinutes, now))
143
+ return false;
144
+ return this.isProcessAlive(lock.pid);
158
145
  }
159
- }
160
- // True when another refresher is actively running and we should NOT start a second one. A finished
161
- // lock, a missing lock, a stale (hung) inprocess lock, OR an inprocess lock whose refresher pid is
162
- // already dead (it was killed before writing its finished lock) all return false — so a killed
163
- // refresher never wedges refreshes for the full hangTimeout.
164
- function isRefreshInProgress(repoRoot, hangTimeoutMinutes, now = Date.now()) {
165
- const lock = readMainSyncLock(repoRoot);
166
- if (!lock)
167
- return false;
168
- if (lock.state !== LOCK_STATE_INPROCESS)
169
- return false;
170
- if (isLockStale(lock, hangTimeoutMinutes, now))
171
- return false;
172
- return isProcessAlive(lock.pid);
173
- }
174
- function inProcessLock(now = Date.now(), pid = process.pid) {
175
- return new MainSyncLock(LOCK_STATE_INPROCESS, now, pid);
176
- }
177
- function finishedLock(started) {
178
- return new MainSyncLock(LOCK_STATE_FINISHED, started, 0);
179
- }
180
- // Run a command capturing trimmed stdout; ok=false on spawn failure or non-zero exit.
181
- function capture(repoRoot, cmd, args) {
182
- const result = (0, child_process_1.spawnSync)(cmd, args, { cwd: repoRoot, encoding: 'utf8' });
183
- if (result.status !== 0 || typeof result.stdout !== 'string')
184
- return { ok: false, out: '' };
185
- return { ok: true, out: result.stdout.trim() };
186
- }
187
- // The actual checked-out branch in repoRoot — cwd-correct so the cache's `branch` label always
188
- // matches what the feature-branch-guard compares against (its own `git rev-parse` in the workspace).
189
- function gitBranch(repoRoot) {
190
- const result = capture(repoRoot, 'git', ['rev-parse', '--abbrev-ref', 'HEAD']);
191
- return result.ok ? result.out : '';
192
- }
193
- function changedFiles(repoRoot, base, head) {
194
- const result = capture(repoRoot, 'git', ['diff', '--name-only', base, head]);
195
- if (!result.ok || result.out === '')
196
- return [];
197
- return result.out.split('\n').map((line) => line.trim()).filter((line) => line.length > 0);
198
- }
199
- // Every file this feature branch has touched since the fork point — committed AND still in the
200
- // working tree (staged / unstaged / untracked). The committed-only `git diff forkPoint..HEAD` was
201
- // BLIND to uncommitted edits: for most of an editing session the files you are actively changing are
202
- // not yet in HEAD, so the overlap with main's changes was empty and conflict=false even when
203
- // origin/main had already moved onto those same files. Unioning in the working-tree changes makes the
204
- // conflict visible WHILE editing, so the guard can force an early merge instead of a painful late one.
205
- function featureChangedFiles(repoRoot, forkPoint) {
206
- const out = new Set();
207
- const add = (args) => {
208
- const r = capture(repoRoot, 'git', args);
209
- if (!r.ok || r.out === '')
210
- return;
211
- for (const line of r.out.split('\n')) {
212
- const f = line.trim();
213
- if (f.length > 0)
214
- out.add(f);
146
+ inProcessLock(now = Date.now(), pid = process.pid) {
147
+ return new MainSyncLock(LOCK_STATE_INPROCESS, now, pid);
148
+ }
149
+ finishedLock(started) {
150
+ return new MainSyncLock(LOCK_STATE_FINISHED, started, 0);
151
+ }
152
+ /**
153
+ * The SLOW path, run only inside the detached refresher. Computes every cached signal the
154
+ * feature-branch-guard needs. Never run on the hook's blocking path.
155
+ */
156
+ // webpieces-disable max-lines-new-methods -- one cohesive slow-path computation
157
+ computeMainSyncStatus(repoRoot) {
158
+ const branch = this.gitBranch(repoRoot);
159
+ const mergedPr = this.detectMergedPr(repoRoot, branch);
160
+ const openPr = this.detectOpenPr(repoRoot, branch);
161
+ // Best-effort network refresh; offline just means we evaluate against the last-fetched ref.
162
+ (0, child_process_1.spawnSync)('git', ['fetch', 'origin', 'main'], { cwd: repoRoot, stdio: 'ignore' });
163
+ const head = this.capture(repoRoot, 'git', ['rev-parse', 'HEAD']);
164
+ const originMain = this.capture(repoRoot, 'git', ['rev-parse', 'origin/main']);
165
+ const featureHead = head.ok ? head.out : '';
166
+ if (!head.ok || !originMain.ok) {
167
+ const status = this.benignStatus(branch, featureHead);
168
+ status.branchAlreadyMerged = mergedPr !== '';
169
+ status.mergedPr = mergedPr;
170
+ status.openPr = openPr;
171
+ return status;
215
172
  }
216
- };
217
- add(['diff', '--name-only', forkPoint, 'HEAD']); // committed since the fork point
218
- add(['diff', '--name-only', 'HEAD']); // unstaged working-tree edits
219
- add(['diff', '--name-only', '--cached', 'HEAD']); // staged edits
220
- add(['ls-files', '--others', '--exclude-standard']); // untracked new files (respects .gitignore)
221
- return [...out];
222
- }
223
- // Has this feature branch already been merged into main? Reliable signal: a MERGED PR exists for the
224
- // branch. Best-effort if gh is missing/unauthenticated we just report not-merged (false).
225
- function detectMergedPr(repoRoot, branch) {
226
- if (!branch || branch === 'main')
227
- return '';
228
- const result = capture(repoRoot, 'gh', ['pr', 'list', '--head', branch, '--state', 'merged', '--json', 'number', '--jq', '.[0].number']);
229
- return result.ok ? result.out : '';
230
- }
231
- // An OPEN PR tracking this branch, if any. Best-effort — this is ADVISORY (it only lets the guard's
232
- // conflict block steer to the PR flow early), so an unreachable gh degrades to '' here. The HARD gate
233
- // that must never guess is wp-start-update's own openPrForBranch, which fails fast instead.
234
- function detectOpenPr(repoRoot, branch) {
235
- if (!branch || branch === 'main')
236
- return '';
237
- const result = capture(repoRoot, 'gh', ['pr', 'list', '--head', branch, '--state', 'open', '--json', 'number', '--jq', '.[0].number']);
238
- return result.ok ? result.out : '';
239
- }
240
- // A benign status that never blocks — used when origin/main can't be resolved (no remote yet,
241
- // offline before first fetch). hasForkPoint=true + conflict=false so the guard allows the edit.
242
- function benignStatus(branch, featureHead) {
243
- return new MainSyncStatus(branch, false, '', true, null, '', featureHead, false, [], new Date().toISOString());
244
- }
245
- /**
246
- * The SLOW path, run only inside the detached refresher. Computes every cached signal the
247
- * feature-branch-guard needs: whether the branch is already merged (merged PR), whether a fork point
248
- * with origin/main still exists, and whether origin/main and this branch touched the SAME file since
249
- * the fork point (the deliberately-simple conflict heuristic — it over-blocks rather than miss a real
250
- * conflict). Never run on the hook's blocking path.
251
- */
252
- function computeMainSyncStatus(repoRoot) {
253
- const branch = gitBranch(repoRoot);
254
- const mergedPr = detectMergedPr(repoRoot, branch);
255
- // Advisory: lets the guard's conflict block steer to the PR flow early when a PR is already open.
256
- const openPr = detectOpenPr(repoRoot, branch);
257
- // Best-effort network refresh; offline just means we evaluate against the last-fetched ref.
258
- (0, child_process_1.spawnSync)('git', ['fetch', 'origin', 'main'], { cwd: repoRoot, stdio: 'ignore' });
259
- const head = capture(repoRoot, 'git', ['rev-parse', 'HEAD']);
260
- const originMain = capture(repoRoot, 'git', ['rev-parse', 'origin/main']);
261
- const featureHead = head.ok ? head.out : '';
262
- if (!head.ok || !originMain.ok) {
263
- const status = benignStatus(branch, featureHead);
264
- status.branchAlreadyMerged = mergedPr !== '';
265
- status.mergedPr = mergedPr;
173
+ const forkPoint = this.capture(repoRoot, 'git', ['merge-base', 'origin/main', 'HEAD']);
174
+ if (!forkPoint.ok || forkPoint.out === '') {
175
+ const noFork = new MainSyncStatus(branch, mergedPr !== '', mergedPr, false, null, originMain.out, featureHead, false, [], new Date().toISOString());
176
+ noFork.openPr = openPr;
177
+ return noFork;
178
+ }
179
+ const featureFiles = new Set(this.featureChangedFiles(repoRoot, forkPoint.out));
180
+ const mainFiles = this.changedFiles(repoRoot, forkPoint.out, 'origin/main');
181
+ const conflictFiles = mainFiles.filter((file) => featureFiles.has(file));
182
+ const status = new MainSyncStatus(branch, mergedPr !== '', mergedPr, true, forkPoint.out, originMain.out, featureHead, conflictFiles.length > 0, conflictFiles, new Date().toISOString());
266
183
  status.openPr = openPr;
267
184
  return status;
268
185
  }
269
- const forkPoint = capture(repoRoot, 'git', ['merge-base', 'origin/main', 'HEAD']);
270
- if (!forkPoint.ok || forkPoint.out === '') {
271
- // No common ancestor — main was merged into the branch. Force the human to squash.
272
- const noFork = new MainSyncStatus(branch, mergedPr !== '', mergedPr, false, null, originMain.out, featureHead, false, [], new Date().toISOString());
273
- noFork.openPr = openPr;
274
- return noFork;
186
+ // The recovery steps when there is no fork point with origin/main (a bad merge of main into branch).
187
+ squashRecoverySteps(currentBranch) {
188
+ return [
189
+ '1. Fetch latest main: git fetch origin main',
190
+ `2. New branch off origin/main: git checkout -b ${currentBranch}-v2 origin/main`,
191
+ `3. Squash-merge old branch: git merge --squash ${currentBranch}`,
192
+ `4. Commit the squash: git add -A && git commit -m "Squashed from ${currentBranch}"`,
193
+ '5. If a PR exists: open a NEW PR for the -v2 branch and close the old one.',
194
+ ];
275
195
  }
276
- const featureFiles = new Set(featureChangedFiles(repoRoot, forkPoint.out));
277
- const mainFiles = changedFiles(repoRoot, forkPoint.out, 'origin/main');
278
- const conflictFiles = mainFiles.filter((file) => featureFiles.has(file));
279
- const status = new MainSyncStatus(branch, mergedPr !== '', mergedPr, true, forkPoint.out, originMain.out, featureHead, conflictFiles.length > 0, conflictFiles, new Date().toISOString());
280
- status.openPr = openPr;
281
- return status;
282
- }
283
- // The recovery steps when there is no fork point with origin/main (someone merged main into the
284
- // branch, so a clean squash-merge is impossible). Shared so the feature-branch-guard and pr-gate's
285
- // findForkPoint check present the SAME instructions. The human must redo the work on a fresh branch —
286
- // deliberately painful so the bad merge gets noticed and reported.
287
- function squashRecoverySteps(currentBranch) {
288
- // Branch off origin/main directly (never `git checkout main`) so these steps are correct on the
289
- // primary repo AND inside a linked worktree, where main is checked out elsewhere and cannot be
290
- // checked out again.
291
- return [
292
- '1. Fetch latest main: git fetch origin main',
293
- `2. New branch off origin/main: git checkout -b ${currentBranch}-v2 origin/main`,
294
- `3. Squash-merge old branch: git merge --squash ${currentBranch}`,
295
- `4. Commit the squash: git add -A && git commit -m "Squashed from ${currentBranch}"`,
296
- '5. If a PR exists: open a NEW PR for the -v2 branch and close the old one.',
297
- ];
298
- }
299
- // Synchronously stamp a clean "up to date with main" status — call right after a successful merge
300
- // (the branch now contains origin/main). Unblocks the next edit immediately without waiting for the
301
- // async refresher. Best-effort: a git failure is swallowed (the refresher will recompute later).
302
- function stampCleanMainSyncStatus(repoRoot) {
303
- // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
304
- try {
305
- const branch = gitBranch(repoRoot);
306
- const originMain = capture(repoRoot, 'git', ['rev-parse', 'origin/main']);
307
- const featureHead = capture(repoRoot, 'git', ['rev-parse', 'HEAD']);
308
- if (!originMain.ok || !featureHead.ok)
309
- return;
310
- const status = new MainSyncStatus(branch, false, '', true, originMain.out, originMain.out, featureHead.out, false, [], new Date().toISOString());
311
- writeMainSyncStatus(repoRoot, status);
196
+ // Synchronously stamp a clean "up to date with main" status — call right after a successful merge.
197
+ stampCleanMainSyncStatus(repoRoot) {
198
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
199
+ try {
200
+ const branch = this.gitBranch(repoRoot);
201
+ const originMain = this.capture(repoRoot, 'git', ['rev-parse', 'origin/main']);
202
+ const featureHead = this.capture(repoRoot, 'git', ['rev-parse', 'HEAD']);
203
+ if (!originMain.ok || !featureHead.ok)
204
+ return;
205
+ const status = new MainSyncStatus(branch, false, '', true, originMain.out, originMain.out, featureHead.out, false, [], new Date().toISOString());
206
+ this.writeMainSyncStatus(repoRoot, status);
207
+ }
208
+ catch (err) {
209
+ const error = (0, to_error_1.toError)(err);
210
+ void error;
211
+ }
312
212
  }
313
- catch (err) {
314
- const error = (0, to_error_1.toError)(err);
315
- void error;
213
+ ensureDir(filePath) {
214
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
316
215
  }
317
- }
216
+ // Liveness probe: is `pid` still a running process? pid <= 0 (unknown) → assume alive.
217
+ isProcessAlive(pid) {
218
+ if (pid <= 0)
219
+ return true;
220
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions
221
+ try {
222
+ process.kill(pid, 0);
223
+ return true;
224
+ }
225
+ catch (err) {
226
+ const error = (0, to_error_1.toError)(err);
227
+ return !error.message.includes('ESRCH');
228
+ }
229
+ }
230
+ // Run a command capturing trimmed stdout; ok=false on spawn failure or non-zero exit.
231
+ capture(repoRoot, cmd, args) {
232
+ const result = (0, child_process_1.spawnSync)(cmd, args, { cwd: repoRoot, encoding: 'utf8' });
233
+ if (result.status !== 0 || typeof result.stdout !== 'string')
234
+ return { ok: false, out: '' };
235
+ return { ok: true, out: result.stdout.trim() };
236
+ }
237
+ // The actual checked-out branch in repoRoot — cwd-correct so the cache's `branch` label matches.
238
+ gitBranch(repoRoot) {
239
+ const result = this.capture(repoRoot, 'git', ['rev-parse', '--abbrev-ref', 'HEAD']);
240
+ return result.ok ? result.out : '';
241
+ }
242
+ changedFiles(repoRoot, base, head) {
243
+ const result = this.capture(repoRoot, 'git', ['diff', '--name-only', base, head]);
244
+ if (!result.ok || result.out === '')
245
+ return [];
246
+ return result.out.split('\n').map((line) => line.trim()).filter((line) => line.length > 0);
247
+ }
248
+ // Every file this feature branch has touched since the fork point — committed AND still in the
249
+ // working tree (staged / unstaged / untracked), so a conflict is visible WHILE editing.
250
+ featureChangedFiles(repoRoot, forkPoint) {
251
+ const out = new Set();
252
+ const add = (args) => {
253
+ const r = this.capture(repoRoot, 'git', args);
254
+ if (!r.ok || r.out === '')
255
+ return;
256
+ for (const line of r.out.split('\n')) {
257
+ const f = line.trim();
258
+ if (f.length > 0)
259
+ out.add(f);
260
+ }
261
+ };
262
+ add(['diff', '--name-only', forkPoint, 'HEAD']); // committed since the fork point
263
+ add(['diff', '--name-only', 'HEAD']); // unstaged working-tree edits
264
+ add(['diff', '--name-only', '--cached', 'HEAD']); // staged edits
265
+ add(['ls-files', '--others', '--exclude-standard']); // untracked new files (respects .gitignore)
266
+ return [...out];
267
+ }
268
+ // Has this feature branch already been merged into main? Reliable signal: a MERGED PR exists.
269
+ detectMergedPr(repoRoot, branch) {
270
+ if (!branch || branch === 'main')
271
+ return '';
272
+ const result = this.capture(repoRoot, 'gh', ['pr', 'list', '--head', branch, '--state', 'merged', '--json', 'number', '--jq', '.[0].number']);
273
+ return result.ok ? result.out : '';
274
+ }
275
+ // An OPEN PR tracking this branch, if any. Best-effort/advisory.
276
+ detectOpenPr(repoRoot, branch) {
277
+ if (!branch || branch === 'main')
278
+ return '';
279
+ const result = this.capture(repoRoot, 'gh', ['pr', 'list', '--head', branch, '--state', 'open', '--json', 'number', '--jq', '.[0].number']);
280
+ return result.ok ? result.out : '';
281
+ }
282
+ // A benign status that never blocks — used when origin/main can't be resolved.
283
+ benignStatus(branch, featureHead) {
284
+ return new MainSyncStatus(branch, false, '', true, null, '', featureHead, false, [], new Date().toISOString());
285
+ }
286
+ };
287
+ exports.MainSyncStatusService = MainSyncStatusService;
288
+ exports.MainSyncStatusService = MainSyncStatusService = tslib_1.__decorate([
289
+ (0, core_context_1.provideSingleton)(),
290
+ (0, inversify_1.injectable)()
291
+ ], MainSyncStatusService);
292
+ // Temporary migration delegators to MainSyncStatusService — removed once consumers inject it.
293
+ const mainSyncSvc = new MainSyncStatusService();
294
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
295
+ function mainSyncStatusPath(repoRoot) { return mainSyncSvc.mainSyncStatusPath(repoRoot); }
296
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
297
+ function mainSyncLockPath(repoRoot) { return mainSyncSvc.mainSyncLockPath(repoRoot); }
298
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
299
+ function readMainSyncStatus(repoRoot) { return mainSyncSvc.readMainSyncStatus(repoRoot); }
300
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
301
+ function writeMainSyncStatus(repoRoot, status) { mainSyncSvc.writeMainSyncStatus(repoRoot, status); }
302
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
303
+ function readMainSyncLock(repoRoot) { return mainSyncSvc.readMainSyncLock(repoRoot); }
304
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
305
+ function writeMainSyncLock(repoRoot, lock) { mainSyncSvc.writeMainSyncLock(repoRoot, lock); }
306
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
307
+ function isLockStale(lock, hangTimeoutMinutes, now = Date.now()) { return mainSyncSvc.isLockStale(lock, hangTimeoutMinutes, now); }
308
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
309
+ function isRefreshInProgress(repoRoot, hangTimeoutMinutes, now = Date.now()) { return mainSyncSvc.isRefreshInProgress(repoRoot, hangTimeoutMinutes, now); }
310
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
311
+ function inProcessLock(now = Date.now(), pid = process.pid) { return mainSyncSvc.inProcessLock(now, pid); }
312
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
313
+ function finishedLock(started) { return mainSyncSvc.finishedLock(started); }
314
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
315
+ function computeMainSyncStatus(repoRoot) { return mainSyncSvc.computeMainSyncStatus(repoRoot); }
316
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
317
+ function squashRecoverySteps(currentBranch) { return mainSyncSvc.squashRecoverySteps(currentBranch); }
318
+ // webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it
319
+ function stampCleanMainSyncStatus(repoRoot) { mainSyncSvc.stampCleanMainSyncStatus(repoRoot); }
318
320
  //# sourceMappingURL=main-sync-status.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"main-sync-status.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/main-sync-status.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { WEBPIECES_TMP_DIR } from './constants';\nimport { toError } from './to-error';\n\n// Shared \"is my feature branch healthy relative to origin/main?\" state. The SLOW signals (git fetch\n// + merge-base + same-file-overlap + a merged-PR lookup) are computed by the ai-hook-rules refresher\n// in a DETACHED background process so the PreToolUse hook never blocks on the network. The\n// feature-branch-guard then only READS this cached file (instant). pr-gate's merge flow also writes\n// it synchronously after a merge so the next edit is unblocked immediately. Lives here (the shared\n// dep of both packages) so neither depends on the other.\n\n// How long an `inprocess` refresher lock may sit before a new refresher assumes the prior run hung\n// and proceeds anyway. Overridable per-rule via FeatureBranchGuardConfig.hangTimeoutMinutes.\nexport const DEFAULT_HANG_TIMEOUT_MINUTES = 5;\n\nconst MAIN_SYNC_STATUS_FILE = 'main-sync-status.json';\nconst MAIN_SYNC_LOCK_FILE = 'main-sync.lock.json';\n\nconst LOCK_STATE_INPROCESS = 'inprocess';\nconst LOCK_STATE_FINISHED = 'finished';\n\n// Data-only (per CLAUDE.md, classes for data). `forkPoint` is null exactly when `hasForkPoint` is\n// false (no merge-base with origin/main). `branchAlreadyMerged` flags that this feature branch was\n// already merged into main (a merged PR exists) — the \"you're working on a finished branch\" case.\nexport class MainSyncStatus {\n branch: string;\n branchAlreadyMerged: boolean;\n mergedPr: string;\n hasForkPoint: boolean;\n forkPoint: string | null;\n originMain: string;\n featureHead: string;\n conflict: boolean;\n conflictFiles: string[];\n timestamp: string;\n // An OPEN (not merged) PR tracking this branch, if any — '' = none or not-yet-known. Set by the\n // refresher (best-effort) and read by the feature-branch-guard so a mid-work conflict block can\n // steer straight to the PR flow instead of the update-only flow (which would just fail-fast when a\n // PR exists). Advisory only — the authoritative gate is wp-start-update's own fail-fast check.\n // Kept OUT of the positional constructor (a defaulted field) so existing call sites don't churn.\n openPr: string = '';\n\n constructor(\n branch: string,\n branchAlreadyMerged: boolean,\n mergedPr: string,\n hasForkPoint: boolean,\n forkPoint: string | null,\n originMain: string,\n featureHead: string,\n conflict: boolean,\n conflictFiles: string[],\n timestamp: string,\n ) {\n this.branch = branch;\n this.branchAlreadyMerged = branchAlreadyMerged;\n this.mergedPr = mergedPr;\n this.hasForkPoint = hasForkPoint;\n this.forkPoint = forkPoint;\n this.originMain = originMain;\n this.featureHead = featureHead;\n this.conflict = conflict;\n this.conflictFiles = conflictFiles;\n this.timestamp = timestamp;\n }\n}\n\n// Concurrency state machine for the detached refresher. `started` is epoch milliseconds. `pid` is\n// the refresher process's pid (0 = unknown, e.g. a lock written by an older version) — used so a\n// refresher that was KILLED before writing its finished lock (SIGKILL skips the finally) doesn't\n// wedge `inprocess` for the whole hangTimeout: if its pid is gone, the lock is reclaimable now.\nexport class MainSyncLock {\n state: string;\n started: number;\n pid: number;\n\n constructor(state: string, started: number, pid: number = 0) {\n this.state = state;\n this.started = started;\n this.pid = pid;\n }\n}\n\n// Raw JSON shapes for the cast at the parse boundary —\n// keeps `any`/`unknown` out of the cast so no-any-unknown stays clean.\ninterface RawStatus {\n branch?: string;\n branchAlreadyMerged?: boolean;\n mergedPr?: string;\n hasForkPoint?: boolean;\n forkPoint?: string | null;\n originMain?: string;\n featureHead?: string;\n conflict?: boolean;\n conflictFiles?: string[];\n timestamp?: string;\n openPr?: string;\n}\n\ninterface RawLock {\n state?: string;\n started?: number;\n pid?: number;\n}\n\n// Result of a captured git/gh invocation: ok=false on spawn failure or non-zero exit.\ninterface CmdCapture {\n ok: boolean;\n out: string;\n}\n\nexport function mainSyncStatusPath(repoRoot: string): string {\n return path.join(repoRoot, WEBPIECES_TMP_DIR, MAIN_SYNC_STATUS_FILE);\n}\n\nexport function mainSyncLockPath(repoRoot: string): string {\n return path.join(repoRoot, WEBPIECES_TMP_DIR, MAIN_SYNC_LOCK_FILE);\n}\n\nfunction ensureDir(filePath: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n}\n\n// Pure read — any error (missing file, malformed JSON) returns null so the guard fails OPEN\n// (never block an edit because the cache is unreadable).\nexport function readMainSyncStatus(repoRoot: string): MainSyncStatus | null {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const statusPath = mainSyncStatusPath(repoRoot);\n if (!fs.existsSync(statusPath)) return null;\n const raw = JSON.parse(fs.readFileSync(statusPath, 'utf8')) as RawStatus;\n const status = new MainSyncStatus(\n raw.branch ?? '',\n raw.branchAlreadyMerged ?? false,\n raw.mergedPr ?? '',\n raw.hasForkPoint ?? true,\n raw.forkPoint ?? null,\n raw.originMain ?? '',\n raw.featureHead ?? '',\n raw.conflict ?? false,\n raw.conflictFiles ?? [],\n raw.timestamp ?? '',\n );\n status.openPr = raw.openPr ?? '';\n return status;\n } catch (err: unknown) {\n const error = toError(err);\n void error;\n return null;\n }\n}\n\nexport function writeMainSyncStatus(repoRoot: string, status: MainSyncStatus): void {\n const statusPath = mainSyncStatusPath(repoRoot);\n ensureDir(statusPath);\n fs.writeFileSync(statusPath, JSON.stringify(status, null, 2) + '\\n');\n}\n\nexport function readMainSyncLock(repoRoot: string): MainSyncLock | null {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const lockPath = mainSyncLockPath(repoRoot);\n if (!fs.existsSync(lockPath)) return null;\n const raw = JSON.parse(fs.readFileSync(lockPath, 'utf8')) as RawLock;\n return new MainSyncLock(raw.state ?? LOCK_STATE_FINISHED, raw.started ?? 0, raw.pid ?? 0);\n } catch (err: unknown) {\n const error = toError(err);\n void error;\n return null;\n }\n}\n\nexport function writeMainSyncLock(repoRoot: string, lock: MainSyncLock): void {\n const lockPath = mainSyncLockPath(repoRoot);\n ensureDir(lockPath);\n fs.writeFileSync(lockPath, JSON.stringify(lock, null, 2) + '\\n');\n}\n\n// A lock is stale (the prior refresher is assumed hung) once it has been `inprocess` longer than\n// hangTimeoutMinutes. `now` is injectable for tests; defaults to Date.now().\nexport function isLockStale(lock: MainSyncLock, hangTimeoutMinutes: number, now: number = Date.now()): boolean {\n return now - lock.started > hangTimeoutMinutes * 60 * 1000;\n}\n\n// Liveness probe: is `pid` still a running process? `process.kill(pid, 0)` sends no signal, it only\n// tests existence — ESRCH means the process is gone, EPERM means it exists but isn't ours (alive).\n// pid <= 0 means \"unknown\" (an old lock with no pid) → assume alive and fall back to staleness only.\nfunction isProcessAlive(pid: number): boolean {\n if (pid <= 0) return true;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n process.kill(pid, 0);\n return true;\n } catch (err: unknown) {\n const error = toError(err);\n // ESRCH = no such process (dead); anything else (e.g. EPERM = exists, not ours) = alive.\n return !error.message.includes('ESRCH');\n }\n}\n\n// True when another refresher is actively running and we should NOT start a second one. A finished\n// lock, a missing lock, a stale (hung) inprocess lock, OR an inprocess lock whose refresher pid is\n// already dead (it was killed before writing its finished lock) all return false — so a killed\n// refresher never wedges refreshes for the full hangTimeout.\nexport function isRefreshInProgress(repoRoot: string, hangTimeoutMinutes: number, now: number = Date.now()): boolean {\n const lock = readMainSyncLock(repoRoot);\n if (!lock) return false;\n if (lock.state !== LOCK_STATE_INPROCESS) return false;\n if (isLockStale(lock, hangTimeoutMinutes, now)) return false;\n return isProcessAlive(lock.pid);\n}\n\nexport function inProcessLock(now: number = Date.now(), pid: number = process.pid): MainSyncLock {\n return new MainSyncLock(LOCK_STATE_INPROCESS, now, pid);\n}\n\nexport function finishedLock(started: number): MainSyncLock {\n return new MainSyncLock(LOCK_STATE_FINISHED, started, 0);\n}\n\n// Run a command capturing trimmed stdout; ok=false on spawn failure or non-zero exit.\nfunction capture(repoRoot: string, cmd: string, args: string[]): CmdCapture {\n const result = spawnSync(cmd, args, { cwd: repoRoot, encoding: 'utf8' });\n if (result.status !== 0 || typeof result.stdout !== 'string') return { ok: false, out: '' };\n return { ok: true, out: result.stdout.trim() };\n}\n\n// The actual checked-out branch in repoRoot — cwd-correct so the cache's `branch` label always\n// matches what the feature-branch-guard compares against (its own `git rev-parse` in the workspace).\nfunction gitBranch(repoRoot: string): string {\n const result = capture(repoRoot, 'git', ['rev-parse', '--abbrev-ref', 'HEAD']);\n return result.ok ? result.out : '';\n}\n\nfunction changedFiles(repoRoot: string, base: string, head: string): string[] {\n const result = capture(repoRoot, 'git', ['diff', '--name-only', base, head]);\n if (!result.ok || result.out === '') return [];\n return result.out.split('\\n').map((line: string): string => line.trim()).filter((line: string): boolean => line.length > 0);\n}\n\n// Every file this feature branch has touched since the fork point — committed AND still in the\n// working tree (staged / unstaged / untracked). The committed-only `git diff forkPoint..HEAD` was\n// BLIND to uncommitted edits: for most of an editing session the files you are actively changing are\n// not yet in HEAD, so the overlap with main's changes was empty and conflict=false even when\n// origin/main had already moved onto those same files. Unioning in the working-tree changes makes the\n// conflict visible WHILE editing, so the guard can force an early merge instead of a painful late one.\nfunction featureChangedFiles(repoRoot: string, forkPoint: string): string[] {\n const out = new Set<string>();\n const add = (args: string[]): void => {\n const r = capture(repoRoot, 'git', args);\n if (!r.ok || r.out === '') return;\n for (const line of r.out.split('\\n')) {\n const f = line.trim();\n if (f.length > 0) out.add(f);\n }\n };\n add(['diff', '--name-only', forkPoint, 'HEAD']); // committed since the fork point\n add(['diff', '--name-only', 'HEAD']); // unstaged working-tree edits\n add(['diff', '--name-only', '--cached', 'HEAD']); // staged edits\n add(['ls-files', '--others', '--exclude-standard']); // untracked new files (respects .gitignore)\n return [...out];\n}\n\n// Has this feature branch already been merged into main? Reliable signal: a MERGED PR exists for the\n// branch. Best-effort — if gh is missing/unauthenticated we just report not-merged (false).\nfunction detectMergedPr(repoRoot: string, branch: string): string {\n if (!branch || branch === 'main') return '';\n const result = capture(repoRoot, 'gh', ['pr', 'list', '--head', branch, '--state', 'merged', '--json', 'number', '--jq', '.[0].number']);\n return result.ok ? result.out : '';\n}\n\n// An OPEN PR tracking this branch, if any. Best-effort — this is ADVISORY (it only lets the guard's\n// conflict block steer to the PR flow early), so an unreachable gh degrades to '' here. The HARD gate\n// that must never guess is wp-start-update's own openPrForBranch, which fails fast instead.\nfunction detectOpenPr(repoRoot: string, branch: string): string {\n if (!branch || branch === 'main') return '';\n const result = capture(repoRoot, 'gh', ['pr', 'list', '--head', branch, '--state', 'open', '--json', 'number', '--jq', '.[0].number']);\n return result.ok ? result.out : '';\n}\n\n// A benign status that never blocks — used when origin/main can't be resolved (no remote yet,\n// offline before first fetch). hasForkPoint=true + conflict=false so the guard allows the edit.\nfunction benignStatus(branch: string, featureHead: string): MainSyncStatus {\n return new MainSyncStatus(branch, false, '', true, null, '', featureHead, false, [], new Date().toISOString());\n}\n\n/**\n * The SLOW path, run only inside the detached refresher. Computes every cached signal the\n * feature-branch-guard needs: whether the branch is already merged (merged PR), whether a fork point\n * with origin/main still exists, and whether origin/main and this branch touched the SAME file since\n * the fork point (the deliberately-simple conflict heuristic — it over-blocks rather than miss a real\n * conflict). Never run on the hook's blocking path.\n */\nexport function computeMainSyncStatus(repoRoot: string): MainSyncStatus {\n const branch = gitBranch(repoRoot);\n const mergedPr = detectMergedPr(repoRoot, branch);\n // Advisory: lets the guard's conflict block steer to the PR flow early when a PR is already open.\n const openPr = detectOpenPr(repoRoot, branch);\n\n // Best-effort network refresh; offline just means we evaluate against the last-fetched ref.\n spawnSync('git', ['fetch', 'origin', 'main'], { cwd: repoRoot, stdio: 'ignore' });\n\n const head = capture(repoRoot, 'git', ['rev-parse', 'HEAD']);\n const originMain = capture(repoRoot, 'git', ['rev-parse', 'origin/main']);\n const featureHead = head.ok ? head.out : '';\n if (!head.ok || !originMain.ok) {\n const status = benignStatus(branch, featureHead);\n status.branchAlreadyMerged = mergedPr !== '';\n status.mergedPr = mergedPr;\n status.openPr = openPr;\n return status;\n }\n\n const forkPoint = capture(repoRoot, 'git', ['merge-base', 'origin/main', 'HEAD']);\n if (!forkPoint.ok || forkPoint.out === '') {\n // No common ancestor — main was merged into the branch. Force the human to squash.\n const noFork = new MainSyncStatus(branch, mergedPr !== '', mergedPr, false, null, originMain.out, featureHead, false, [], new Date().toISOString());\n noFork.openPr = openPr;\n return noFork;\n }\n\n const featureFiles = new Set(featureChangedFiles(repoRoot, forkPoint.out));\n const mainFiles = changedFiles(repoRoot, forkPoint.out, 'origin/main');\n const conflictFiles = mainFiles.filter((file: string): boolean => featureFiles.has(file));\n\n const status = new MainSyncStatus(\n branch,\n mergedPr !== '',\n mergedPr,\n true,\n forkPoint.out,\n originMain.out,\n featureHead,\n conflictFiles.length > 0,\n conflictFiles,\n new Date().toISOString(),\n );\n status.openPr = openPr;\n return status;\n}\n\n// The recovery steps when there is no fork point with origin/main (someone merged main into the\n// branch, so a clean squash-merge is impossible). Shared so the feature-branch-guard and pr-gate's\n// findForkPoint check present the SAME instructions. The human must redo the work on a fresh branch —\n// deliberately painful so the bad merge gets noticed and reported.\nexport function squashRecoverySteps(currentBranch: string): string[] {\n // Branch off origin/main directly (never `git checkout main`) so these steps are correct on the\n // primary repo AND inside a linked worktree, where main is checked out elsewhere and cannot be\n // checked out again.\n return [\n '1. Fetch latest main: git fetch origin main',\n `2. New branch off origin/main: git checkout -b ${currentBranch}-v2 origin/main`,\n `3. Squash-merge old branch: git merge --squash ${currentBranch}`,\n `4. Commit the squash: git add -A && git commit -m \"Squashed from ${currentBranch}\"`,\n '5. If a PR exists: open a NEW PR for the -v2 branch and close the old one.',\n ];\n}\n\n// Synchronously stamp a clean \"up to date with main\" status — call right after a successful merge\n// (the branch now contains origin/main). Unblocks the next edit immediately without waiting for the\n// async refresher. Best-effort: a git failure is swallowed (the refresher will recompute later).\nexport function stampCleanMainSyncStatus(repoRoot: string): void {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const branch = gitBranch(repoRoot);\n const originMain = capture(repoRoot, 'git', ['rev-parse', 'origin/main']);\n const featureHead = capture(repoRoot, 'git', ['rev-parse', 'HEAD']);\n if (!originMain.ok || !featureHead.ok) return;\n const status = new MainSyncStatus(\n branch, false, '', true, originMain.out, originMain.out, featureHead.out, false, [], new Date().toISOString(),\n );\n writeMainSyncStatus(repoRoot, status);\n } catch (err: unknown) {\n const error = toError(err);\n void error;\n }\n}\n"]}
1
+ {"version":3,"file":"main-sync-status.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/main-sync-status.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\n\nimport { WEBPIECES_TMP_DIR } from './constants';\nimport { toError } from './to-error';\n\n// Shared \"is my feature branch healthy relative to origin/main?\" state. The SLOW signals (git fetch +\n// merge-base + same-file-overlap + a merged-PR lookup) are computed by the ai-hook-rules refresher in a\n// DETACHED background process; the feature-branch-guard only READS this cached file. pr-gate's merge\n// flow also writes it synchronously after a merge. Lives here (the shared dep of both).\n\n// How long an `inprocess` refresher lock may sit before a new refresher assumes the prior run hung.\nexport const DEFAULT_HANG_TIMEOUT_MINUTES = 5;\n\nconst MAIN_SYNC_STATUS_FILE = 'main-sync-status.json';\nconst MAIN_SYNC_LOCK_FILE = 'main-sync.lock.json';\n\nconst LOCK_STATE_INPROCESS = 'inprocess';\nconst LOCK_STATE_FINISHED = 'finished';\n\n// Data-only (per CLAUDE.md, classes for data).\nexport class MainSyncStatus {\n branch: string;\n branchAlreadyMerged: boolean;\n mergedPr: string;\n hasForkPoint: boolean;\n forkPoint: string | null;\n originMain: string;\n featureHead: string;\n conflict: boolean;\n conflictFiles: string[];\n timestamp: string;\n // An OPEN (not merged) PR tracking this branch, if any — '' = none or not-yet-known. Advisory.\n // Kept OUT of the positional constructor (a defaulted field) so existing call sites don't churn.\n openPr: string = '';\n\n constructor(\n branch: string,\n branchAlreadyMerged: boolean,\n mergedPr: string,\n hasForkPoint: boolean,\n forkPoint: string | null,\n originMain: string,\n featureHead: string,\n conflict: boolean,\n conflictFiles: string[],\n timestamp: string,\n ) {\n this.branch = branch;\n this.branchAlreadyMerged = branchAlreadyMerged;\n this.mergedPr = mergedPr;\n this.hasForkPoint = hasForkPoint;\n this.forkPoint = forkPoint;\n this.originMain = originMain;\n this.featureHead = featureHead;\n this.conflict = conflict;\n this.conflictFiles = conflictFiles;\n this.timestamp = timestamp;\n }\n}\n\n// Concurrency state machine for the detached refresher. `started` is epoch ms. `pid` is the refresher\n// process's pid (0 = unknown) — used so a KILLED refresher doesn't wedge `inprocess` for the timeout.\nexport class MainSyncLock {\n state: string;\n started: number;\n pid: number;\n\n constructor(state: string, started: number, pid: number = 0) {\n this.state = state;\n this.started = started;\n this.pid = pid;\n }\n}\n\n// Raw JSON shapes for the cast at the parse boundary.\ninterface RawStatus {\n branch?: string;\n branchAlreadyMerged?: boolean;\n mergedPr?: string;\n hasForkPoint?: boolean;\n forkPoint?: string | null;\n originMain?: string;\n featureHead?: string;\n conflict?: boolean;\n conflictFiles?: string[];\n timestamp?: string;\n openPr?: string;\n}\n\ninterface RawLock {\n state?: string;\n started?: number;\n pid?: number;\n}\n\n// Result of a captured git/gh invocation: ok=false on spawn failure or non-zero exit.\ninterface CmdCapture {\n ok: boolean;\n out: string;\n}\n\n/**\n * Reads/writes the main-sync cache + lock and computes the slow \"is my branch healthy vs origin/main?\"\n * status. `@provideSingleton` so it's injectable and drawn in the rules-config DI design.\n */\n@provideSingleton()\n@injectable()\nexport class MainSyncStatusService {\n mainSyncStatusPath(repoRoot: string): string {\n return path.join(repoRoot, WEBPIECES_TMP_DIR, MAIN_SYNC_STATUS_FILE);\n }\n\n mainSyncLockPath(repoRoot: string): string {\n return path.join(repoRoot, WEBPIECES_TMP_DIR, MAIN_SYNC_LOCK_FILE);\n }\n\n // Pure read — any error (missing file, malformed JSON) returns null so the guard fails OPEN.\n readMainSyncStatus(repoRoot: string): MainSyncStatus | null {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const statusPath = this.mainSyncStatusPath(repoRoot);\n if (!fs.existsSync(statusPath)) return null;\n const raw = JSON.parse(fs.readFileSync(statusPath, 'utf8')) as RawStatus;\n const status = new MainSyncStatus(\n raw.branch ?? '',\n raw.branchAlreadyMerged ?? false,\n raw.mergedPr ?? '',\n raw.hasForkPoint ?? true,\n raw.forkPoint ?? null,\n raw.originMain ?? '',\n raw.featureHead ?? '',\n raw.conflict ?? false,\n raw.conflictFiles ?? [],\n raw.timestamp ?? '',\n );\n status.openPr = raw.openPr ?? '';\n return status;\n } catch (err: unknown) {\n const error = toError(err);\n void error;\n return null;\n }\n }\n\n writeMainSyncStatus(repoRoot: string, status: MainSyncStatus): void {\n const statusPath = this.mainSyncStatusPath(repoRoot);\n this.ensureDir(statusPath);\n fs.writeFileSync(statusPath, JSON.stringify(status, null, 2) + '\\n');\n }\n\n readMainSyncLock(repoRoot: string): MainSyncLock | null {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const lockPath = this.mainSyncLockPath(repoRoot);\n if (!fs.existsSync(lockPath)) return null;\n const raw = JSON.parse(fs.readFileSync(lockPath, 'utf8')) as RawLock;\n return new MainSyncLock(raw.state ?? LOCK_STATE_FINISHED, raw.started ?? 0, raw.pid ?? 0);\n } catch (err: unknown) {\n const error = toError(err);\n void error;\n return null;\n }\n }\n\n writeMainSyncLock(repoRoot: string, lock: MainSyncLock): void {\n const lockPath = this.mainSyncLockPath(repoRoot);\n this.ensureDir(lockPath);\n fs.writeFileSync(lockPath, JSON.stringify(lock, null, 2) + '\\n');\n }\n\n // A lock is stale (prior refresher assumed hung) once `inprocess` longer than hangTimeoutMinutes.\n isLockStale(lock: MainSyncLock, hangTimeoutMinutes: number, now: number = Date.now()): boolean {\n return now - lock.started > hangTimeoutMinutes * 60 * 1000;\n }\n\n // True when another refresher is actively running and we should NOT start a second one.\n isRefreshInProgress(repoRoot: string, hangTimeoutMinutes: number, now: number = Date.now()): boolean {\n const lock = this.readMainSyncLock(repoRoot);\n if (!lock) return false;\n if (lock.state !== LOCK_STATE_INPROCESS) return false;\n if (this.isLockStale(lock, hangTimeoutMinutes, now)) return false;\n return this.isProcessAlive(lock.pid);\n }\n\n inProcessLock(now: number = Date.now(), pid: number = process.pid): MainSyncLock {\n return new MainSyncLock(LOCK_STATE_INPROCESS, now, pid);\n }\n\n finishedLock(started: number): MainSyncLock {\n return new MainSyncLock(LOCK_STATE_FINISHED, started, 0);\n }\n\n /**\n * The SLOW path, run only inside the detached refresher. Computes every cached signal the\n * feature-branch-guard needs. Never run on the hook's blocking path.\n */\n // webpieces-disable max-lines-new-methods -- one cohesive slow-path computation\n computeMainSyncStatus(repoRoot: string): MainSyncStatus {\n const branch = this.gitBranch(repoRoot);\n const mergedPr = this.detectMergedPr(repoRoot, branch);\n const openPr = this.detectOpenPr(repoRoot, branch);\n\n // Best-effort network refresh; offline just means we evaluate against the last-fetched ref.\n spawnSync('git', ['fetch', 'origin', 'main'], { cwd: repoRoot, stdio: 'ignore' });\n\n const head = this.capture(repoRoot, 'git', ['rev-parse', 'HEAD']);\n const originMain = this.capture(repoRoot, 'git', ['rev-parse', 'origin/main']);\n const featureHead = head.ok ? head.out : '';\n if (!head.ok || !originMain.ok) {\n const status = this.benignStatus(branch, featureHead);\n status.branchAlreadyMerged = mergedPr !== '';\n status.mergedPr = mergedPr;\n status.openPr = openPr;\n return status;\n }\n\n const forkPoint = this.capture(repoRoot, 'git', ['merge-base', 'origin/main', 'HEAD']);\n if (!forkPoint.ok || forkPoint.out === '') {\n const noFork = new MainSyncStatus(branch, mergedPr !== '', mergedPr, false, null, originMain.out, featureHead, false, [], new Date().toISOString());\n noFork.openPr = openPr;\n return noFork;\n }\n\n const featureFiles = new Set(this.featureChangedFiles(repoRoot, forkPoint.out));\n const mainFiles = this.changedFiles(repoRoot, forkPoint.out, 'origin/main');\n const conflictFiles = mainFiles.filter((file: string): boolean => featureFiles.has(file));\n\n const status = new MainSyncStatus(\n branch,\n mergedPr !== '',\n mergedPr,\n true,\n forkPoint.out,\n originMain.out,\n featureHead,\n conflictFiles.length > 0,\n conflictFiles,\n new Date().toISOString(),\n );\n status.openPr = openPr;\n return status;\n }\n\n // The recovery steps when there is no fork point with origin/main (a bad merge of main into branch).\n squashRecoverySteps(currentBranch: string): string[] {\n return [\n '1. Fetch latest main: git fetch origin main',\n `2. New branch off origin/main: git checkout -b ${currentBranch}-v2 origin/main`,\n `3. Squash-merge old branch: git merge --squash ${currentBranch}`,\n `4. Commit the squash: git add -A && git commit -m \"Squashed from ${currentBranch}\"`,\n '5. If a PR exists: open a NEW PR for the -v2 branch and close the old one.',\n ];\n }\n\n // Synchronously stamp a clean \"up to date with main\" status — call right after a successful merge.\n stampCleanMainSyncStatus(repoRoot: string): void {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const branch = this.gitBranch(repoRoot);\n const originMain = this.capture(repoRoot, 'git', ['rev-parse', 'origin/main']);\n const featureHead = this.capture(repoRoot, 'git', ['rev-parse', 'HEAD']);\n if (!originMain.ok || !featureHead.ok) return;\n const status = new MainSyncStatus(\n branch, false, '', true, originMain.out, originMain.out, featureHead.out, false, [], new Date().toISOString(),\n );\n this.writeMainSyncStatus(repoRoot, status);\n } catch (err: unknown) {\n const error = toError(err);\n void error;\n }\n }\n\n private ensureDir(filePath: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n }\n\n // Liveness probe: is `pid` still a running process? pid <= 0 (unknown) → assume alive.\n private isProcessAlive(pid: number): boolean {\n if (pid <= 0) return true;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n process.kill(pid, 0);\n return true;\n } catch (err: unknown) {\n const error = toError(err);\n return !error.message.includes('ESRCH');\n }\n }\n\n // Run a command capturing trimmed stdout; ok=false on spawn failure or non-zero exit.\n private capture(repoRoot: string, cmd: string, args: string[]): CmdCapture {\n const result = spawnSync(cmd, args, { cwd: repoRoot, encoding: 'utf8' });\n if (result.status !== 0 || typeof result.stdout !== 'string') return { ok: false, out: '' };\n return { ok: true, out: result.stdout.trim() };\n }\n\n // The actual checked-out branch in repoRoot — cwd-correct so the cache's `branch` label matches.\n private gitBranch(repoRoot: string): string {\n const result = this.capture(repoRoot, 'git', ['rev-parse', '--abbrev-ref', 'HEAD']);\n return result.ok ? result.out : '';\n }\n\n private changedFiles(repoRoot: string, base: string, head: string): string[] {\n const result = this.capture(repoRoot, 'git', ['diff', '--name-only', base, head]);\n if (!result.ok || result.out === '') return [];\n return result.out.split('\\n').map((line: string): string => line.trim()).filter((line: string): boolean => line.length > 0);\n }\n\n // Every file this feature branch has touched since the fork point — committed AND still in the\n // working tree (staged / unstaged / untracked), so a conflict is visible WHILE editing.\n private featureChangedFiles(repoRoot: string, forkPoint: string): string[] {\n const out = new Set<string>();\n const add = (args: string[]): void => {\n const r = this.capture(repoRoot, 'git', args);\n if (!r.ok || r.out === '') return;\n for (const line of r.out.split('\\n')) {\n const f = line.trim();\n if (f.length > 0) out.add(f);\n }\n };\n add(['diff', '--name-only', forkPoint, 'HEAD']); // committed since the fork point\n add(['diff', '--name-only', 'HEAD']); // unstaged working-tree edits\n add(['diff', '--name-only', '--cached', 'HEAD']); // staged edits\n add(['ls-files', '--others', '--exclude-standard']); // untracked new files (respects .gitignore)\n return [...out];\n }\n\n // Has this feature branch already been merged into main? Reliable signal: a MERGED PR exists.\n private detectMergedPr(repoRoot: string, branch: string): string {\n if (!branch || branch === 'main') return '';\n const result = this.capture(repoRoot, 'gh', ['pr', 'list', '--head', branch, '--state', 'merged', '--json', 'number', '--jq', '.[0].number']);\n return result.ok ? result.out : '';\n }\n\n // An OPEN PR tracking this branch, if any. Best-effort/advisory.\n private detectOpenPr(repoRoot: string, branch: string): string {\n if (!branch || branch === 'main') return '';\n const result = this.capture(repoRoot, 'gh', ['pr', 'list', '--head', branch, '--state', 'open', '--json', 'number', '--jq', '.[0].number']);\n return result.ok ? result.out : '';\n }\n\n // A benign status that never blocks — used when origin/main can't be resolved.\n private benignStatus(branch: string, featureHead: string): MainSyncStatus {\n return new MainSyncStatus(branch, false, '', true, null, '', featureHead, false, [], new Date().toISOString());\n }\n}\n\n// Temporary migration delegators to MainSyncStatusService — removed once consumers inject it.\nconst mainSyncSvc = new MainSyncStatusService();\n\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function mainSyncStatusPath(repoRoot: string): string { return mainSyncSvc.mainSyncStatusPath(repoRoot); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function mainSyncLockPath(repoRoot: string): string { return mainSyncSvc.mainSyncLockPath(repoRoot); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function readMainSyncStatus(repoRoot: string): MainSyncStatus | null { return mainSyncSvc.readMainSyncStatus(repoRoot); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function writeMainSyncStatus(repoRoot: string, status: MainSyncStatus): void { mainSyncSvc.writeMainSyncStatus(repoRoot, status); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function readMainSyncLock(repoRoot: string): MainSyncLock | null { return mainSyncSvc.readMainSyncLock(repoRoot); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function writeMainSyncLock(repoRoot: string, lock: MainSyncLock): void { mainSyncSvc.writeMainSyncLock(repoRoot, lock); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function isLockStale(lock: MainSyncLock, hangTimeoutMinutes: number, now: number = Date.now()): boolean { return mainSyncSvc.isLockStale(lock, hangTimeoutMinutes, now); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function isRefreshInProgress(repoRoot: string, hangTimeoutMinutes: number, now: number = Date.now()): boolean { return mainSyncSvc.isRefreshInProgress(repoRoot, hangTimeoutMinutes, now); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function inProcessLock(now: number = Date.now(), pid: number = process.pid): MainSyncLock { return mainSyncSvc.inProcessLock(now, pid); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function finishedLock(started: number): MainSyncLock { return mainSyncSvc.finishedLock(started); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function computeMainSyncStatus(repoRoot: string): MainSyncStatus { return mainSyncSvc.computeMainSyncStatus(repoRoot); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function squashRecoverySteps(currentBranch: string): string[] { return mainSyncSvc.squashRecoverySteps(currentBranch); }\n// webpieces-disable no-function-outside-class -- temporary back-compat delegator to MainSyncStatusService; removed once consumers inject it\nexport function stampCleanMainSyncStatus(repoRoot: string): void { mainSyncSvc.stampCleanMainSyncStatus(repoRoot); }\n"]}
@@ -4,6 +4,7 @@ import { TemplateWriter } from './load-template';
4
4
  import { DiffScope } from './diff-scope';
5
5
  import { BranchMutationLog } from './branch-mutation-log';
6
6
  import { ReviewJsonService } from './review-json';
7
+ import { MainSyncStatusService } from './main-sync-status';
7
8
  /**
8
9
  * DI-design root for @webpieces/rules-config (role:designed-lib).
9
10
  *
@@ -20,5 +21,6 @@ export declare class RulesConfigDesign {
20
21
  private readonly diffScope;
21
22
  private readonly branchMutationLog;
22
23
  private readonly reviewJson;
23
- constructor(repoRootFinder: RepoRootFinder, configLoader: ConfigLoader, templateWriter: TemplateWriter, diffScope: DiffScope, branchMutationLog: BranchMutationLog, reviewJson: ReviewJsonService);
24
+ private readonly mainSyncStatus;
25
+ constructor(repoRootFinder: RepoRootFinder, configLoader: ConfigLoader, templateWriter: TemplateWriter, diffScope: DiffScope, branchMutationLog: BranchMutationLog, reviewJson: ReviewJsonService, mainSyncStatus: MainSyncStatusService);
24
26
  }
@@ -11,6 +11,7 @@ const load_template_1 = require("./load-template");
11
11
  const diff_scope_1 = require("./diff-scope");
12
12
  const branch_mutation_log_1 = require("./branch-mutation-log");
13
13
  const review_json_1 = require("./review-json");
14
+ const main_sync_status_1 = require("./main-sync-status");
14
15
  /**
15
16
  * DI-design root for @webpieces/rules-config (role:designed-lib).
16
17
  *
@@ -27,13 +28,15 @@ let RulesConfigDesign = class RulesConfigDesign {
27
28
  diffScope;
28
29
  branchMutationLog;
29
30
  reviewJson;
30
- constructor(repoRootFinder, configLoader, templateWriter, diffScope, branchMutationLog, reviewJson) {
31
+ mainSyncStatus;
32
+ constructor(repoRootFinder, configLoader, templateWriter, diffScope, branchMutationLog, reviewJson, mainSyncStatus) {
31
33
  this.repoRootFinder = repoRootFinder;
32
34
  this.configLoader = configLoader;
33
35
  this.templateWriter = templateWriter;
34
36
  this.diffScope = diffScope;
35
37
  this.branchMutationLog = branchMutationLog;
36
38
  this.reviewJson = reviewJson;
39
+ this.mainSyncStatus = mainSyncStatus;
37
40
  }
38
41
  };
39
42
  exports.RulesConfigDesign = RulesConfigDesign;
@@ -46,6 +49,7 @@ exports.RulesConfigDesign = RulesConfigDesign = tslib_1.__decorate([
46
49
  load_template_1.TemplateWriter,
47
50
  diff_scope_1.DiffScope,
48
51
  branch_mutation_log_1.BranchMutationLog,
49
- review_json_1.ReviewJsonService])
52
+ review_json_1.ReviewJsonService,
53
+ main_sync_status_1.MainSyncStatusService])
50
54
  ], RulesConfigDesign);
51
55
  //# sourceMappingURL=rules-config-design.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rules-config-design.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/rules-config-design.ts"],"names":[],"mappings":";;;;AAAA,oDAAsD;AACtD,0DAA2D;AAC3D,yCAAuC;AAEvC,2CAA6C;AAC7C,+CAA6C;AAC7C,mDAAiD;AACjD,6CAAyC;AACzC,+DAA0D;AAC1D,+CAAkD;AAElD;;;;;;;;GAQG;AAII,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAEL;IACA;IACA;IACA;IACA;IACA;IANrB,YACqB,cAA8B,EAC9B,YAA0B,EAC1B,cAA8B,EAC9B,SAAoB,EACpB,iBAAoC,EACpC,UAA6B;QAL7B,mBAAc,GAAd,cAAc,CAAgB;QAC9B,iBAAY,GAAZ,YAAY,CAAc;QAC1B,mBAAc,GAAd,cAAc,CAAgB;QAC9B,cAAS,GAAT,SAAS,CAAW;QACpB,sBAAiB,GAAjB,iBAAiB,CAAmB;QACpC,eAAU,GAAV,UAAU,CAAmB;IAC/C,CAAC;CACP,CAAA;AATY,8CAAiB;4BAAjB,iBAAiB;IAH7B,IAAA,0BAAc,GAAE;IAChB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;6CAG4B,0BAAc;QAChB,0BAAY;QACV,8BAAc;QACnB,sBAAS;QACD,uCAAiB;QACxB,+BAAiB;GAPzC,iBAAiB,CAS7B","sourcesContent":["import { DocumentDesign } from '@webpieces/core-util';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\n\nimport { RepoRootFinder } from './repo-root';\nimport { ConfigLoader } from './load-config';\nimport { TemplateWriter } from './load-template';\nimport { DiffScope } from './diff-scope';\nimport { BranchMutationLog } from './branch-mutation-log';\nimport { ReviewJsonService } from './review-json';\n\n/**\n * DI-design root for @webpieces/rules-config (role:designed-lib).\n *\n * `@DocumentDesign` marks the top of the DAG the DI-design analyzer roots on, so the library's design\n * (design.json / design.md / design.html) is generated. rules-config is the shared foundation whose\n * utilities are being migrated from free functions to injected `@provideSingleton` service classes; as\n * each service class lands (config loader, template writer, diff/git services, …) it is injected HERE\n * so it appears in the drawn design.\n */\n@DocumentDesign()\n@provideSingleton()\n@injectable()\nexport class RulesConfigDesign {\n constructor(\n private readonly repoRootFinder: RepoRootFinder,\n private readonly configLoader: ConfigLoader,\n private readonly templateWriter: TemplateWriter,\n private readonly diffScope: DiffScope,\n private readonly branchMutationLog: BranchMutationLog,\n private readonly reviewJson: ReviewJsonService,\n ) {}\n}\n"]}
1
+ {"version":3,"file":"rules-config-design.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/rules-config-design.ts"],"names":[],"mappings":";;;;AAAA,oDAAsD;AACtD,0DAA2D;AAC3D,yCAAuC;AAEvC,2CAA6C;AAC7C,+CAA6C;AAC7C,mDAAiD;AACjD,6CAAyC;AACzC,+DAA0D;AAC1D,+CAAkD;AAClD,yDAA2D;AAE3D;;;;;;;;GAQG;AAII,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAEL;IACA;IACA;IACA;IACA;IACA;IACA;IAPrB,YACqB,cAA8B,EAC9B,YAA0B,EAC1B,cAA8B,EAC9B,SAAoB,EACpB,iBAAoC,EACpC,UAA6B,EAC7B,cAAqC;QANrC,mBAAc,GAAd,cAAc,CAAgB;QAC9B,iBAAY,GAAZ,YAAY,CAAc;QAC1B,mBAAc,GAAd,cAAc,CAAgB;QAC9B,cAAS,GAAT,SAAS,CAAW;QACpB,sBAAiB,GAAjB,iBAAiB,CAAmB;QACpC,eAAU,GAAV,UAAU,CAAmB;QAC7B,mBAAc,GAAd,cAAc,CAAuB;IACvD,CAAC;CACP,CAAA;AAVY,8CAAiB;4BAAjB,iBAAiB;IAH7B,IAAA,0BAAc,GAAE;IAChB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;6CAG4B,0BAAc;QAChB,0BAAY;QACV,8BAAc;QACnB,sBAAS;QACD,uCAAiB;QACxB,+BAAiB;QACb,wCAAqB;GARjD,iBAAiB,CAU7B","sourcesContent":["import { DocumentDesign } from '@webpieces/core-util';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\n\nimport { RepoRootFinder } from './repo-root';\nimport { ConfigLoader } from './load-config';\nimport { TemplateWriter } from './load-template';\nimport { DiffScope } from './diff-scope';\nimport { BranchMutationLog } from './branch-mutation-log';\nimport { ReviewJsonService } from './review-json';\nimport { MainSyncStatusService } from './main-sync-status';\n\n/**\n * DI-design root for @webpieces/rules-config (role:designed-lib).\n *\n * `@DocumentDesign` marks the top of the DAG the DI-design analyzer roots on, so the library's design\n * (design.json / design.md / design.html) is generated. rules-config is the shared foundation whose\n * utilities are being migrated from free functions to injected `@provideSingleton` service classes; as\n * each service class lands (config loader, template writer, diff/git services, …) it is injected HERE\n * so it appears in the drawn design.\n */\n@DocumentDesign()\n@provideSingleton()\n@injectable()\nexport class RulesConfigDesign {\n constructor(\n private readonly repoRootFinder: RepoRootFinder,\n private readonly configLoader: ConfigLoader,\n private readonly templateWriter: TemplateWriter,\n private readonly diffScope: DiffScope,\n private readonly branchMutationLog: BranchMutationLog,\n private readonly reviewJson: ReviewJsonService,\n private readonly mainSyncStatus: MainSyncStatusService,\n ) {}\n}\n"]}