@@ -10,6 +10,65 @@ const crypto = require('crypto')
1010const fs = require ( 'fs' )
1111const path = require ( 'path' )
1212const { resolveGlobalHostTarget } = require ( './global-host-target.js' )
13+ const {
14+ describeGlobalAdapterRefreshForPackageRoot
15+ } = require ( './global-adapter-refresh-guidance.js' )
16+
17+ const PACKAGE_ROOT = path . join ( __dirname , '..' , '..' )
18+
19+ /**
20+ * Repair command for missing/stale user-global adapters.
21+ * Source checkout → R1a `devcodex global-adapters apply`; published package → npm -g.
22+ */
23+ function resolveAdapterRefreshGuidance ( options = { } ) {
24+ if ( options . guidance && typeof options . guidance === 'object' ) return options . guidance
25+ const packageRoot = options . packageRoot
26+ ? path . resolve ( options . packageRoot )
27+ : PACKAGE_ROOT
28+ return describeGlobalAdapterRefreshForPackageRoot ( packageRoot , {
29+ packageVersion : options . packageVersion || null ,
30+ fs : options . fs || fs ,
31+ path : options . path || path
32+ } )
33+ }
34+
35+ function buildCheckRepairCatalog ( guidance ) {
36+ const command = guidance && guidance . primary
37+ ? String ( guidance . primary )
38+ : 'devcodex global-adapters apply'
39+ return Object . freeze ( {
40+ globalKernelAgentsMd : {
41+ check : 'globalKernelAgentsMd' ,
42+ command,
43+ detail : 'Install/refresh the user-global controlling kernel and stable runtime copy.'
44+ } ,
45+ globalCodexLifecycleReachable : {
46+ check : 'globalCodexLifecycleReachable' ,
47+ command,
48+ detail : 'Install/refresh the Codex user-global lifecycle runtime; workspace host directories are not used.'
49+ } ,
50+ denyAdapterContract : {
51+ check : 'denyAdapterContract' ,
52+ command,
53+ detail : 'lifecycle-host-adapters must export adaptGrokOutput and decision:deny mapping.'
54+ } ,
55+ pathObservableCapability : {
56+ check : 'pathObservableCapability' ,
57+ command,
58+ detail : 'lifecycle-bootstrap-state must treat Grok as path-observable (same band as Codex tool-path).'
59+ } ,
60+ globalGrokPluginInstalled : {
61+ check : 'globalGrokPluginInstalled' ,
62+ command,
63+ detail : 'Install/refresh the Grok plugin under the user-global Grok configuration root.'
64+ } ,
65+ globalGrokPluginConfigured : {
66+ check : 'globalGrokPluginConfigured' ,
67+ command,
68+ detail : 'Ensure the user-global Grok config registers the managed global plugin.'
69+ }
70+ } )
71+ }
1372
1473/** Scannable always-on checklist for passive-hook hosts (Grok). */
1574const GROK_TURN_EXECUTION_CHECKLIST = Object . freeze ( [
@@ -64,39 +123,6 @@ function assertCannotClaimFloor(cannotClaim) {
64123 return { ok : true }
65124}
66125
67- const CHECK_REPAIR_CATALOG = Object . freeze ( {
68- globalKernelAgentsMd : {
69- check : 'globalKernelAgentsMd' ,
70- command : 'npm install -g devcodex' ,
71- detail : 'Install the user-global controlling kernel and stable runtime copy.'
72- } ,
73- globalCodexLifecycleReachable : {
74- check : 'globalCodexLifecycleReachable' ,
75- command : 'npm install -g devcodex' ,
76- detail : 'Install the Codex user-global lifecycle runtime; workspace host directories are not used.'
77- } ,
78- denyAdapterContract : {
79- check : 'denyAdapterContract' ,
80- command : 'npm install -g devcodex' ,
81- detail : 'lifecycle-host-adapters must export adaptGrokOutput and decision:deny mapping.'
82- } ,
83- pathObservableCapability : {
84- check : 'pathObservableCapability' ,
85- command : 'npm install -g devcodex' ,
86- detail : 'lifecycle-bootstrap-state must treat Grok as path-observable (same band as Codex tool-path).'
87- } ,
88- globalGrokPluginInstalled : {
89- check : 'globalGrokPluginInstalled' ,
90- command : 'npm install -g devcodex' ,
91- detail : 'Install the Grok plugin under the user-global Grok configuration root.'
92- } ,
93- globalGrokPluginConfigured : {
94- check : 'globalGrokPluginConfigured' ,
95- command : 'npm install -g devcodex' ,
96- detail : 'Ensure the user-global Grok config registers the managed global plugin.'
97- }
98- } )
99-
100126function resolveGrokIntentSkillBundle ( intent ) {
101127 const key = String ( intent || '' ) . trim ( ) . toLowerCase ( )
102128 if ( Object . prototype . hasOwnProperty . call ( GROK_INTENT_SKILL_BUNDLES , key ) ) {
@@ -114,17 +140,20 @@ function resolveGrokIntentSkillBundle(intent) {
114140 }
115141}
116142
117- function buildGrokRepairSteps ( checks = { } ) {
143+ function buildGrokRepairSteps ( checks = { } , options = { } ) {
144+ const guidance = resolveAdapterRefreshGuidance ( options )
145+ const catalog = buildCheckRepairCatalog ( guidance )
146+ const fallbackCommand = guidance . primary || 'devcodex global-adapters apply'
118147 const steps = [ ]
119148 for ( const [ key , ok ] of Object . entries ( checks || { } ) ) {
120149 if ( ok ) continue
121- const catalog = CHECK_REPAIR_CATALOG [ key ]
122- if ( catalog ) {
123- steps . push ( { ...catalog , status : 'failed' } )
150+ const entry = catalog [ key ]
151+ if ( entry ) {
152+ steps . push ( { ...entry , status : 'failed' } )
124153 } else {
125154 steps . push ( {
126155 check : key ,
127- command : 'npm install -g devcodex' ,
156+ command : fallbackCommand ,
128157 detail : `Missing HostParity check: ${ key } ` ,
129158 status : 'failed'
130159 } )
@@ -369,10 +398,17 @@ function evaluateGrokHostParity(input = {}) {
369398
370399 // Full requires hardReady + recommendation to use launcher; plain child never auto-Full
371400 const tier = hardReady ? 'full-capable' : 'partial'
372- const repairSteps = buildGrokRepairSteps ( checks )
401+ const refreshGuidance = resolveAdapterRefreshGuidance ( {
402+ packageRoot : input . packageRoot || PACKAGE_ROOT ,
403+ packageVersion : input . packageVersion ,
404+ guidance : input . adapterRefreshGuidance ,
405+ fs : input . fs ,
406+ path : input . path
407+ } )
408+ const repairSteps = buildGrokRepairSteps ( checks , { guidance : refreshGuidance } )
373409 const recommendedEntry = hardReady
374410 ? 'devcodex grok # Full evidence: --rules binds the user-global controlling kernel'
375- : ( repairSteps [ 0 ] && repairSteps [ 0 ] . command ) || 'npm install -g devcodex '
411+ : ( repairSteps [ 0 ] && repairSteps [ 0 ] . command ) || refreshGuidance . primary || 'devcodex global-adapters apply '
376412
377413 const cannotClaim = [ ...MIN_CANNOT_CLAIM ]
378414 assertCannotClaimFloor ( cannotClaim )
@@ -383,6 +419,7 @@ function evaluateGrokHostParity(input = {}) {
383419 . slice ( 0 , 3 )
384420 . map ( ( s ) => s . command )
385421 . join ( ' ; ' )
422+ const fallbackFix = refreshGuidance . nextStepShort || refreshGuidance . primary || 'devcodex global-adapters apply'
386423
387424 const scorecard = {
388425 schemaVersion : 'HostParityScorecardV1' ,
@@ -404,13 +441,15 @@ function evaluateGrokHostParity(input = {}) {
404441 pluginRoot : hasGlobalGrokPlugin ? pluginRoot : null ,
405442 scope : 'user-global' ,
406443 deny,
407- bootstrap
444+ bootstrap,
445+ adapterRefreshPrimary : refreshGuidance . primary || null ,
446+ adapterRefreshSourceCheckout : refreshGuidance . sourceCheckout === true
408447 } ,
409448 recommendedEntry,
410449 cannotClaim,
411450 userVisibleSummary : hardReady
412451 ? 'Grok HostParity: full-capable (PreTool deny + path-observable + kernel). Use `devcodex grok` for Full session evidence. Inject/Stop still Partial. Follow GrokTurnChecklist + Intent→Skill bundle.'
413- : `Grok HostParity: partial — failed: ${ failedChecks . join ( ', ' ) || 'unknown' } . Fix: ${ repairPreview || 'npm install -g devcodex' } . Then doctor --json hostParity.repairSteps.`
452+ : `Grok HostParity: partial — failed: ${ failedChecks . join ( ', ' ) || 'unknown' } . Fix: ${ repairPreview || fallbackFix } . Then doctor --json hostParity.repairSteps.`
414453 }
415454
416455 scorecard . digest = crypto
@@ -467,7 +506,6 @@ function entryCheckAssistSuffix(options = {}) {
467506module . exports = {
468507 GROK_TURN_EXECUTION_CHECKLIST ,
469508 GROK_INTENT_SKILL_BUNDLES ,
470- CHECK_REPAIR_CATALOG ,
471509 MIN_CANNOT_CLAIM ,
472510 assertCannotClaimFloor,
473511 evaluateGrokHostParity,
@@ -476,6 +514,8 @@ module.exports = {
476514 composePc4Line,
477515 resolveGrokIntentSkillBundle,
478516 buildGrokRepairSteps,
517+ buildCheckRepairCatalog,
518+ resolveAdapterRefreshGuidance,
479519 formatGrokTurnChecklistMarkdown,
480520 classifyGrokTurnOmissionSample,
481521 classifyWorkspaceRootScanSample,
0 commit comments