@nklisch/pi-enhanced 0.1.2 → 0.1.4

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.
Files changed (236) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +3 -2
  3. package/node_modules/@nklisch/pi-clearance/README.md +10 -5
  4. package/node_modules/@nklisch/pi-clearance/docs/ARCHITECTURE.md +12 -7
  5. package/node_modules/@nklisch/pi-clearance/docs/CONFIGURATION.md +25 -35
  6. package/node_modules/@nklisch/pi-clearance/docs/DEVELOPER_GUIDE.md +30 -30
  7. package/node_modules/@nklisch/pi-clearance/docs/PACK_AUTHORING.md +5 -4
  8. package/node_modules/@nklisch/pi-clearance/docs/PRINCIPLES.md +14 -10
  9. package/node_modules/@nklisch/pi-clearance/docs/REFERENCE_PATTERNS.md +1 -1
  10. package/node_modules/@nklisch/pi-clearance/docs/REVIEWER_PROMPTS.md +12 -8
  11. package/node_modules/@nklisch/pi-clearance/docs/RULE_PACKS.md +1 -1
  12. package/node_modules/@nklisch/pi-clearance/docs/SPEC.md +7 -6
  13. package/node_modules/@nklisch/pi-clearance/docs/TUNE.md +2 -2
  14. package/node_modules/@nklisch/pi-clearance/docs/USER_GUIDE.md +7 -3
  15. package/node_modules/@nklisch/pi-clearance/docs/VISION.md +3 -3
  16. package/node_modules/@nklisch/pi-clearance/native/clearance-core.darwin-arm64.node +0 -0
  17. package/node_modules/@nklisch/pi-clearance/native/clearance-core.darwin-x64.node +0 -0
  18. package/node_modules/@nklisch/pi-clearance/native/clearance-core.linux-arm64-gnu.node +0 -0
  19. package/node_modules/@nklisch/pi-clearance/native/clearance-core.linux-x64-gnu.node +0 -0
  20. package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-arm64-msvc.node +0 -0
  21. package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-x64-msvc.node +0 -0
  22. package/node_modules/@nklisch/pi-clearance/package.json +9 -5
  23. package/node_modules/@nklisch/pi-clearance/src/config/config-command-plans.ts +79 -3
  24. package/node_modules/@nklisch/pi-clearance/src/config/config-command-writer.ts +7 -1
  25. package/node_modules/@nklisch/pi-clearance/src/config/defaults.ts +42 -0
  26. package/node_modules/@nklisch/pi-clearance/src/config/gated-tools.ts +7 -0
  27. package/node_modules/@nklisch/pi-clearance/src/config/loader.ts +7 -1
  28. package/node_modules/@nklisch/pi-clearance/src/config/pack-enablement-writer.ts +1 -0
  29. package/node_modules/@nklisch/pi-clearance/src/config/paths.ts +14 -3
  30. package/node_modules/@nklisch/pi-clearance/src/config/persistence.ts +135 -0
  31. package/node_modules/@nklisch/pi-clearance/src/config/schema.ts +74 -26
  32. package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCase.ts +1 -1
  33. package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseCategory.ts +1 -1
  34. package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseExpectation.ts +1 -1
  35. package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseResult.ts +1 -1
  36. package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseResultOutcome.ts +1 -1
  37. package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialCaseSource.ts +1 -1
  38. package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialValidationReport.ts +1 -1
  39. package/node_modules/@nklisch/pi-clearance/src/contracts/AdversarialValidationStatus.ts +1 -1
  40. package/node_modules/@nklisch/pi-clearance/src/contracts/BashBlock.ts +1 -1
  41. package/node_modules/@nklisch/pi-clearance/src/contracts/BashCommandShape.ts +1 -1
  42. package/node_modules/@nklisch/pi-clearance/src/contracts/BashConditionalArm.ts +1 -1
  43. package/node_modules/@nklisch/pi-clearance/src/contracts/BashControlConstruct.ts +1 -1
  44. package/node_modules/@nklisch/pi-clearance/src/contracts/BashFlag.ts +1 -1
  45. package/node_modules/@nklisch/pi-clearance/src/contracts/BashForLoopKeywordSpans.ts +1 -1
  46. package/node_modules/@nklisch/pi-clearance/src/contracts/BashIteratorEntry.ts +1 -1
  47. package/node_modules/@nklisch/pi-clearance/src/contracts/BashIteratorEntryKind.ts +1 -1
  48. package/node_modules/@nklisch/pi-clearance/src/contracts/BashListOperator.ts +1 -1
  49. package/node_modules/@nklisch/pi-clearance/src/contracts/BashLoopVariableReference.ts +1 -1
  50. package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFact.ts +1 -1
  51. package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFactContext.ts +1 -1
  52. package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFactProvenance.ts +1 -1
  53. package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFactProvenanceEntry.ts +1 -1
  54. package/node_modules/@nklisch/pi-clearance/src/contracts/BashPathFacts.ts +1 -1
  55. package/node_modules/@nklisch/pi-clearance/src/contracts/BashPipeline.ts +1 -1
  56. package/node_modules/@nklisch/pi-clearance/src/contracts/BashStage.ts +1 -1
  57. package/node_modules/@nklisch/pi-clearance/src/contracts/BashStageProgram.ts +1 -1
  58. package/node_modules/@nklisch/pi-clearance/src/contracts/BlockOperator.ts +1 -1
  59. package/node_modules/@nklisch/pi-clearance/src/contracts/CapturedOutcome.ts +1 -1
  60. package/node_modules/@nklisch/pi-clearance/src/contracts/CommandFamilyKey.ts +1 -1
  61. package/node_modules/@nklisch/pi-clearance/src/contracts/CommandFamilySummary.ts +1 -1
  62. package/node_modules/@nklisch/pi-clearance/src/contracts/CompileError.ts +1 -1
  63. package/node_modules/@nklisch/pi-clearance/src/contracts/CompositionOperator.ts +1 -1
  64. package/node_modules/@nklisch/pi-clearance/src/contracts/CompoundBodyReason.ts +1 -1
  65. package/node_modules/@nklisch/pi-clearance/src/contracts/CompoundFeatureReason.ts +1 -1
  66. package/node_modules/@nklisch/pi-clearance/src/contracts/CompoundForm.ts +1 -1
  67. package/node_modules/@nklisch/pi-clearance/src/contracts/CompoundIteratorReason.ts +1 -1
  68. package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusEntry.ts +1 -1
  69. package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusExpectedLabel.ts +1 -1
  70. package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusFidelity.ts +1 -1
  71. package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusQueryModel.ts +1 -1
  72. package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusQuerySummary.ts +1 -1
  73. package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusQuerySummarySnapshot.ts +1 -1
  74. package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusRecord.ts +1 -1
  75. package/node_modules/@nklisch/pi-clearance/src/contracts/CorpusSource.ts +1 -1
  76. package/node_modules/@nklisch/pi-clearance/src/contracts/CountByLabel.ts +1 -1
  77. package/node_modules/@nklisch/pi-clearance/src/contracts/Decision.ts +1 -1
  78. package/node_modules/@nklisch/pi-clearance/src/contracts/DecisionEffect.ts +1 -1
  79. package/node_modules/@nklisch/pi-clearance/src/contracts/DecisionProvenance.ts +1 -1
  80. package/node_modules/@nklisch/pi-clearance/src/contracts/DecisionSource.ts +1 -1
  81. package/node_modules/@nklisch/pi-clearance/src/contracts/DiagnosticSeverity.ts +1 -1
  82. package/node_modules/@nklisch/pi-clearance/src/contracts/EffectivePolicy.ts +1 -1
  83. package/node_modules/@nklisch/pi-clearance/src/contracts/EmbeddedShellProjection.ts +1 -1
  84. package/node_modules/@nklisch/pi-clearance/src/contracts/EnvironmentAssignment.ts +1 -1
  85. package/node_modules/@nklisch/pi-clearance/src/contracts/IteratorSourceKind.ts +1 -1
  86. package/node_modules/@nklisch/pi-clearance/src/contracts/LoopQuoteKind.ts +1 -1
  87. package/node_modules/@nklisch/pi-clearance/src/contracts/LoopVariableUnknownReason.ts +1 -1
  88. package/node_modules/@nklisch/pi-clearance/src/contracts/MatcherExpr.ts +1 -1
  89. package/node_modules/@nklisch/pi-clearance/src/contracts/MutationShapeKind.ts +1 -1
  90. package/node_modules/@nklisch/pi-clearance/src/contracts/MutationTrustBoundaryClassification.ts +1 -1
  91. package/node_modules/@nklisch/pi-clearance/src/contracts/MutationTrustBoundaryKind.ts +1 -1
  92. package/node_modules/@nklisch/pi-clearance/src/contracts/PackCompileResult.ts +1 -1
  93. package/node_modules/@nklisch/pi-clearance/src/contracts/PackWarningLevel.ts +1 -1
  94. package/node_modules/@nklisch/pi-clearance/src/contracts/ParsedEvidence.ts +1 -1
  95. package/node_modules/@nklisch/pi-clearance/src/contracts/ParsedShapeSummary.ts +1 -1
  96. package/node_modules/@nklisch/pi-clearance/src/contracts/PathAccess.ts +1 -1
  97. package/node_modules/@nklisch/pi-clearance/src/contracts/PathFactProjectScope.ts +1 -1
  98. package/node_modules/@nklisch/pi-clearance/src/contracts/PathFactsRequirement.ts +1 -1
  99. package/node_modules/@nklisch/pi-clearance/src/contracts/PathFactsResolvedConfig.ts +1 -1
  100. package/node_modules/@nklisch/pi-clearance/src/contracts/PathNormalization.ts +1 -1
  101. package/node_modules/@nklisch/pi-clearance/src/contracts/PathScope.ts +1 -1
  102. package/node_modules/@nklisch/pi-clearance/src/contracts/PathScopeMatcherExpr.ts +1 -1
  103. package/node_modules/@nklisch/pi-clearance/src/contracts/PathScopeMatcherMode.ts +1 -1
  104. package/node_modules/@nklisch/pi-clearance/src/contracts/PathUnknownReason.ts +1 -1
  105. package/node_modules/@nklisch/pi-clearance/src/contracts/PathUsageKind.ts +1 -1
  106. package/node_modules/@nklisch/pi-clearance/src/contracts/PiBuiltinToolOperation.ts +1 -1
  107. package/node_modules/@nklisch/pi-clearance/src/contracts/PiBuiltinToolPathInput.ts +1 -1
  108. package/node_modules/@nklisch/pi-clearance/src/contracts/PiBuiltinToolShape.ts +1 -1
  109. package/node_modules/@nklisch/pi-clearance/src/contracts/PiBuiltinToolSpec.ts +1 -1
  110. package/node_modules/@nklisch/pi-clearance/src/contracts/PiFileMutationToolName.ts +1 -1
  111. package/node_modules/@nklisch/pi-clearance/src/contracts/PiToolMutationFacts.ts +1 -1
  112. package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPack.ts +1 -1
  113. package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPackDocLink.ts +1 -1
  114. package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPackExample.ts +1 -1
  115. package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPackMetadata.ts +1 -1
  116. package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyPackWarning.ts +1 -1
  117. package/node_modules/@nklisch/pi-clearance/src/contracts/PolicyRule.ts +1 -1
  118. package/node_modules/@nklisch/pi-clearance/src/contracts/ProposalNotRunReason.ts +1 -1
  119. package/node_modules/@nklisch/pi-clearance/src/contracts/ProposalNotRunSeverity.ts +1 -1
  120. package/node_modules/@nklisch/pi-clearance/src/contracts/QuoteKind.ts +1 -1
  121. package/node_modules/@nklisch/pi-clearance/src/contracts/Redirect.ts +1 -1
  122. package/node_modules/@nklisch/pi-clearance/src/contracts/RedirectStream.ts +1 -1
  123. package/node_modules/@nklisch/pi-clearance/src/contracts/RedirectTargetKind.ts +1 -1
  124. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayCorpus.ts +1 -1
  125. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDelta.ts +1 -1
  126. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaBlockedSummary.ts +1 -1
  127. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaChangedRecord.ts +1 -1
  128. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaFamily.ts +1 -1
  129. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaImprovement.ts +1 -1
  130. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaRegression.ts +1 -1
  131. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaStatus.ts +1 -1
  132. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayDeltaTransitionCount.ts +1 -1
  133. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayPathFacts.ts +1 -1
  134. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayReviewerMode.ts +1 -1
  135. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayReviewerOutcome.ts +1 -1
  136. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayStatus.ts +1 -1
  137. package/node_modules/@nklisch/pi-clearance/src/contracts/ReplayedDecision.ts +1 -1
  138. package/node_modules/@nklisch/pi-clearance/src/contracts/ShapeDiagnostic.ts +1 -1
  139. package/node_modules/@nklisch/pi-clearance/src/contracts/SourceFidelity.ts +1 -1
  140. package/node_modules/@nklisch/pi-clearance/src/contracts/SourceSpan.ts +1 -1
  141. package/node_modules/@nklisch/pi-clearance/src/contracts/Substitution.ts +1 -1
  142. package/node_modules/@nklisch/pi-clearance/src/contracts/SubstitutionKind.ts +1 -1
  143. package/node_modules/@nklisch/pi-clearance/src/contracts/ToolCallIdentity.ts +1 -1
  144. package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathAccess.ts +1 -1
  145. package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathFact.ts +1 -1
  146. package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathFactContext.ts +1 -1
  147. package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathFacts.ts +1 -1
  148. package/node_modules/@nklisch/pi-clearance/src/contracts/ToolPathUsage.ts +1 -1
  149. package/node_modules/@nklisch/pi-clearance/src/contracts/ToolShape.ts +1 -1
  150. package/node_modules/@nklisch/pi-clearance/src/contracts/UnknownPathBehavior.ts +1 -1
  151. package/node_modules/@nklisch/pi-clearance/src/contracts/UnknownToolShape.ts +1 -1
  152. package/node_modules/@nklisch/pi-clearance/src/contracts/index.ts +1 -1
  153. package/node_modules/@nklisch/pi-clearance/src/index.ts +33 -2
  154. package/node_modules/@nklisch/pi-clearance/src/native/loader.ts +29 -42
  155. package/node_modules/@nklisch/pi-clearance/src/replay/reviewer-config-proposals.ts +7 -4
  156. package/node_modules/@nklisch/pi-clearance/src/runtime/allow-request-message.ts +21 -0
  157. package/node_modules/@nklisch/pi-clearance/src/runtime/auto-reviewer-read-models.ts +165 -8
  158. package/node_modules/@nklisch/pi-clearance/src/runtime/command-registry.ts +1 -1
  159. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/allow.ts +26 -2
  160. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/packs.ts +6 -6
  161. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/scope.ts +5 -5
  162. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/actions.ts +11 -0
  163. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/dispatcher.ts +274 -1
  164. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/model-options.ts +52 -0
  165. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/native-ui.ts +54 -67
  166. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/panels/reviewer.ts +19 -3
  167. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/panels/scope.ts +2 -11
  168. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/panels.ts +10 -1
  169. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings/read-model.ts +47 -13
  170. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/settings.ts +32 -37
  171. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/status.ts +3 -0
  172. package/node_modules/@nklisch/pi-clearance/src/runtime/config-commands/types.ts +14 -5
  173. package/node_modules/@nklisch/pi-clearance/src/runtime/handler.ts +36 -0
  174. package/node_modules/@nklisch/pi-clearance/src/runtime/mode-prompt.ts +0 -1
  175. package/node_modules/@nklisch/pi-clearance/src/runtime/model-adapter.ts +5 -1
  176. package/node_modules/@nklisch/pi-clearance/src/runtime/reviewer-context.ts +73 -10
  177. package/node_modules/@nklisch/pi-clearance/src/runtime/reviewer-prompts.ts +186 -175
  178. package/node_modules/@nklisch/pi-clearance/src/runtime/reviewer.ts +26 -6
  179. package/node_modules/@nklisch/pi-plugins/dist/infrastructure/state/local-lock-filesystem.d.ts +23 -1
  180. package/node_modules/@nklisch/pi-plugins/dist/infrastructure/state/local-lock-filesystem.js +46 -50
  181. package/node_modules/@nklisch/pi-plugins/dist/infrastructure/state/local-lock-filesystem.js.map +1 -1
  182. package/node_modules/@nklisch/pi-plugins/dist/runtime/mcp/pi-mcp-adapter-package.js +2 -2
  183. package/node_modules/@nklisch/pi-plugins/dist/runtime/mcp/pi-mcp-adapter-runtime.js +2 -2
  184. package/node_modules/@nklisch/pi-plugins/dist/runtime/subagents/pi-subagents-lifecycle.js +1 -1
  185. package/node_modules/@nklisch/pi-plugins/dist/runtime/subagents/pi-subagents-package.js +2 -2
  186. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/README.md +41 -31
  187. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/dist/public.d.ts +2 -1
  188. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/FORK-MAINTENANCE.md +17 -11
  189. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/VISION.md +14 -7
  190. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/architecture.md +11 -19
  191. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/comparison-with-upstream.md +58 -53
  192. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/package.json +2 -2
  193. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/agent-type-resolution.ts +43 -0
  194. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/agent-types.ts +11 -6
  195. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/custom-agents.ts +13 -6
  196. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/default-agents.ts +0 -52
  197. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/config/thinking-levels.ts +12 -0
  198. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/handlers/interrupt.ts +5 -2
  199. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/handlers/lifecycle.ts +3 -3
  200. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/index.ts +7 -6
  201. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/create-subagent-session.ts +7 -2
  202. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/parent-snapshot.ts +11 -3
  203. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-manager.ts +26 -56
  204. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-session.ts +48 -9
  205. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-state.ts +32 -0
  206. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent.ts +105 -17
  207. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/composite-subagent-observer.ts +4 -0
  208. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/notification.ts +50 -46
  209. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/renderer.ts +1 -1
  210. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/subagent-events-observer.ts +15 -0
  211. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/runtime.ts +2 -0
  212. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/service/service-adapter.ts +35 -6
  213. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/service/service.ts +1 -0
  214. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/model-label.ts +19 -0
  215. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/prompts.ts +24 -1
  216. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/session-config.ts +11 -6
  217. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/settings.ts +70 -3
  218. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/agent-tool.ts +27 -10
  219. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/background-spawner.ts +6 -2
  220. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/foreground-runner.ts +12 -3
  221. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/get-result-report.ts +17 -3
  222. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/get-result-tool.ts +13 -20
  223. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/result-renderer.ts +6 -1
  224. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/spawn-config.ts +16 -16
  225. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/steer-tool.ts +12 -4
  226. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/types.ts +2 -2
  227. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/agent-widget.ts +24 -11
  228. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/display.ts +10 -7
  229. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/glyphs.ts +7 -0
  230. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/session-navigation.ts +34 -25
  231. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/session-navigator.ts +30 -10
  232. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/subagents-settings.ts +58 -13
  233. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/widget-renderer.ts +32 -19
  234. package/node_modules/@nklisch/pi-plugins/package.json +3 -3
  235. package/package.json +1 -1
  236. package/test/verify-bundle.mjs +28 -1
@@ -2,10 +2,12 @@ import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
2
 
3
3
  import {
4
4
  type ProjectScopeListField,
5
+ planGatedToolCommandChange,
5
6
  planModeCommandChange,
6
7
  planProjectScopeCommandChange,
7
8
  planReviewerCommandChange,
8
9
  planReviewNoteDisplayCommandChange,
10
+ type GatedToolCommandChange,
9
11
  type ReviewerCommandChange,
10
12
  type ReviewNoteDisplayCommandChange,
11
13
  type ScopeCommandChange,
@@ -15,9 +17,17 @@ import {
15
17
  type ConfigCommandApplyResult,
16
18
  type ConfigCommandPlan,
17
19
  } from "../../../config/config-command-writer.ts";
18
- import type { ClearanceMode } from "../../../config/schema.ts";
20
+ import {
21
+ CLEARANCE_MODES,
22
+ type ClearanceMode,
23
+ REVIEW_NOTE_MODES,
24
+ } from "../../../config/schema.ts";
19
25
  import type { JsonPatchOperation } from "../../../replay/proposal-schema.ts";
20
26
  import { detectReviewDecisionDisplayCapability } from "../../review-decision-display.ts";
27
+ import {
28
+ isShippedReviewerPostureId,
29
+ SHIPPED_REVIEWER_POSTURE_OPTIONS,
30
+ } from "../../reviewer-prompts.ts";
21
31
  import {
22
32
  handlePackMutationCommand,
23
33
  type PackMutationRequest,
@@ -36,6 +46,11 @@ import {
36
46
  type SettingsActionId,
37
47
  } from "./actions.ts";
38
48
  import { renderPacksOpenDrill, renderPacksShowDrill } from "./panels/packs.ts";
49
+ import {
50
+ ACTIVE_SESSION_MODEL_LABEL,
51
+ availableReviewerModels,
52
+ type ReviewerModelOption,
53
+ } from "./model-options.ts";
39
54
 
40
55
  export interface SettingsDispatchDependencies
41
56
  extends AutoReviewerCommandDependencies {}
@@ -83,6 +98,10 @@ export async function dispatchSettingsAction(
83
98
  ctx: ExtensionCommandContext,
84
99
  deps: SettingsDispatchDependencies,
85
100
  ): Promise<CommandReport<SettingsDispatchDetails | unknown>> {
101
+ const selected = await resolveSelectorAction(action, ctx, deps);
102
+ if (!selected.ok) return selected.report;
103
+ action = selected.action;
104
+
86
105
  if (isDrillAction(action.id)) {
87
106
  if (action.id === "packs.open") {
88
107
  return await renderPacksOpenDrill({ action, ctx, deps });
@@ -133,6 +152,11 @@ export async function dispatchSettingsAction(
133
152
  mode: change.mode,
134
153
  resolvedConfig: policy.policy.config,
135
154
  });
155
+ case "gated-tools":
156
+ return planGatedToolCommandChange({
157
+ change: change.change,
158
+ resolvedConfig: policy.policy.config,
159
+ });
136
160
  case "reviewer":
137
161
  return planReviewerCommandChange({
138
162
  change: change.change,
@@ -236,8 +260,217 @@ export function settingsUiRequiredReport(
236
260
  };
237
261
  }
238
262
 
263
+ async function resolveSelectorAction(
264
+ action: SettingsAction,
265
+ ctx: ExtensionCommandContext,
266
+ deps: SettingsDispatchDependencies,
267
+ ): Promise<
268
+ | { readonly ok: true; readonly action: SettingsAction }
269
+ | { readonly ok: false; readonly report: CommandReport }
270
+ > {
271
+ const isSelector =
272
+ action.id === "mode.select" ||
273
+ (action.id === "reviewer.model" && !Object.hasOwn(action.args, "model")) ||
274
+ action.id === "reviewer.posture.select" ||
275
+ action.id === "scope.preset.select" ||
276
+ action.id === "scope.unknown-path.select" ||
277
+ action.id === "briefing.mode.select" ||
278
+ (action.id === "gated-tools.add" &&
279
+ !Object.hasOwn(action.args, "toolName"));
280
+ if (!isSelector) return { ok: true, action };
281
+ if (ctx.hasUI !== true)
282
+ return { ok: false, report: settingsUiRequiredReport(action) };
283
+
284
+ const policy = await resolvePolicyReport(ctx, deps);
285
+ if (!policy.ok) return { ok: false, report: policy.report };
286
+ const reviewerModelOptions =
287
+ action.id === "reviewer.model" ? availableReviewerModels(ctx) : [];
288
+ const options = selectorOptions(
289
+ action,
290
+ deps,
291
+ reviewerModelOptions,
292
+ policy.policy.config.gatedTools ?? [],
293
+ );
294
+ if (options.length === 0) {
295
+ return {
296
+ ok: false,
297
+ report: invalidActionReport(
298
+ action,
299
+ "No choices are available in the current Pi session.",
300
+ ),
301
+ };
302
+ }
303
+
304
+ let selected: string | undefined;
305
+ try {
306
+ selected = await ctx.ui.select(selectorTitle(action), [...options]);
307
+ } catch {
308
+ selected = undefined;
309
+ }
310
+ if (selected === undefined) {
311
+ return {
312
+ ok: false,
313
+ report: {
314
+ title: "Settings selection cancelled",
315
+ summary: "No setting was selected; no config changes were written.",
316
+ markdown:
317
+ "# Settings selection cancelled\n\nNo config changes were written.",
318
+ details: { reason: "cancelled", action },
319
+ level: "warning",
320
+ },
321
+ };
322
+ }
323
+
324
+ const selectedAction = selectorSelection(
325
+ action,
326
+ selected,
327
+ reviewerModelOptions,
328
+ );
329
+ return selectedAction === undefined
330
+ ? {
331
+ ok: false,
332
+ report: invalidActionReport(action, "Unknown settings selection."),
333
+ }
334
+ : { ok: true, action: selectedAction };
335
+ }
336
+
337
+ function selectorOptions(
338
+ action: SettingsAction,
339
+ deps: SettingsDispatchDependencies,
340
+ reviewerModelOptions: readonly ReviewerModelOption[],
341
+ gatedTools: readonly string[],
342
+ ): readonly string[] {
343
+ switch (action.id) {
344
+ case "mode.select":
345
+ return CLEARANCE_MODES.map((mode) => modeLabel(mode));
346
+ case "reviewer.model":
347
+ return [
348
+ ACTIVE_SESSION_MODEL_LABEL,
349
+ ...reviewerModelOptions.map((model) => model.label),
350
+ ];
351
+ case "reviewer.posture.select":
352
+ return SHIPPED_REVIEWER_POSTURE_OPTIONS.map((option) => option.label);
353
+ case "scope.preset.select":
354
+ return ["Project only", "Home + project", "Full minus danger list"];
355
+ case "scope.unknown-path.select":
356
+ return ["Review unknown paths", "Deny unknown paths"];
357
+ case "briefing.mode.select":
358
+ return REVIEW_NOTE_MODES.map((mode) => `Note mode: ${mode}`);
359
+ case "gated-tools.add": {
360
+ const metadata = deps.toolMetadata?.();
361
+ return metadata === undefined
362
+ ? []
363
+ : activeToolNames(metadata)
364
+ .filter((name) => name !== "bash")
365
+ .filter((name) => !gatedTools.includes(name));
366
+ }
367
+ default:
368
+ return [];
369
+ }
370
+ }
371
+
372
+ function selectorTitle(action: SettingsAction): string {
373
+ switch (action.id) {
374
+ case "mode.select":
375
+ return "Choose Clearance mode";
376
+ case "reviewer.model":
377
+ return "Choose reviewer model";
378
+ case "reviewer.posture.select":
379
+ return "Choose reviewer posture";
380
+ case "scope.preset.select":
381
+ return "Choose scope preset";
382
+ case "scope.unknown-path.select":
383
+ return "Choose unknown-path behavior";
384
+ case "briefing.mode.select":
385
+ return "Choose briefing mode";
386
+ case "gated-tools.add":
387
+ return "Add exact gated non-Bash tool";
388
+ default:
389
+ return "Choose setting";
390
+ }
391
+ }
392
+
393
+ function selectorSelection(
394
+ action: SettingsAction,
395
+ selected: string,
396
+ reviewerModelOptions: readonly ReviewerModelOption[],
397
+ ): SettingsAction | undefined {
398
+ switch (action.id) {
399
+ case "mode.select": {
400
+ const mode = CLEARANCE_MODES.find(
401
+ (candidate) => selected === modeLabel(candidate),
402
+ );
403
+ return mode === undefined
404
+ ? undefined
405
+ : { id: "mode.set", args: { mode } };
406
+ }
407
+ case "reviewer.model": {
408
+ if (selected === ACTIVE_SESSION_MODEL_LABEL)
409
+ return { id: "reviewer.model", args: { model: null } };
410
+ const model = reviewerModelOptions.find(
411
+ (candidate) => candidate.label === selected,
412
+ );
413
+ return model === undefined
414
+ ? undefined
415
+ : { id: "reviewer.model", args: { model: model.spec } };
416
+ }
417
+ case "reviewer.posture.select": {
418
+ const posture = SHIPPED_REVIEWER_POSTURE_OPTIONS.find(
419
+ (option) => option.label === selected,
420
+ )?.id;
421
+ return posture === undefined
422
+ ? undefined
423
+ : { id: "reviewer.posture.set", args: { promptPosture: posture } };
424
+ }
425
+ case "scope.preset.select": {
426
+ const preset = {
427
+ "Project only": "project",
428
+ "Home + project": "home",
429
+ "Full minus danger list": "unrestricted",
430
+ }[selected];
431
+ return preset === undefined
432
+ ? undefined
433
+ : { id: "scope.preset", args: { preset } };
434
+ }
435
+ case "scope.unknown-path.select":
436
+ return selected === "Review unknown paths"
437
+ ? { id: "scope.unknown-path", args: { behavior: "review" } }
438
+ : selected === "Deny unknown paths"
439
+ ? { id: "scope.unknown-path", args: { behavior: "deny" } }
440
+ : undefined;
441
+ case "briefing.mode.select": {
442
+ const mode = selected.replace(/^Note mode: /, "");
443
+ return (REVIEW_NOTE_MODES as readonly string[]).includes(mode)
444
+ ? { id: "briefing.mode", args: { mode } }
445
+ : undefined;
446
+ }
447
+ case "gated-tools.add":
448
+ return { id: "gated-tools.add", args: { toolName: selected } };
449
+ default:
450
+ return undefined;
451
+ }
452
+ }
453
+
454
+ function modeLabel(mode: ClearanceMode): string {
455
+ return mode[0]?.toUpperCase() + mode.slice(1);
456
+ }
457
+
458
+ function activeToolNames(metadata: {
459
+ readonly activeToolNames: readonly string[];
460
+ readonly allToolNames: readonly string[];
461
+ }): readonly string[] {
462
+ return metadata.activeToolNames.length > 0
463
+ ? metadata.activeToolNames
464
+ : metadata.allToolNames;
465
+ }
466
+
239
467
  type MaterializedSettingsChange =
240
468
  | { readonly ok: true; readonly kind: "mode"; readonly mode: ClearanceMode }
469
+ | {
470
+ readonly ok: true;
471
+ readonly kind: "gated-tools";
472
+ readonly change: GatedToolCommandChange;
473
+ }
241
474
  | {
242
475
  readonly ok: true;
243
476
  readonly kind: "reviewer";
@@ -266,6 +499,41 @@ function materializeSettingsAction(
266
499
  }
267
500
  return { ok: true, kind: "mode", mode };
268
501
  }
502
+ case "gated-tools.add":
503
+ case "gated-tools.remove": {
504
+ const toolName = stringArg(action, "toolName");
505
+ if (toolName === undefined) {
506
+ return invalidArg(action, "toolName", "an exact non-Bash tool name");
507
+ }
508
+ return {
509
+ ok: true,
510
+ kind: "gated-tools",
511
+ change: {
512
+ kind: action.id === "gated-tools.add" ? "add" : "remove",
513
+ toolName,
514
+ },
515
+ };
516
+ }
517
+ case "reviewer.posture.set": {
518
+ const promptPosture = stringArg(action, "promptPosture");
519
+ if (
520
+ promptPosture === undefined ||
521
+ !isShippedReviewerPostureId(promptPosture)
522
+ ) {
523
+ return invalidArg(
524
+ action,
525
+ "promptPosture",
526
+ SHIPPED_REVIEWER_POSTURE_OPTIONS.map((option) => option.id).join(
527
+ ", ",
528
+ ),
529
+ );
530
+ }
531
+ return {
532
+ ok: true,
533
+ kind: "reviewer",
534
+ change: { kind: "prompt-posture", promptPosture },
535
+ };
536
+ }
269
537
  case "reviewer.model": {
270
538
  const model = nullableStringArg(action, "model");
271
539
  if (!model.ok) return { ok: false, reason: model.reason };
@@ -383,6 +651,11 @@ function materializeSettingsAction(
383
651
  change: { kind: "accent", enabled },
384
652
  };
385
653
  }
654
+ case "mode.select":
655
+ case "reviewer.posture.select":
656
+ case "scope.preset.select":
657
+ case "scope.unknown-path.select":
658
+ case "briefing.mode.select":
386
659
  case "reviewer.open":
387
660
  case "scope.open":
388
661
  case "packs.open":
@@ -0,0 +1,52 @@
1
+ import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
+
3
+ import type { ReviewerModelRegistry } from "../../reviewer-model.ts";
4
+
5
+ export interface ReviewerModelOption {
6
+ /** Canonical provider/modelId spec written to config. */
7
+ readonly spec: string;
8
+ /** Human-facing label shown by Pi's selector. */
9
+ readonly label: string;
10
+ }
11
+
12
+ export const ACTIVE_SESSION_MODEL_LABEL = "Use active session model" as const;
13
+ export const REVIEWER_MODEL_OPTION_LIMIT = 12;
14
+
15
+ /**
16
+ * Return the same capped, auth-filtered model catalog for both read models and
17
+ * selector dispatch. Keeping the spec beside its label avoids rebuilding a
18
+ * potentially different provider/model mapping at the point of selection.
19
+ */
20
+ export function availableReviewerModels(
21
+ ctx: ExtensionCommandContext,
22
+ ): readonly ReviewerModelOption[] {
23
+ const registry = (ctx as { readonly modelRegistry?: unknown })
24
+ .modelRegistry as ReviewerModelRegistry | undefined;
25
+ if (
26
+ registry === undefined ||
27
+ typeof registry.getAll !== "function" ||
28
+ typeof registry.hasConfiguredAuth !== "function"
29
+ ) {
30
+ return [];
31
+ }
32
+
33
+ try {
34
+ return registry
35
+ .getAll()
36
+ .filter((model) => registry.hasConfiguredAuth(model))
37
+ .map((model) => {
38
+ const spec = `${model.provider}/${model.id}`;
39
+ return {
40
+ spec,
41
+ label:
42
+ typeof model.name === "string" && model.name.length > 0
43
+ ? `${model.name} (${spec})`
44
+ : spec,
45
+ };
46
+ })
47
+ .sort((a, b) => a.spec.localeCompare(b.spec))
48
+ .slice(0, REVIEWER_MODEL_OPTION_LIMIT);
49
+ } catch {
50
+ return [];
51
+ }
52
+ }
@@ -1,7 +1,11 @@
1
1
  import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
2
  import { Key, matchesKey, truncateToWidth } from "@earendil-works/pi-tui";
3
3
 
4
- import type { ProjectScopeListField } from "../../../config/config-command-plans.ts";
4
+ import {
5
+ inferScopePreset,
6
+ SCOPE_PRESET_LABELS,
7
+ type ProjectScopeListField,
8
+ } from "../../../config/config-command-plans.ts";
5
9
  import { handleScopeCommand } from "../scope.ts";
6
10
  import type { CommandReport } from "../types.ts";
7
11
  import type { SettingsAction, SettingsActionId } from "./actions.ts";
@@ -645,6 +649,11 @@ export class SettingsNativeUiComponent {
645
649
  `Mode: ${this.model.currentMode.label} - ${this.model.currentMode.description}`,
646
650
  `Reviewer: ${this.model.status.reviewer.path} - ${this.model.status.reviewer.consequence}`,
647
651
  `Review context: ${this.model.status.reviewer.contextMode}`,
652
+ ...((this.model.status.customizations?.length ?? 0) === 0
653
+ ? []
654
+ : [
655
+ `Customizations: ${this.model.status.customizations?.join("; ") ?? ""}`,
656
+ ]),
648
657
  `Packs: ${this.model.status.packs.enabled}/${this.model.status.packs.total} enabled`,
649
658
  ];
650
659
  }
@@ -720,16 +729,11 @@ export class SettingsNativeUiComponent {
720
729
 
721
730
  function homeItems(model: SettingsReadModel): readonly NativeSettingsItem[] {
722
731
  return [
723
- ...model.modes.map((mode) => ({
724
- kind: "selection" as const,
725
- label: `Set mode: ${mode.label}`,
726
- description: mode.description,
727
- selection: {
728
- kind: "action" as const,
729
- label: `Set mode: ${mode.label}`,
730
- action: { id: "mode.set" as const, args: { mode: mode.mode } },
731
- },
732
- })),
732
+ actionItem(
733
+ `Mode: ${model.currentMode.label}`,
734
+ model.currentMode.description,
735
+ { id: "mode.select", args: {} },
736
+ ),
733
737
  ...model.panels.map((descriptor) => ({
734
738
  kind: "panel" as const,
735
739
  label: descriptor.title,
@@ -763,22 +767,36 @@ function panelItems(
763
767
  function reviewerItems(
764
768
  model: SettingsReadModel,
765
769
  ): readonly NativeSettingsItem[] {
770
+ const configuredModel = model.status.reviewer.configuredModel;
771
+ const gatedToolItems = model.gatedTools.names.map((toolName) =>
772
+ actionItem(
773
+ `Gated tool: ${toolName}`,
774
+ "Toggle this exact non-Bash tool off; Bash cannot be listed.",
775
+ { id: "gated-tools.remove", args: { toolName } },
776
+ ),
777
+ );
766
778
  return [
767
- ...model.reviewerModels.map((option) =>
768
779
  actionItem(
769
- `Use reviewer model ${option.label}`,
770
- "Pin the reviewer model; writes user-owned config after confirmation.",
771
- { id: "reviewer.model", args: { model: option.spec } },
780
+ `Reviewer model: ${configuredModel ?? "session model"}`,
781
+ "Choose a configured model or return to the active session model; writes require confirmation.",
782
+ { id: "reviewer.model", args: {} },
772
783
  ),
784
+ actionItem(
785
+ `Prompt posture: ${model.status.reviewer.promptPosture}`,
786
+ "Choose the evidence threshold used by the model reviewer; writes require confirmation.",
787
+ { id: "reviewer.posture.select", args: {} },
773
788
  ),
774
789
  actionItem(
775
- "Clear explicit reviewer model",
776
- "Fall back to the active session model for review.",
777
- { id: "reviewer.model", args: { model: null } },
790
+ `Gated non-Bash tools: ${model.gatedTools.names.length}`,
791
+ model.gatedTools.addableToolNames.length === 0
792
+ ? "No active non-Bash tools are available to add."
793
+ : "Choose an active non-Bash tool to opt into exact-name Clearance gating.",
794
+ { id: "gated-tools.add", args: {} },
778
795
  ),
796
+ ...gatedToolItems,
779
797
  actionItem(
780
798
  "Show reviewer details",
781
- "Reviewer settings are read-only except model selection.",
799
+ "Reviewer settings and current evidence thresholds.",
782
800
  { id: "reviewer.open", args: {} },
783
801
  ),
784
802
  backItem(),
@@ -786,24 +804,13 @@ function reviewerItems(
786
804
  }
787
805
 
788
806
  function scopeItems(model: SettingsReadModel): readonly NativeSettingsItem[] {
789
- const safeHomeEnabled = model.projectScope.safeHomeUseDefaults !== false;
790
- const agentSupportEnabled =
791
- model.projectScope.agentSupportUseDefaults !== false;
807
+ const safeHomeEnabled = model.projectScope.safeHomeUseDefaults;
808
+ const agentSupportEnabled = model.projectScope.agentSupportUseDefaults;
792
809
  return [
793
810
  actionItem(
794
- "Preset: Project only",
795
- "Review anything touching paths outside the project; safe-home and agent-support defaults off.",
796
- { id: "scope.preset", args: { preset: "project" } },
797
- ),
798
- actionItem(
799
- "Preset: Home + project",
800
- "Baseline read auto-approvals extend into non-secret home directories.",
801
- { id: "scope.preset", args: { preset: "home" } },
802
- ),
803
- actionItem(
804
- "Preset: Full minus danger list",
805
- "Broad home reads; credential and key paths are hard-denied.",
806
- { id: "scope.preset", args: { preset: "unrestricted" } },
811
+ `Scope preset: ${scopePresetLabel(model)}`,
812
+ "Choose one behavior bundle; path lists remain unchanged and writes require confirmation.",
813
+ { id: "scope.preset.select", args: {} },
807
814
  ),
808
815
  actionItem(
809
816
  "Show full scope details",
@@ -813,20 +820,9 @@ function scopeItems(model: SettingsReadModel): readonly NativeSettingsItem[] {
813
820
  ...scopePathItems("scope.add-path", "Add"),
814
821
  ...scopePathItems("scope.remove-path", "Remove"),
815
822
  actionItem(
816
- "Unknown paths: review",
817
- "Review ambiguous paths instead of denying immediately.",
818
- {
819
- id: "scope.unknown-path",
820
- args: { behavior: "review" },
821
- },
822
- ),
823
- actionItem(
824
- "Unknown paths: deny",
825
- "Deny ambiguous paths unless policy can prove safety.",
826
- {
827
- id: "scope.unknown-path",
828
- args: { behavior: "deny" },
829
- },
823
+ `Unknown paths: ${model.projectScope.unknownPathBehavior}`,
824
+ "Choose whether ambiguous paths review or deny; writes require confirmation.",
825
+ { id: "scope.unknown-path.select", args: {} },
830
826
  ),
831
827
  actionItem(
832
828
  safeHomeEnabled ? "Safe-home defaults: off" : "Safe-home defaults: on",
@@ -888,30 +884,21 @@ export function packItems(
888
884
  ];
889
885
  }
890
886
 
887
+ function scopePresetLabel(model: SettingsReadModel): string {
888
+ const scope = model.projectScope;
889
+ const preset = inferScopePreset(scope);
890
+ return preset === "custom" ? "Custom" : SCOPE_PRESET_LABELS[preset];
891
+ }
892
+
891
893
  function briefingItems(
892
894
  model: SettingsReadModel,
893
895
  ): readonly NativeSettingsItem[] {
894
896
  const briefing = model.briefing;
895
897
  return [
896
898
  actionItem(
897
- `Note text: reason + accent${briefing.mode === "reason+accent" ? " (current)" : ""}`,
898
- "Show the decision reason inline after each reviewed call.",
899
- { id: "briefing.mode", args: { mode: "reason+accent" } },
900
- ),
901
- actionItem(
902
- `Note text: accent only${briefing.mode === "accent-only" ? " (current)" : ""}`,
903
- "Quiet allows: no reason text, accent marker only.",
904
- { id: "briefing.mode", args: { mode: "accent-only" } },
905
- ),
906
- actionItem(
907
- `Note text: reason + model${briefing.mode === "reason+model" ? " (current)" : ""}`,
908
- "Show the decision reason and the reviewer model label.",
909
- { id: "briefing.mode", args: { mode: "reason+model" } },
910
- ),
911
- actionItem(
912
- `Note text: off${briefing.mode === "off" ? " (current)" : ""}`,
913
- "Hide review-note text entirely.",
914
- { id: "briefing.mode", args: { mode: "off" } },
899
+ `Note mode: ${briefing.mode}`,
900
+ "Choose the inline review-note mode; writes require confirmation.",
901
+ { id: "briefing.mode.select", args: {} },
915
902
  ),
916
903
  actionItem(
917
904
  briefing.showModelLabel ? "Model label: hide" : "Model label: show",
@@ -5,7 +5,14 @@ export const REVIEWER_PANEL: SettingsPanel = {
5
5
  id: "reviewer",
6
6
  title: "Reviewer",
7
7
  rows: reviewerRows,
8
- actions: ["reviewer.model", "reviewer.open"],
8
+ actions: [
9
+ "reviewer.model",
10
+ "reviewer.posture.select",
11
+ "reviewer.posture.set",
12
+ "gated-tools.add",
13
+ "gated-tools.remove",
14
+ "reviewer.open",
15
+ ],
9
16
  };
10
17
 
11
18
  export function reviewerRows(model: SettingsReadModel): readonly SettingsRow[] {
@@ -33,7 +40,7 @@ export function reviewerRows(model: SettingsReadModel): readonly SettingsRow[] {
33
40
  {
34
41
  label: "Prompt posture",
35
42
  value: reviewer.promptPosture,
36
- meaning: "Edit advanced reviewer settings in global.json.",
43
+ meaning: "Select a posture; writes global.json after confirmation.",
37
44
  },
38
45
  {
39
46
  label: "Context mode",
@@ -42,6 +49,15 @@ export function reviewerRows(model: SettingsReadModel): readonly SettingsRow[] {
42
49
  },
43
50
  { label: "Token budget", value: formatTokenBudget(reviewer.tokenBudget) },
44
51
  { label: "Escalation", value: formatEscalation(reviewer.escalation) },
52
+ {
53
+ label: "Gated non-Bash tools",
54
+ value:
55
+ model.gatedTools.names.length === 0
56
+ ? "none"
57
+ : `${model.gatedTools.names.length} configured`,
58
+ meaning:
59
+ "Only exact names shown in this control are analyzed by Clearance; Bash remains gated and cannot be listed.",
60
+ },
45
61
  ];
46
62
  }
47
63
 
@@ -51,7 +67,7 @@ export function renderReviewerPanel(model: SettingsReadModel): string {
51
67
  "",
52
68
  markdownTable(reviewerRows(model)),
53
69
  "",
54
- "Model selection is interactive. Other reviewer settings are read-only here; edit global.json.",
70
+ "Model and prompt-posture selection are interactive and confirm-backed. Other reviewer settings are read-only here; edit global.json.",
55
71
  ].join("\n");
56
72
  }
57
73
 
@@ -5,7 +5,6 @@ import {
5
5
  type ProjectScopeListField,
6
6
  SCOPE_PRESET_LABELS,
7
7
  } from "../../../../config/config-command-plans.ts";
8
- import type { ProjectScopeConfig } from "../../../../config/schema.ts";
9
8
  import type { CommandReport } from "../../types.ts";
10
9
  import type { SettingsAction } from "../actions.ts";
11
10
  import {
@@ -84,15 +83,7 @@ export const SCOPE_PANEL: SettingsPanel = {
84
83
 
85
84
  export function scopeRows(model: SettingsReadModel): readonly SettingsRow[] {
86
85
  const scope = model.projectScope;
87
- const preset = inferScopePreset({
88
- safeHomeUseDefaults: scope.safeHomeUseDefaults ?? true,
89
- ...(scope.agentSupportUseDefaults === undefined
90
- ? {}
91
- : { agentSupportUseDefaults: scope.agentSupportUseDefaults }),
92
- homePathBehavior: scope.homePathBehavior,
93
- sensitivePathBehavior: scope.sensitivePathBehavior,
94
- unknownPathBehavior: scope.unknownPathBehavior,
95
- } as ProjectScopeConfig);
86
+ const preset = inferScopePreset(scope);
96
87
 
97
88
  return [
98
89
  {
@@ -308,5 +299,5 @@ function markdownTable(rows: readonly SettingsRow[]): string {
308
299
  }
309
300
 
310
301
  function escapeCell(value: string): string {
311
- return value.replaceAll("|", "\\|").replaceAll("\n", "<br>");
302
+ return value.replaceAll("|", "\\|").replaceAll("\n", "; ");
312
303
  }
@@ -30,12 +30,21 @@ export const SETTINGS_PANELS = [
30
30
  ] as const satisfies readonly SettingsPanel[];
31
31
 
32
32
  export function renderControlCenter(model: SettingsReadModel): string {
33
- const rows: readonly SettingsRow[] = [
33
+ const rows: SettingsRow[] = [
34
34
  {
35
35
  label: "Clearance mode",
36
36
  value: model.currentMode.label,
37
37
  meaning: model.currentMode.description,
38
38
  },
39
+ ...(model.status.customizations === undefined ||
40
+ model.status.customizations.length === 0
41
+ ? []
42
+ : [
43
+ {
44
+ label: "Customizations",
45
+ value: model.status.customizations.join("; "),
46
+ },
47
+ ]),
39
48
  {
40
49
  label: "Tune mode",
41
50
  value: formatTuneCueStatus(model.status.ratchet.active),