@yohakuforce/core 0.4.0
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/README.md +65 -0
- package/dist/adapters/dx-mcp/dx-mcp-source-adapter.d.ts +25 -0
- package/dist/adapters/dx-mcp/dx-mcp-source-adapter.d.ts.map +1 -0
- package/dist/adapters/dx-mcp/dx-mcp-source-adapter.js +45 -0
- package/dist/adapters/dx-mcp/dx-mcp-source-adapter.js.map +1 -0
- package/dist/adapters/dx-mcp/index.d.ts +3 -0
- package/dist/adapters/dx-mcp/index.d.ts.map +1 -0
- package/dist/adapters/dx-mcp/index.js +2 -0
- package/dist/adapters/dx-mcp/index.js.map +1 -0
- package/dist/adapters/local/index.d.ts +5 -0
- package/dist/adapters/local/index.d.ts.map +1 -0
- package/dist/adapters/local/index.js +3 -0
- package/dist/adapters/local/index.js.map +1 -0
- package/dist/adapters/local/local-source-adapter.d.ts +19 -0
- package/dist/adapters/local/local-source-adapter.d.ts.map +1 -0
- package/dist/adapters/local/local-source-adapter.js +214 -0
- package/dist/adapters/local/local-source-adapter.js.map +1 -0
- package/dist/adapters/local/sfdx-project.d.ts +14 -0
- package/dist/adapters/local/sfdx-project.d.ts.map +1 -0
- package/dist/adapters/local/sfdx-project.js +76 -0
- package/dist/adapters/local/sfdx-project.js.map +1 -0
- package/dist/change-summary/index.d.ts +4 -0
- package/dist/change-summary/index.d.ts.map +1 -0
- package/dist/change-summary/index.js +3 -0
- package/dist/change-summary/index.js.map +1 -0
- package/dist/change-summary/schema.json +152 -0
- package/dist/change-summary/types.d.ts +52 -0
- package/dist/change-summary/types.d.ts.map +1 -0
- package/dist/change-summary/types.js +18 -0
- package/dist/change-summary/types.js.map +1 -0
- package/dist/change-summary/validate.d.ts +8 -0
- package/dist/change-summary/validate.d.ts.map +1 -0
- package/dist/change-summary/validate.js +35 -0
- package/dist/change-summary/validate.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +945 -0
- package/dist/cli.js.map +1 -0
- package/dist/consistency/check.d.ts +4 -0
- package/dist/consistency/check.d.ts.map +1 -0
- package/dist/consistency/check.js +70 -0
- package/dist/consistency/check.js.map +1 -0
- package/dist/consistency/index.d.ts +4 -0
- package/dist/consistency/index.d.ts.map +1 -0
- package/dist/consistency/index.js +3 -0
- package/dist/consistency/index.js.map +1 -0
- package/dist/consistency/types.d.ts +29 -0
- package/dist/consistency/types.d.ts.map +1 -0
- package/dist/consistency/types.js +12 -0
- package/dist/consistency/types.js.map +1 -0
- package/dist/diff/classify-files.d.ts +9 -0
- package/dist/diff/classify-files.d.ts.map +1 -0
- package/dist/diff/classify-files.js +105 -0
- package/dist/diff/classify-files.js.map +1 -0
- package/dist/diff/diff.d.ts +11 -0
- package/dist/diff/diff.d.ts.map +1 -0
- package/dist/diff/diff.js +69 -0
- package/dist/diff/diff.js.map +1 -0
- package/dist/diff/git.d.ts +28 -0
- package/dist/diff/git.d.ts.map +1 -0
- package/dist/diff/git.js +115 -0
- package/dist/diff/git.js.map +1 -0
- package/dist/diff/index.d.ts +7 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +5 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/diff/types.d.ts +28 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +4 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/explain/block-registry.d.ts +17 -0
- package/dist/explain/block-registry.d.ts.map +1 -0
- package/dist/explain/block-registry.js +73 -0
- package/dist/explain/block-registry.js.map +1 -0
- package/dist/explain/index.d.ts +22 -0
- package/dist/explain/index.d.ts.map +1 -0
- package/dist/explain/index.js +128 -0
- package/dist/explain/index.js.map +1 -0
- package/dist/graph/builder.d.ts +9 -0
- package/dist/graph/builder.d.ts.map +1 -0
- package/dist/graph/builder.js +276 -0
- package/dist/graph/builder.js.map +1 -0
- package/dist/graph/dependencies.d.ts +5 -0
- package/dist/graph/dependencies.d.ts.map +1 -0
- package/dist/graph/dependencies.js +38 -0
- package/dist/graph/dependencies.js.map +1 -0
- package/dist/graph/extractors/apex-body.d.ts +5 -0
- package/dist/graph/extractors/apex-body.d.ts.map +1 -0
- package/dist/graph/extractors/apex-body.js +289 -0
- package/dist/graph/extractors/apex-body.js.map +1 -0
- package/dist/graph/extractors/apex-class.d.ts +5 -0
- package/dist/graph/extractors/apex-class.d.ts.map +1 -0
- package/dist/graph/extractors/apex-class.js +43 -0
- package/dist/graph/extractors/apex-class.js.map +1 -0
- package/dist/graph/extractors/apex-control-flow.d.ts +33 -0
- package/dist/graph/extractors/apex-control-flow.d.ts.map +1 -0
- package/dist/graph/extractors/apex-control-flow.js +432 -0
- package/dist/graph/extractors/apex-control-flow.js.map +1 -0
- package/dist/graph/extractors/apex-trigger.d.ts +4 -0
- package/dist/graph/extractors/apex-trigger.d.ts.map +1 -0
- package/dist/graph/extractors/apex-trigger.js +40 -0
- package/dist/graph/extractors/apex-trigger.js.map +1 -0
- package/dist/graph/extractors/approval-process.d.ts +4 -0
- package/dist/graph/extractors/approval-process.d.ts.map +1 -0
- package/dist/graph/extractors/approval-process.js +103 -0
- package/dist/graph/extractors/approval-process.js.map +1 -0
- package/dist/graph/extractors/aura-bundle.d.ts +4 -0
- package/dist/graph/extractors/aura-bundle.d.ts.map +1 -0
- package/dist/graph/extractors/aura-bundle.js +77 -0
- package/dist/graph/extractors/aura-bundle.js.map +1 -0
- package/dist/graph/extractors/custom-application.d.ts +4 -0
- package/dist/graph/extractors/custom-application.d.ts.map +1 -0
- package/dist/graph/extractors/custom-application.js +55 -0
- package/dist/graph/extractors/custom-application.js.map +1 -0
- package/dist/graph/extractors/custom-metadata-record.d.ts +4 -0
- package/dist/graph/extractors/custom-metadata-record.d.ts.map +1 -0
- package/dist/graph/extractors/custom-metadata-record.js +53 -0
- package/dist/graph/extractors/custom-metadata-record.js.map +1 -0
- package/dist/graph/extractors/field.d.ts +4 -0
- package/dist/graph/extractors/field.d.ts.map +1 -0
- package/dist/graph/extractors/field.js +36 -0
- package/dist/graph/extractors/field.js.map +1 -0
- package/dist/graph/extractors/flexi-page.d.ts +4 -0
- package/dist/graph/extractors/flexi-page.d.ts.map +1 -0
- package/dist/graph/extractors/flexi-page.js +46 -0
- package/dist/graph/extractors/flexi-page.js.map +1 -0
- package/dist/graph/extractors/flow-body.d.ts +3 -0
- package/dist/graph/extractors/flow-body.d.ts.map +1 -0
- package/dist/graph/extractors/flow-body.js +144 -0
- package/dist/graph/extractors/flow-body.js.map +1 -0
- package/dist/graph/extractors/flow.d.ts +4 -0
- package/dist/graph/extractors/flow.d.ts.map +1 -0
- package/dist/graph/extractors/flow.js +20 -0
- package/dist/graph/extractors/flow.js.map +1 -0
- package/dist/graph/extractors/index.d.ts +24 -0
- package/dist/graph/extractors/index.d.ts.map +1 -0
- package/dist/graph/extractors/index.js +23 -0
- package/dist/graph/extractors/index.js.map +1 -0
- package/dist/graph/extractors/layout.d.ts +4 -0
- package/dist/graph/extractors/layout.d.ts.map +1 -0
- package/dist/graph/extractors/layout.js +89 -0
- package/dist/graph/extractors/layout.js.map +1 -0
- package/dist/graph/extractors/lwc.d.ts +4 -0
- package/dist/graph/extractors/lwc.d.ts.map +1 -0
- package/dist/graph/extractors/lwc.js +170 -0
- package/dist/graph/extractors/lwc.js.map +1 -0
- package/dist/graph/extractors/named-credential.d.ts +9 -0
- package/dist/graph/extractors/named-credential.d.ts.map +1 -0
- package/dist/graph/extractors/named-credential.js +38 -0
- package/dist/graph/extractors/named-credential.js.map +1 -0
- package/dist/graph/extractors/object.d.ts +4 -0
- package/dist/graph/extractors/object.d.ts.map +1 -0
- package/dist/graph/extractors/object.js +16 -0
- package/dist/graph/extractors/object.js.map +1 -0
- package/dist/graph/extractors/permission-set-body.d.ts +3 -0
- package/dist/graph/extractors/permission-set-body.d.ts.map +1 -0
- package/dist/graph/extractors/permission-set-body.js +80 -0
- package/dist/graph/extractors/permission-set-body.js.map +1 -0
- package/dist/graph/extractors/permission-set.d.ts +4 -0
- package/dist/graph/extractors/permission-set.d.ts.map +1 -0
- package/dist/graph/extractors/permission-set.js +17 -0
- package/dist/graph/extractors/permission-set.js.map +1 -0
- package/dist/graph/extractors/profile.d.ts +4 -0
- package/dist/graph/extractors/profile.d.ts.map +1 -0
- package/dist/graph/extractors/profile.js +15 -0
- package/dist/graph/extractors/profile.js.map +1 -0
- package/dist/graph/extractors/record-type.d.ts +4 -0
- package/dist/graph/extractors/record-type.d.ts.map +1 -0
- package/dist/graph/extractors/record-type.js +19 -0
- package/dist/graph/extractors/record-type.js.map +1 -0
- package/dist/graph/extractors/remote-site-setting.d.ts +4 -0
- package/dist/graph/extractors/remote-site-setting.d.ts.map +1 -0
- package/dist/graph/extractors/remote-site-setting.js +15 -0
- package/dist/graph/extractors/remote-site-setting.js.map +1 -0
- package/dist/graph/extractors/sharing-rules.d.ts +8 -0
- package/dist/graph/extractors/sharing-rules.d.ts.map +1 -0
- package/dist/graph/extractors/sharing-rules.js +122 -0
- package/dist/graph/extractors/sharing-rules.js.map +1 -0
- package/dist/graph/extractors/types.d.ts +8 -0
- package/dist/graph/extractors/types.d.ts.map +1 -0
- package/dist/graph/extractors/types.js +2 -0
- package/dist/graph/extractors/types.js.map +1 -0
- package/dist/graph/extractors/validation-rule.d.ts +4 -0
- package/dist/graph/extractors/validation-rule.d.ts.map +1 -0
- package/dist/graph/extractors/validation-rule.js +19 -0
- package/dist/graph/extractors/validation-rule.js.map +1 -0
- package/dist/graph/extractors/visualforce-component.d.ts +4 -0
- package/dist/graph/extractors/visualforce-component.d.ts.map +1 -0
- package/dist/graph/extractors/visualforce-component.js +90 -0
- package/dist/graph/extractors/visualforce-component.js.map +1 -0
- package/dist/graph/extractors/visualforce-page.d.ts +4 -0
- package/dist/graph/extractors/visualforce-page.d.ts.map +1 -0
- package/dist/graph/extractors/visualforce-page.js +92 -0
- package/dist/graph/extractors/visualforce-page.js.map +1 -0
- package/dist/graph/index.d.ts +8 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +5 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/parse-xml.d.ts +5 -0
- package/dist/graph/parse-xml.d.ts.map +1 -0
- package/dist/graph/parse-xml.js +39 -0
- package/dist/graph/parse-xml.js.map +1 -0
- package/dist/graph/sqlite-reader.d.ts +33 -0
- package/dist/graph/sqlite-reader.d.ts.map +1 -0
- package/dist/graph/sqlite-reader.js +445 -0
- package/dist/graph/sqlite-reader.js.map +1 -0
- package/dist/graph/sqlite-store.d.ts +78 -0
- package/dist/graph/sqlite-store.d.ts.map +1 -0
- package/dist/graph/sqlite-store.js +683 -0
- package/dist/graph/sqlite-store.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/init/index.d.ts +4 -0
- package/dist/init/index.d.ts.map +1 -0
- package/dist/init/index.js +3 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/init.d.ts +9 -0
- package/dist/init/init.d.ts.map +1 -0
- package/dist/init/init.js +92 -0
- package/dist/init/init.js.map +1 -0
- package/dist/init/types.d.ts +37 -0
- package/dist/init/types.d.ts.map +1 -0
- package/dist/init/types.js +59 -0
- package/dist/init/types.js.map +1 -0
- package/dist/merge/index.d.ts +6 -0
- package/dist/merge/index.d.ts.map +1 -0
- package/dist/merge/index.js +5 -0
- package/dist/merge/index.js.map +1 -0
- package/dist/merge/markers.d.ts +8 -0
- package/dist/merge/markers.d.ts.map +1 -0
- package/dist/merge/markers.js +30 -0
- package/dist/merge/markers.js.map +1 -0
- package/dist/merge/merge.d.ts +12 -0
- package/dist/merge/merge.d.ts.map +1 -0
- package/dist/merge/merge.js +116 -0
- package/dist/merge/merge.js.map +1 -0
- package/dist/merge/parser.d.ts +5 -0
- package/dist/merge/parser.d.ts.map +1 -0
- package/dist/merge/parser.js +63 -0
- package/dist/merge/parser.js.map +1 -0
- package/dist/merge/validator.d.ts +15 -0
- package/dist/merge/validator.d.ts.map +1 -0
- package/dist/merge/validator.js +64 -0
- package/dist/merge/validator.js.map +1 -0
- package/dist/metrics/aggregate.d.ts +11 -0
- package/dist/metrics/aggregate.d.ts.map +1 -0
- package/dist/metrics/aggregate.js +51 -0
- package/dist/metrics/aggregate.js.map +1 -0
- package/dist/metrics/index.d.ts +7 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +4 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/store.d.ts +19 -0
- package/dist/metrics/store.d.ts.map +1 -0
- package/dist/metrics/store.js +69 -0
- package/dist/metrics/store.js.map +1 -0
- package/dist/metrics/types.d.ts +32 -0
- package/dist/metrics/types.d.ts.map +1 -0
- package/dist/metrics/types.js +38 -0
- package/dist/metrics/types.js.map +1 -0
- package/dist/onboarding/context-map.d.ts +15 -0
- package/dist/onboarding/context-map.d.ts.map +1 -0
- package/dist/onboarding/context-map.js +138 -0
- package/dist/onboarding/context-map.js.map +1 -0
- package/dist/onboarding/faq.d.ts +24 -0
- package/dist/onboarding/faq.d.ts.map +1 -0
- package/dist/onboarding/faq.js +127 -0
- package/dist/onboarding/faq.js.map +1 -0
- package/dist/onboarding/index.d.ts +9 -0
- package/dist/onboarding/index.d.ts.map +1 -0
- package/dist/onboarding/index.js +5 -0
- package/dist/onboarding/index.js.map +1 -0
- package/dist/onboarding/state.d.ts +15 -0
- package/dist/onboarding/state.d.ts.map +1 -0
- package/dist/onboarding/state.js +92 -0
- package/dist/onboarding/state.js.map +1 -0
- package/dist/onboarding/types.d.ts +38 -0
- package/dist/onboarding/types.d.ts.map +1 -0
- package/dist/onboarding/types.js +13 -0
- package/dist/onboarding/types.js.map +1 -0
- package/dist/release/extract-manual-steps.d.ts +16 -0
- package/dist/release/extract-manual-steps.d.ts.map +1 -0
- package/dist/release/extract-manual-steps.js +164 -0
- package/dist/release/extract-manual-steps.js.map +1 -0
- package/dist/release/index.d.ts +4 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +3 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/schema.json +142 -0
- package/dist/release/types.d.ts +39 -0
- package/dist/release/types.d.ts.map +1 -0
- package/dist/release/types.js +4 -0
- package/dist/release/types.js.map +1 -0
- package/dist/release/validate.d.ts +8 -0
- package/dist/release/validate.d.ts.map +1 -0
- package/dist/release/validate.js +35 -0
- package/dist/release/validate.js.map +1 -0
- package/dist/render/approval-mermaid.d.ts +3 -0
- package/dist/render/approval-mermaid.d.ts.map +1 -0
- package/dist/render/approval-mermaid.js +69 -0
- package/dist/render/approval-mermaid.js.map +1 -0
- package/dist/render/archive.d.ts +2 -0
- package/dist/render/archive.d.ts.map +1 -0
- package/dist/render/archive.js +32 -0
- package/dist/render/archive.js.map +1 -0
- package/dist/render/concerns.d.ts +11 -0
- package/dist/render/concerns.d.ts.map +1 -0
- package/dist/render/concerns.js +83 -0
- package/dist/render/concerns.js.map +1 -0
- package/dist/render/er-diagram.d.ts +3 -0
- package/dist/render/er-diagram.d.ts.map +1 -0
- package/dist/render/er-diagram.js +79 -0
- package/dist/render/er-diagram.js.map +1 -0
- package/dist/render/eta-engine.d.ts +2 -0
- package/dist/render/eta-engine.d.ts.map +1 -0
- package/dist/render/eta-engine.js +39 -0
- package/dist/render/eta-engine.js.map +1 -0
- package/dist/render/flow-flowchart.d.ts +4 -0
- package/dist/render/flow-flowchart.d.ts.map +1 -0
- package/dist/render/flow-flowchart.js +59 -0
- package/dist/render/flow-flowchart.js.map +1 -0
- package/dist/render/flow-sequence-table.d.ts +11 -0
- package/dist/render/flow-sequence-table.d.ts.map +1 -0
- package/dist/render/flow-sequence-table.js +88 -0
- package/dist/render/flow-sequence-table.js.map +1 -0
- package/dist/render/formula.d.ts +33 -0
- package/dist/render/formula.d.ts.map +1 -0
- package/dist/render/formula.js +381 -0
- package/dist/render/formula.js.map +1 -0
- package/dist/render/index.d.ts +6 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +5 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/intra-class-call-graph.d.ts +3 -0
- package/dist/render/intra-class-call-graph.d.ts.map +1 -0
- package/dist/render/intra-class-call-graph.js +32 -0
- package/dist/render/intra-class-call-graph.js.map +1 -0
- package/dist/render/mermaid.d.ts +6 -0
- package/dist/render/mermaid.d.ts.map +1 -0
- package/dist/render/mermaid.js +99 -0
- package/dist/render/mermaid.js.map +1 -0
- package/dist/render/method-flowchart.d.ts +15 -0
- package/dist/render/method-flowchart.d.ts.map +1 -0
- package/dist/render/method-flowchart.js +232 -0
- package/dist/render/method-flowchart.js.map +1 -0
- package/dist/render/method-summary-table.d.ts +17 -0
- package/dist/render/method-summary-table.d.ts.map +1 -0
- package/dist/render/method-summary-table.js +189 -0
- package/dist/render/method-summary-table.js.map +1 -0
- package/dist/render/render.d.ts +37 -0
- package/dist/render/render.d.ts.map +1 -0
- package/dist/render/render.js +491 -0
- package/dist/render/render.js.map +1 -0
- package/dist/render/summary.d.ts +21 -0
- package/dist/render/summary.d.ts.map +1 -0
- package/dist/render/summary.js +542 -0
- package/dist/render/summary.js.map +1 -0
- package/dist/render/templates/apex-class.eta +204 -0
- package/dist/render/templates/apex-trigger.eta +143 -0
- package/dist/render/templates/approval-process.eta +118 -0
- package/dist/render/templates/aura-bundle.eta +47 -0
- package/dist/render/templates/custom-application.eta +44 -0
- package/dist/render/templates/custom-metadata-record.eta +37 -0
- package/dist/render/templates/executive-risks.eta +56 -0
- package/dist/render/templates/executive-summary.eta +68 -0
- package/dist/render/templates/flexi-page.eta +47 -0
- package/dist/render/templates/flow.eta +166 -0
- package/dist/render/templates/layout.eta +68 -0
- package/dist/render/templates/lwc.eta +118 -0
- package/dist/render/templates/named-credential.eta +30 -0
- package/dist/render/templates/object.eta +68 -0
- package/dist/render/templates/permission-set.eta +80 -0
- package/dist/render/templates/profile.eta +78 -0
- package/dist/render/templates/record-type.eta +23 -0
- package/dist/render/templates/remote-site-setting.eta +23 -0
- package/dist/render/templates/sharing-rule.eta +50 -0
- package/dist/render/templates/system-index.eta +52 -0
- package/dist/render/templates/system-overview.eta +37 -0
- package/dist/render/templates/validation-rule.eta +55 -0
- package/dist/render/templates/visualforce-component.eta +52 -0
- package/dist/render/templates/visualforce-page.eta +76 -0
- package/dist/render/trigger-processing-summary.d.ts +12 -0
- package/dist/render/trigger-processing-summary.d.ts.map +1 -0
- package/dist/render/trigger-processing-summary.js +94 -0
- package/dist/render/trigger-processing-summary.js.map +1 -0
- package/dist/sarif/index.d.ts +3 -0
- package/dist/sarif/index.d.ts.map +1 -0
- package/dist/sarif/index.js +2 -0
- package/dist/sarif/index.js.map +1 -0
- package/dist/sarif/parse.d.ts +7 -0
- package/dist/sarif/parse.d.ts.map +1 -0
- package/dist/sarif/parse.js +55 -0
- package/dist/sarif/parse.js.map +1 -0
- package/dist/sarif/types.d.ts +43 -0
- package/dist/sarif/types.d.ts.map +1 -0
- package/dist/sarif/types.js +4 -0
- package/dist/sarif/types.js.map +1 -0
- package/dist/scaffold/.agents/README.md +12 -0
- package/dist/scaffold/.agents/knowledge/INDEX.md +52 -0
- package/dist/scaffold/.agents/knowledge/README.md +29 -0
- package/dist/scaffold/.agents/knowledge/decisions/.gitkeep +0 -0
- package/dist/scaffold/.agents/knowledge/improvements/.gitkeep +0 -0
- package/dist/scaffold/.agents/knowledge/pitfalls/.gitkeep +0 -0
- package/dist/scaffold/.agents/knowledge/retrospectives/.gitkeep +0 -0
- package/dist/scaffold/.agents/knowledge/wins/.gitkeep +0 -0
- package/dist/scaffold/.agents/templates/.gitkeep +0 -0
- package/dist/scaffold/.agents/templates/README.md +19 -0
- package/dist/scaffold/.agents/templates/decision.md +39 -0
- package/dist/scaffold/.agents/templates/improvement.md +33 -0
- package/dist/scaffold/.agents/templates/pitfall.md +33 -0
- package/dist/scaffold/.agents/templates/retrospective.md +61 -0
- package/dist/scaffold/.agents/templates/win.md +28 -0
- package/dist/scaffold/.claude/README.md +11 -0
- package/dist/scaffold/.claude/agents/.gitkeep +0 -0
- package/dist/scaffold/.claude/agents/apex-query-tracer.md.eta +199 -0
- package/dist/scaffold/.claude/agents/automation-classifier.md.eta +39 -0
- package/dist/scaffold/.claude/agents/batch-calculator.md.eta +209 -0
- package/dist/scaffold/.claude/agents/cascade-tracer.md.eta +139 -0
- package/dist/scaffold/.claude/agents/customer-impact-explainer.md.eta +96 -0
- package/dist/scaffold/.claude/agents/data-model-classifier.md.eta +84 -0
- package/dist/scaffold/.claude/agents/explain-writer.md.eta +104 -0
- package/dist/scaffold/.claude/agents/flow-query-tracer.md.eta +211 -0
- package/dist/scaffold/.claude/agents/graph-querier.md.eta +47 -0
- package/dist/scaffold/.claude/agents/logic-classifier.md.eta +36 -0
- package/dist/scaffold/.claude/agents/manual-step-extractor.md.eta +72 -0
- package/dist/scaffold/.claude/agents/object-documenter.md.eta +66 -0
- package/dist/scaffold/.claude/agents/onboarding-guide.md.eta +77 -0
- package/dist/scaffold/.claude/agents/permission-classifier.md.eta +32 -0
- package/dist/scaffold/.claude/agents/release-advisor.md.eta +96 -0
- package/dist/scaffold/.claude/agents/release-composer.md.eta +106 -0
- package/dist/scaffold/.claude/agents/review-assistant.md.eta +72 -0
- package/dist/scaffold/.claude/agents/rollback-drafter.md.eta +95 -0
- package/dist/scaffold/.claude/agents/ui-classifier.md.eta +31 -0
- package/dist/scaffold/.claude/commands/.gitkeep +0 -0
- package/dist/scaffold/.claude/commands/analyze-batch-limits.md.eta +309 -0
- package/dist/scaffold/.claude/commands/change-summary.md.eta +79 -0
- package/dist/scaffold/.claude/commands/classify-diff.md.eta +107 -0
- package/dist/scaffold/.claude/commands/explain.md.eta +63 -0
- package/dist/scaffold/.claude/commands/impact.md.eta +67 -0
- package/dist/scaffold/.claude/commands/manual-steps.md.eta +62 -0
- package/dist/scaffold/.claude/commands/onboard.md.eta +107 -0
- package/dist/scaffold/.claude/commands/release-prep.md.eta +147 -0
- package/dist/scaffold/.claude/commands/yohaku-explain.md.eta +81 -0
- package/dist/scaffold/.claude/settings.json.eta +59 -0
- package/dist/scaffold/.yohaku/context-map.yaml.eta +56 -0
- package/dist/scaffold/.yohaku/secrets-rules.yaml.eta +44 -0
- package/dist/scaffold/AGENTS.md.eta +147 -0
- package/dist/scaffold/CLAUDE.md.eta +121 -0
- package/dist/scaffold/README.md +37 -0
- package/dist/schema/graph.schema.json +446 -0
- package/dist/schema/validate.d.ts +8 -0
- package/dist/schema/validate.d.ts.map +1 -0
- package/dist/schema/validate.js +49 -0
- package/dist/schema/validate.js.map +1 -0
- package/dist/secrets/apply.d.ts +17 -0
- package/dist/secrets/apply.d.ts.map +1 -0
- package/dist/secrets/apply.js +44 -0
- package/dist/secrets/apply.js.map +1 -0
- package/dist/secrets/index.d.ts +7 -0
- package/dist/secrets/index.d.ts.map +1 -0
- package/dist/secrets/index.js +4 -0
- package/dist/secrets/index.js.map +1 -0
- package/dist/secrets/load.d.ts +16 -0
- package/dist/secrets/load.d.ts.map +1 -0
- package/dist/secrets/load.js +136 -0
- package/dist/secrets/load.js.map +1 -0
- package/dist/secrets/mask.d.ts +15 -0
- package/dist/secrets/mask.d.ts.map +1 -0
- package/dist/secrets/mask.js +34 -0
- package/dist/secrets/mask.js.map +1 -0
- package/dist/secrets/rules.d.ts +10 -0
- package/dist/secrets/rules.d.ts.map +1 -0
- package/dist/secrets/rules.js +47 -0
- package/dist/secrets/rules.js.map +1 -0
- package/dist/types/graph.d.ts +508 -0
- package/dist/types/graph.d.ts.map +1 -0
- package/dist/types/graph.js +9 -0
- package/dist/types/graph.js.map +1 -0
- package/dist/types/render.d.ts +26 -0
- package/dist/types/render.d.ts.map +1 -0
- package/dist/types/render.js +10 -0
- package/dist/types/render.js.map +1 -0
- package/dist/types/source-adapter.d.ts +26 -0
- package/dist/types/source-adapter.d.ts.map +1 -0
- package/dist/types/source-adapter.js +11 -0
- package/dist/types/source-adapter.js.map +1 -0
- package/dist/util/build-lock.d.ts +35 -0
- package/dist/util/build-lock.d.ts.map +1 -0
- package/dist/util/build-lock.js +72 -0
- package/dist/util/build-lock.js.map +1 -0
- package/dist/util/hash.d.ts +3 -0
- package/dist/util/hash.d.ts.map +1 -0
- package/dist/util/hash.js +13 -0
- package/dist/util/hash.js.map +1 -0
- package/dist/util/path-guard.d.ts +16 -0
- package/dist/util/path-guard.d.ts.map +1 -0
- package/dist/util/path-guard.js +40 -0
- package/dist/util/path-guard.js.map +1 -0
- package/dist/util/timing-log.d.ts +28 -0
- package/dist/util/timing-log.d.ts.map +1 -0
- package/dist/util/timing-log.js +38 -0
- package/dist/util/timing-log.js.map +1 -0
- package/dist/util/walk.d.ts +10 -0
- package/dist/util/walk.d.ts.map +1 -0
- package/dist/util/walk.js +45 -0
- package/dist/util/walk.js.map +1 -0
- package/package.json +48 -0
- package/src/schema/graph.schema.json +446 -0
- package/src/schema/validate.ts +57 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,945 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, realpathSync, writeSync, } from "node:fs";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { DxMcpSourceAdapter } from "./adapters/dx-mcp/index.js";
|
|
7
|
+
import { LocalSourceAdapter } from "./adapters/local/index.js";
|
|
8
|
+
import { computeDiff } from "./diff/index.js";
|
|
9
|
+
import { EXPLAIN_KINDS, applyExplain } from "./explain/index.js";
|
|
10
|
+
import { KnowledgeGraphReader, SqliteGraphStore, buildGraph } from "./graph/index.js";
|
|
11
|
+
import { runInit } from "./init/index.js";
|
|
12
|
+
import { MetricsStore, summarize } from "./metrics/index.js";
|
|
13
|
+
import { OnboardingStateStore, PERSONA_IDS, expandReadOrder, extractFaq, loadContextMap, renderFaqMarkdown, } from "./onboarding/index.js";
|
|
14
|
+
import { renderAll, renderApex, renderApexTriggers, renderFlows, renderObjects, renderPermissions, renderSystemIndex, renderValidationRules, } from "./render/index.js";
|
|
15
|
+
import { parseSarifFile } from "./sarif/index.js";
|
|
16
|
+
import { loadGraphSchema, validateGraph } from "./schema/validate.js";
|
|
17
|
+
import { cleanStaleLock, releaseBuildLock, tryAcquireBuildLock } from "./util/build-lock.js";
|
|
18
|
+
import { PathGuardError, assertWithinRoot, resolveWithinRoot } from "./util/path-guard.js";
|
|
19
|
+
import { appendTimingLog, measureMsAsync } from "./util/timing-log.js";
|
|
20
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const BUNDLED_SCAFFOLD = resolve(here, "scaffold");
|
|
22
|
+
const YOHAKU_VERSION = "0.4.0";
|
|
23
|
+
const DEFAULT_API = "62.0";
|
|
24
|
+
const DEFAULT_DB = ".yohaku/graph.sqlite";
|
|
25
|
+
const DEFAULT_OUT = "docs/generated";
|
|
26
|
+
const DEFAULT_TIMING_LOG = ".yohaku/hook-timings.jsonl";
|
|
27
|
+
const DEFAULT_TIMING_WARN_MS = 2000;
|
|
28
|
+
const DEFAULT_BUILD_LOCK = ".yohaku/build.lock";
|
|
29
|
+
const DEFAULT_BUILD_DIRTY = ".yohaku/build.dirty";
|
|
30
|
+
const DEFAULT_ASYNC_LOG = ".yohaku/build-async.log";
|
|
31
|
+
function parseArgs(argv) {
|
|
32
|
+
const command = [];
|
|
33
|
+
const flags = new Map();
|
|
34
|
+
const positional = [];
|
|
35
|
+
let inFlags = false;
|
|
36
|
+
for (let i = 0; i < argv.length; i++) {
|
|
37
|
+
const arg = argv[i];
|
|
38
|
+
if (arg === undefined)
|
|
39
|
+
continue;
|
|
40
|
+
if (arg.startsWith("--")) {
|
|
41
|
+
inFlags = true;
|
|
42
|
+
const eqIdx = arg.indexOf("=");
|
|
43
|
+
if (eqIdx > 0) {
|
|
44
|
+
flags.set(arg.slice(2, eqIdx), arg.slice(eqIdx + 1));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const next = argv[i + 1];
|
|
48
|
+
if (next !== undefined && !next.startsWith("--")) {
|
|
49
|
+
flags.set(arg.slice(2), next);
|
|
50
|
+
i++;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
flags.set(arg.slice(2), "true");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else if (inFlags) {
|
|
58
|
+
positional.push(arg);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
command.push(arg);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { command, flags, positional };
|
|
65
|
+
}
|
|
66
|
+
async function buildAndStore(options) {
|
|
67
|
+
const adapter = options.sourceKind === "dx-mcp"
|
|
68
|
+
? new DxMcpSourceAdapter({ apiVersion: options.apiVersion })
|
|
69
|
+
: new LocalSourceAdapter({ rootPath: options.root });
|
|
70
|
+
const graph = await buildGraph(adapter, {
|
|
71
|
+
yohakuVersion: YOHAKU_VERSION,
|
|
72
|
+
salesforceApiVersion: options.apiVersion,
|
|
73
|
+
projectRoot: options.root,
|
|
74
|
+
});
|
|
75
|
+
const store = new SqliteGraphStore({ dbPath: options.dbPath });
|
|
76
|
+
store.writeAll(graph, options.incremental ? "incremental" : "full");
|
|
77
|
+
store.close();
|
|
78
|
+
const counts = {
|
|
79
|
+
objects: graph.objects.length,
|
|
80
|
+
fields: graph.fields.length,
|
|
81
|
+
flows: graph.flows.length,
|
|
82
|
+
apex: graph.apexClasses.length,
|
|
83
|
+
};
|
|
84
|
+
if (!options.quiet) {
|
|
85
|
+
console.log(`[yohaku] graph build complete: objects=${counts.objects} fields=${counts.fields} flows=${counts.flows} apex=${counts.apex}`);
|
|
86
|
+
}
|
|
87
|
+
return counts;
|
|
88
|
+
}
|
|
89
|
+
async function cmdGraphBuild(args) {
|
|
90
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
91
|
+
const dbPath = resolve(root, args.flags.get("db") ?? DEFAULT_DB);
|
|
92
|
+
const sourceKind = (args.flags.get("source") ?? "local");
|
|
93
|
+
const incremental = args.flags.get("incremental") === "true";
|
|
94
|
+
const apiVersion = args.flags.get("api") ?? DEFAULT_API;
|
|
95
|
+
const quiet = args.flags.get("quiet") === "true";
|
|
96
|
+
const noTimingLog = args.flags.get("no-timing-log") === "true";
|
|
97
|
+
const asyncMode = args.flags.get("async") === "true";
|
|
98
|
+
const asyncWorker = args.flags.get("async-worker") === "true";
|
|
99
|
+
if (sourceKind !== "local" && sourceKind !== "dx-mcp") {
|
|
100
|
+
console.error(`Unknown source: ${sourceKind}. Use --source local|dx-mcp.`);
|
|
101
|
+
return 2;
|
|
102
|
+
}
|
|
103
|
+
const lockPaths = {
|
|
104
|
+
lockPath: resolve(root, args.flags.get("lock-file") ?? DEFAULT_BUILD_LOCK),
|
|
105
|
+
dirtyPath: resolve(root, args.flags.get("dirty-file") ?? DEFAULT_BUILD_DIRTY),
|
|
106
|
+
};
|
|
107
|
+
const timingPath = resolve(root, args.flags.get("timing-log") ?? DEFAULT_TIMING_LOG);
|
|
108
|
+
// --async: 子プロセスを detach して即座に戻る (Claude Code hook の wall-clock を最小化)
|
|
109
|
+
if (asyncMode && !asyncWorker) {
|
|
110
|
+
return spawnAsyncBuildWorker({ args, root });
|
|
111
|
+
}
|
|
112
|
+
// --async-worker: detach された子プロセス。ロックを取って実行。
|
|
113
|
+
if (asyncWorker) {
|
|
114
|
+
cleanStaleLock(lockPaths);
|
|
115
|
+
const acq = tryAcquireBuildLock(lockPaths);
|
|
116
|
+
if (!acq.acquired) {
|
|
117
|
+
// 既に別 build が走っている。dirty を立てた (tryAcquireBuildLock 内) ので終了。
|
|
118
|
+
if (!quiet) {
|
|
119
|
+
console.error(`[yohaku] async build skipped: another build is in progress (${acq.heldBy}). Marked dirty for re-run.`);
|
|
120
|
+
}
|
|
121
|
+
return 0;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
// 「並行 Edit で取りこぼした最後の変更を 1 回だけ拾う」ループ。無限再実行は防ぐ。
|
|
125
|
+
const MAX_RERUNS = 1;
|
|
126
|
+
let rerunCount = 0;
|
|
127
|
+
let keepGoing = true;
|
|
128
|
+
while (keepGoing) {
|
|
129
|
+
const { result: counts, durationMs } = await measureMsAsync(() => buildAndStore({ root, dbPath, apiVersion, incremental, quiet: true, sourceKind }));
|
|
130
|
+
if (!noTimingLog) {
|
|
131
|
+
appendTimingLog(timingPath, {
|
|
132
|
+
timestamp: new Date().toISOString(),
|
|
133
|
+
command: "graph build",
|
|
134
|
+
durationMs: Math.round(durationMs),
|
|
135
|
+
mode: incremental ? "incremental" : "full",
|
|
136
|
+
extra: {
|
|
137
|
+
objects: counts.objects,
|
|
138
|
+
fields: counts.fields,
|
|
139
|
+
flows: counts.flows,
|
|
140
|
+
apex: counts.apex,
|
|
141
|
+
source: sourceKind,
|
|
142
|
+
async: true,
|
|
143
|
+
rerun: rerunCount > 0,
|
|
144
|
+
},
|
|
145
|
+
}, { warnThresholdMs: DEFAULT_TIMING_WARN_MS, silent: true });
|
|
146
|
+
}
|
|
147
|
+
// dirty が立っていれば 1 回だけ再実行
|
|
148
|
+
const release = releaseBuildLock(lockPaths);
|
|
149
|
+
if (!release.rerunNeeded || rerunCount >= MAX_RERUNS) {
|
|
150
|
+
keepGoing = false;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
rerunCount++;
|
|
154
|
+
// 次のループに備えて lock を取り直す
|
|
155
|
+
const next = tryAcquireBuildLock(lockPaths);
|
|
156
|
+
if (!next.acquired)
|
|
157
|
+
keepGoing = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
// worker は detach されているので親への通知経路がない。ログだけ残す。
|
|
162
|
+
releaseBuildLock(lockPaths);
|
|
163
|
+
try {
|
|
164
|
+
const errPath = resolve(root, DEFAULT_ASYNC_LOG);
|
|
165
|
+
mkdirSync(dirname(errPath), { recursive: true });
|
|
166
|
+
const fd = openSync(errPath, "a");
|
|
167
|
+
const msg = `${new Date().toISOString()} [error] ${err.message}\n`;
|
|
168
|
+
try {
|
|
169
|
+
writeSync(fd, msg);
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
closeSync(fd);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// ignore
|
|
177
|
+
}
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
// 通常 (同期) 実行
|
|
183
|
+
const { result: counts, durationMs } = await measureMsAsync(() => buildAndStore({ root, dbPath, apiVersion, incremental, quiet, sourceKind }));
|
|
184
|
+
if (!noTimingLog) {
|
|
185
|
+
appendTimingLog(timingPath, {
|
|
186
|
+
timestamp: new Date().toISOString(),
|
|
187
|
+
command: "graph build",
|
|
188
|
+
durationMs: Math.round(durationMs),
|
|
189
|
+
mode: incremental ? "incremental" : "full",
|
|
190
|
+
extra: {
|
|
191
|
+
objects: counts.objects,
|
|
192
|
+
fields: counts.fields,
|
|
193
|
+
flows: counts.flows,
|
|
194
|
+
apex: counts.apex,
|
|
195
|
+
source: sourceKind,
|
|
196
|
+
},
|
|
197
|
+
}, { warnThresholdMs: DEFAULT_TIMING_WARN_MS, silent: quiet });
|
|
198
|
+
}
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* --async モードの起動口: detach された子プロセスに --async-worker を付けて起動し、即座に戻る。
|
|
203
|
+
* stdout/stderr は `.yohaku/build-async.log` にリダイレクト。
|
|
204
|
+
*/
|
|
205
|
+
function spawnAsyncBuildWorker(opts) {
|
|
206
|
+
const { args, root } = opts;
|
|
207
|
+
const logPath = resolve(root, DEFAULT_ASYNC_LOG);
|
|
208
|
+
mkdirSync(dirname(logPath), { recursive: true });
|
|
209
|
+
const out = openSync(logPath, "a");
|
|
210
|
+
// 引数を組み立て直し: --async → --async-worker, それ以外は保持
|
|
211
|
+
const childArgs = ["graph", "build", "--async-worker"];
|
|
212
|
+
for (const [k, v] of args.flags) {
|
|
213
|
+
if (k === "async" || k === "async-worker")
|
|
214
|
+
continue;
|
|
215
|
+
if (v === "true")
|
|
216
|
+
childArgs.push(`--${k}`);
|
|
217
|
+
else
|
|
218
|
+
childArgs.push(`--${k}`, v);
|
|
219
|
+
}
|
|
220
|
+
// 自分自身 (cli.js) を node で再起動する
|
|
221
|
+
const selfPath = fileURLToPath(import.meta.url);
|
|
222
|
+
const child = spawn(process.execPath, [selfPath, ...childArgs], {
|
|
223
|
+
detached: true,
|
|
224
|
+
stdio: ["ignore", out, out],
|
|
225
|
+
cwd: root,
|
|
226
|
+
env: process.env,
|
|
227
|
+
});
|
|
228
|
+
child.unref();
|
|
229
|
+
// 親プロセスは即座に戻る (hook の wall-clock を最小化)
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
async function cmdSync(args) {
|
|
233
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
234
|
+
const dbPath = resolve(root, args.flags.get("db") ?? DEFAULT_DB);
|
|
235
|
+
const outDir = resolve(root, args.flags.get("output") ?? DEFAULT_OUT);
|
|
236
|
+
const apiVersion = args.flags.get("api") ?? DEFAULT_API;
|
|
237
|
+
const quiet = args.flags.get("quiet") === "true";
|
|
238
|
+
// sync はデフォルトで incremental (full は --full-rebuild で明示)
|
|
239
|
+
const incremental = args.flags.get("full-rebuild") !== "true";
|
|
240
|
+
await buildAndStore({ root, dbPath, apiVersion, incremental, quiet });
|
|
241
|
+
const graph = readGraphFromStore(dbPath);
|
|
242
|
+
// Phase 7-A: sync で全種 Markdown 化
|
|
243
|
+
reportRender(renderAll(graph, outDir));
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
async function cmdGraphQuery(args) {
|
|
247
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
248
|
+
const dbPath = resolve(root, args.flags.get("db") ?? DEFAULT_DB);
|
|
249
|
+
// SQL は "graph query" の後ろ (command[2]+) と positional のどちらにも来うる
|
|
250
|
+
const sqlFromCommand = args.command.slice(2).join(" ");
|
|
251
|
+
const sqlFromPositional = args.positional.join(" ");
|
|
252
|
+
const sql = [sqlFromCommand, sqlFromPositional]
|
|
253
|
+
.filter((s) => s !== "")
|
|
254
|
+
.join(" ")
|
|
255
|
+
.trim();
|
|
256
|
+
if (sql === "") {
|
|
257
|
+
console.error('Usage: yohaku graph query "<SQL>"');
|
|
258
|
+
return 2;
|
|
259
|
+
}
|
|
260
|
+
// 外部入力 SQL は readonly モード + SELECT allowlist の二重防御で実行する
|
|
261
|
+
const store = new SqliteGraphStore({ dbPath, readonly: true });
|
|
262
|
+
let rows;
|
|
263
|
+
try {
|
|
264
|
+
rows = store.queryUntrusted(sql);
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
const msg = err.message;
|
|
268
|
+
console.error(`[yohaku] graph query rejected: ${msg}`);
|
|
269
|
+
// 「PRAGMA を試そうとした」「複文」のような典型誤りには専用ヒントを出す
|
|
270
|
+
if (/Untrusted query rejected/.test(msg) && /pragma/i.test(sql)) {
|
|
271
|
+
console.error("Hint: PRAGMA is intentionally blocked on this path. Use `yohaku graph schema --tables` to inspect tables/columns.");
|
|
272
|
+
}
|
|
273
|
+
// SQLite エラーから「該当しないテーブル/カラム名」を抽出し、近い候補を提案する
|
|
274
|
+
const hint = buildGraphQueryHint(store, msg);
|
|
275
|
+
if (hint)
|
|
276
|
+
console.error(hint);
|
|
277
|
+
store.close();
|
|
278
|
+
return 2;
|
|
279
|
+
}
|
|
280
|
+
store.close();
|
|
281
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
282
|
+
return 0;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* SQLite の "no such column: X" / "no such table: X" エラー時に
|
|
286
|
+
* 近い候補を提案するヒントメッセージを生成する。
|
|
287
|
+
* camelCase → snake_case の典型誤推測も明示的に検出する。
|
|
288
|
+
*/
|
|
289
|
+
function buildGraphQueryHint(store, errorMsg) {
|
|
290
|
+
const colMatch = errorMsg.match(/no such column:\s*([A-Za-z_][\w.]*)/);
|
|
291
|
+
const tblMatch = errorMsg.match(/no such table:\s*([A-Za-z_][\w.]*)/);
|
|
292
|
+
if (colMatch) {
|
|
293
|
+
const bad = colMatch[1] ?? "";
|
|
294
|
+
const last = bad.includes(".") ? (bad.split(".").pop() ?? bad) : bad;
|
|
295
|
+
let candidates;
|
|
296
|
+
try {
|
|
297
|
+
candidates = store.getAllColumnNames();
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
const snake = camelToSnake(last);
|
|
303
|
+
const lines = [];
|
|
304
|
+
if (snake !== last && candidates.includes(snake)) {
|
|
305
|
+
lines.push(`Hint: did you mean "${snake}"? Column names in this graph are snake_case.`);
|
|
306
|
+
}
|
|
307
|
+
const near = nearestNames(last, candidates, 3);
|
|
308
|
+
if (near.length > 0)
|
|
309
|
+
lines.push(`Hint: similar columns → ${near.join(", ")}`);
|
|
310
|
+
lines.push("Hint: run `yohaku graph schema --tables` to see all tables and columns.");
|
|
311
|
+
return lines.join("\n");
|
|
312
|
+
}
|
|
313
|
+
if (tblMatch) {
|
|
314
|
+
const bad = tblMatch[1] ?? "";
|
|
315
|
+
let candidates;
|
|
316
|
+
try {
|
|
317
|
+
candidates = store.getAllTableNames();
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
const snake = camelToSnake(bad);
|
|
323
|
+
const lines = [];
|
|
324
|
+
if (snake !== bad && candidates.includes(snake)) {
|
|
325
|
+
lines.push(`Hint: did you mean "${snake}"? Table names in this graph are snake_case.`);
|
|
326
|
+
}
|
|
327
|
+
const near = nearestNames(bad, candidates, 3);
|
|
328
|
+
if (near.length > 0)
|
|
329
|
+
lines.push(`Hint: similar tables → ${near.join(", ")}`);
|
|
330
|
+
lines.push("Hint: run `yohaku graph schema --tables` to see all tables and columns.");
|
|
331
|
+
return lines.join("\n");
|
|
332
|
+
}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
function camelToSnake(s) {
|
|
336
|
+
return s
|
|
337
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1_$2")
|
|
338
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
|
|
339
|
+
.toLowerCase();
|
|
340
|
+
}
|
|
341
|
+
function nearestNames(target, candidates, limit) {
|
|
342
|
+
const t = target.toLowerCase();
|
|
343
|
+
const scored = candidates
|
|
344
|
+
.map((c) => ({ name: c, d: levenshtein(t, c.toLowerCase()) }))
|
|
345
|
+
.filter((x) => x.d <= Math.max(2, Math.floor(t.length / 2)))
|
|
346
|
+
.sort((a, b) => a.d - b.d);
|
|
347
|
+
return scored.slice(0, limit).map((x) => x.name);
|
|
348
|
+
}
|
|
349
|
+
function levenshtein(a, b) {
|
|
350
|
+
if (a === b)
|
|
351
|
+
return 0;
|
|
352
|
+
if (a.length === 0)
|
|
353
|
+
return b.length;
|
|
354
|
+
if (b.length === 0)
|
|
355
|
+
return a.length;
|
|
356
|
+
const prev = new Array(b.length + 1);
|
|
357
|
+
const curr = new Array(b.length + 1);
|
|
358
|
+
for (let j = 0; j <= b.length; j++)
|
|
359
|
+
prev[j] = j;
|
|
360
|
+
for (let i = 1; i <= a.length; i++) {
|
|
361
|
+
curr[0] = i;
|
|
362
|
+
for (let j = 1; j <= b.length; j++) {
|
|
363
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
364
|
+
curr[j] = Math.min((curr[j - 1] ?? 0) + 1, (prev[j] ?? 0) + 1, (prev[j - 1] ?? 0) + cost);
|
|
365
|
+
}
|
|
366
|
+
for (let j = 0; j <= b.length; j++)
|
|
367
|
+
prev[j] = curr[j] ?? 0;
|
|
368
|
+
}
|
|
369
|
+
return prev[b.length] ?? 0;
|
|
370
|
+
}
|
|
371
|
+
async function cmdGraphSchema(args) {
|
|
372
|
+
const format = args.flags.get("format") ?? "json";
|
|
373
|
+
// --tables: 実 SQLite テーブル定義を返す (PRAGMA 経由できない LLM 向けの安全な経路)
|
|
374
|
+
if (args.flags.has("tables")) {
|
|
375
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
376
|
+
const dbPath = resolve(root, args.flags.get("db") ?? DEFAULT_DB);
|
|
377
|
+
// `--tables objects` (filterとして) と `--tables --table=objects` の両方を許容
|
|
378
|
+
const tablesVal = args.flags.get("tables");
|
|
379
|
+
const tableFilter = args.flags.get("table") ?? (tablesVal && tablesVal !== "true" ? tablesVal : undefined);
|
|
380
|
+
const store = new SqliteGraphStore({ dbPath, readonly: true });
|
|
381
|
+
let schemas;
|
|
382
|
+
try {
|
|
383
|
+
schemas = store.getTableSchemas(tableFilter);
|
|
384
|
+
}
|
|
385
|
+
catch (err) {
|
|
386
|
+
console.error(`[yohaku] graph schema --tables failed: ${err.message}`);
|
|
387
|
+
store.close();
|
|
388
|
+
return 2;
|
|
389
|
+
}
|
|
390
|
+
store.close();
|
|
391
|
+
if (format === "markdown") {
|
|
392
|
+
console.log("# Knowledge Graph Tables\n");
|
|
393
|
+
for (const s of schemas) {
|
|
394
|
+
console.log(`## \`${s.table}\`\n`);
|
|
395
|
+
console.log("| Column | Type | Not Null | Default | PK |");
|
|
396
|
+
console.log("|---|---|---|---|---|");
|
|
397
|
+
for (const c of s.columns) {
|
|
398
|
+
const dflt = c.defaultValue ?? "";
|
|
399
|
+
console.log(`| \`${c.name}\` | ${c.type} | ${c.notNull ? "Y" : ""} | ${dflt} | ${c.primaryKey ? "Y" : ""} |`);
|
|
400
|
+
}
|
|
401
|
+
console.log("");
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
console.log(JSON.stringify(schemas, null, 2));
|
|
406
|
+
}
|
|
407
|
+
return 0;
|
|
408
|
+
}
|
|
409
|
+
// 後方互換: 引数なしは meta スキーマ (既存挙動)
|
|
410
|
+
const schema = loadGraphSchema();
|
|
411
|
+
if (format === "markdown") {
|
|
412
|
+
console.log("# Knowledge Graph Schema\n");
|
|
413
|
+
console.log("```json");
|
|
414
|
+
console.log(JSON.stringify(schema, null, 2));
|
|
415
|
+
console.log("```");
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
console.log(JSON.stringify(schema, null, 2));
|
|
419
|
+
}
|
|
420
|
+
return 0;
|
|
421
|
+
}
|
|
422
|
+
async function cmdRender(args) {
|
|
423
|
+
const target = args.command[1];
|
|
424
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
425
|
+
const outDir = resolve(root, args.flags.get("output") ?? DEFAULT_OUT);
|
|
426
|
+
const dbPath = resolve(root, args.flags.get("db") ?? DEFAULT_DB);
|
|
427
|
+
const renderAllFlag = args.flags.get("all") === "true";
|
|
428
|
+
if (!existsSync(dbPath)) {
|
|
429
|
+
console.error(`Knowledge graph not found at ${dbPath}. Run "yohaku graph build" first.`);
|
|
430
|
+
return 2;
|
|
431
|
+
}
|
|
432
|
+
const graph = readGraphFromStore(dbPath);
|
|
433
|
+
if (target === undefined && renderAllFlag) {
|
|
434
|
+
reportRender(renderAll(graph, outDir));
|
|
435
|
+
return 0;
|
|
436
|
+
}
|
|
437
|
+
if (target === undefined) {
|
|
438
|
+
// 後方互換: 引数省略時は system-index + objects (Phase 2.5 仕様)
|
|
439
|
+
const r1 = renderSystemIndex(graph, outDir);
|
|
440
|
+
const r2 = renderObjects(graph, outDir);
|
|
441
|
+
reportRender({
|
|
442
|
+
written: [...r1.written, ...r2.written],
|
|
443
|
+
archived: [...r1.archived, ...r2.archived],
|
|
444
|
+
warnings: [...r1.warnings, ...r2.warnings],
|
|
445
|
+
});
|
|
446
|
+
return 0;
|
|
447
|
+
}
|
|
448
|
+
if (target === "all") {
|
|
449
|
+
reportRender(renderAll(graph, outDir));
|
|
450
|
+
return 0;
|
|
451
|
+
}
|
|
452
|
+
if (target === "system-index") {
|
|
453
|
+
reportRender(renderSystemIndex(graph, outDir));
|
|
454
|
+
return 0;
|
|
455
|
+
}
|
|
456
|
+
if (target === "objects") {
|
|
457
|
+
reportRender(renderObjects(graph, outDir));
|
|
458
|
+
return 0;
|
|
459
|
+
}
|
|
460
|
+
if (target === "flows") {
|
|
461
|
+
reportRender(renderFlows(graph, outDir));
|
|
462
|
+
return 0;
|
|
463
|
+
}
|
|
464
|
+
if (target === "apex") {
|
|
465
|
+
reportRender(renderApex(graph, outDir));
|
|
466
|
+
return 0;
|
|
467
|
+
}
|
|
468
|
+
if (target === "triggers") {
|
|
469
|
+
reportRender(renderApexTriggers(graph, outDir));
|
|
470
|
+
return 0;
|
|
471
|
+
}
|
|
472
|
+
if (target === "permissions") {
|
|
473
|
+
reportRender(renderPermissions(graph, outDir));
|
|
474
|
+
return 0;
|
|
475
|
+
}
|
|
476
|
+
if (target === "validation-rules") {
|
|
477
|
+
reportRender(renderValidationRules(graph, outDir));
|
|
478
|
+
return 0;
|
|
479
|
+
}
|
|
480
|
+
console.error(`Unknown render target: ${target}`);
|
|
481
|
+
return 2;
|
|
482
|
+
}
|
|
483
|
+
function reportRender(result) {
|
|
484
|
+
console.log(`[yohaku] render complete: written=${result.written.length} archived=${result.archived.length} warnings=${result.warnings.length}`);
|
|
485
|
+
for (const w of result.warnings) {
|
|
486
|
+
console.warn(` warning: ${w.code} ${w.blockId ?? ""}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function readGraphFromStore(dbPath) {
|
|
490
|
+
const reader = new KnowledgeGraphReader({ dbPath });
|
|
491
|
+
try {
|
|
492
|
+
return reader.read();
|
|
493
|
+
}
|
|
494
|
+
finally {
|
|
495
|
+
reader.close();
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
async function cmdDiff(args) {
|
|
499
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
500
|
+
const fromRef = args.flags.get("from");
|
|
501
|
+
const toRef = args.flags.get("to") ?? "HEAD";
|
|
502
|
+
if (fromRef === undefined) {
|
|
503
|
+
console.error("Usage: yohaku diff --from <ref> [--to <ref>] [--path-prefix force-app/]");
|
|
504
|
+
return 2;
|
|
505
|
+
}
|
|
506
|
+
const fileLimitRaw = args.flags.get("limit");
|
|
507
|
+
const fileLimit = fileLimitRaw !== undefined && !Number.isNaN(Number(fileLimitRaw))
|
|
508
|
+
? Number(fileLimitRaw)
|
|
509
|
+
: undefined;
|
|
510
|
+
const pathPrefix = args.flags.get("path-prefix");
|
|
511
|
+
const diff = computeDiff({
|
|
512
|
+
fromRef,
|
|
513
|
+
toRef,
|
|
514
|
+
cwd: root,
|
|
515
|
+
...(fileLimit !== undefined ? { fileLimit } : {}),
|
|
516
|
+
...(pathPrefix !== undefined ? { pathPrefix } : {}),
|
|
517
|
+
});
|
|
518
|
+
const sarifPath = args.flags.get("include-static-analysis");
|
|
519
|
+
const findings = sarifPath !== undefined ? parseSarifFile(resolve(root, sarifPath)) : [];
|
|
520
|
+
const json = args.flags.get("json") === "true";
|
|
521
|
+
if (json) {
|
|
522
|
+
console.log(JSON.stringify({ ...diff, staticAnalysisFindings: findings }, null, 2));
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
console.log(`[yohaku] diff ${fromRef}..${toRef}: files=${diff.totals.files} +${diff.totals.addedLines} -${diff.totals.removedLines} truncated=${diff.truncated}`);
|
|
526
|
+
for (const [cat, count] of Object.entries(diff.totals.byCategory)) {
|
|
527
|
+
if (count === 0)
|
|
528
|
+
continue;
|
|
529
|
+
console.log(` ${cat}: ${count}`);
|
|
530
|
+
}
|
|
531
|
+
if (findings.length > 0) {
|
|
532
|
+
console.log(` static_analysis: ${findings.length} findings`);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return 0;
|
|
536
|
+
}
|
|
537
|
+
async function cmdOnboardContext(args) {
|
|
538
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
539
|
+
const role = (args.flags.get("role") ?? "new_joiner").replace(/-/g, "_");
|
|
540
|
+
if (!PERSONA_IDS.includes(role)) {
|
|
541
|
+
console.error(`Unknown role: ${role}. Use one of: ${PERSONA_IDS.join(", ")}`);
|
|
542
|
+
return 2;
|
|
543
|
+
}
|
|
544
|
+
const contextMap = loadContextMap({ rootPath: root });
|
|
545
|
+
const persona = contextMap.personas[role];
|
|
546
|
+
const expanded = expandReadOrder(persona, contextMap);
|
|
547
|
+
const output = {
|
|
548
|
+
project: contextMap.project.name,
|
|
549
|
+
role,
|
|
550
|
+
goal: persona.goal,
|
|
551
|
+
depth: persona.depth,
|
|
552
|
+
primaryAgent: persona.primaryAgent,
|
|
553
|
+
readOrder: expanded,
|
|
554
|
+
domains: contextMap.project.domains,
|
|
555
|
+
};
|
|
556
|
+
console.log(JSON.stringify(output, null, 2));
|
|
557
|
+
return 0;
|
|
558
|
+
}
|
|
559
|
+
async function cmdOnboardState(args) {
|
|
560
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
561
|
+
const sub = args.command[2] ?? "show";
|
|
562
|
+
const store = new OnboardingStateStore({ rootPath: root });
|
|
563
|
+
if (sub === "show") {
|
|
564
|
+
console.log(JSON.stringify(store.read(), null, 2));
|
|
565
|
+
return 0;
|
|
566
|
+
}
|
|
567
|
+
if (sub === "record-step") {
|
|
568
|
+
const role = (args.flags.get("role") ?? "").replace(/-/g, "_");
|
|
569
|
+
const step = args.flags.get("step");
|
|
570
|
+
if (!PERSONA_IDS.includes(role) || step === undefined) {
|
|
571
|
+
console.error("Usage: yohaku onboard state record-step --role <persona> --step <step-id> [--entities a,b,c]");
|
|
572
|
+
return 2;
|
|
573
|
+
}
|
|
574
|
+
const entitiesRaw = args.flags.get("entities");
|
|
575
|
+
const entities = entitiesRaw ? entitiesRaw.split(",").map((s) => s.trim()) : [];
|
|
576
|
+
const result = store.recordStep(role, step, entities);
|
|
577
|
+
console.log(JSON.stringify(result, null, 2));
|
|
578
|
+
return 0;
|
|
579
|
+
}
|
|
580
|
+
if (sub === "increment-questions") {
|
|
581
|
+
const role = (args.flags.get("role") ?? "").replace(/-/g, "_");
|
|
582
|
+
if (!PERSONA_IDS.includes(role)) {
|
|
583
|
+
console.error("Usage: yohaku onboard state increment-questions --role <persona>");
|
|
584
|
+
return 2;
|
|
585
|
+
}
|
|
586
|
+
const result = store.incrementQuestions(role);
|
|
587
|
+
console.log(JSON.stringify(result, null, 2));
|
|
588
|
+
return 0;
|
|
589
|
+
}
|
|
590
|
+
if (sub === "reset") {
|
|
591
|
+
const roleFlag = args.flags.get("role");
|
|
592
|
+
const role = roleFlag !== undefined ? roleFlag.replace(/-/g, "_") : undefined;
|
|
593
|
+
if (role !== undefined && !PERSONA_IDS.includes(role)) {
|
|
594
|
+
console.error(`Unknown role: ${role}`);
|
|
595
|
+
return 2;
|
|
596
|
+
}
|
|
597
|
+
store.reset(role);
|
|
598
|
+
console.log(`[yohaku] reset ${role ?? "all"}`);
|
|
599
|
+
return 0;
|
|
600
|
+
}
|
|
601
|
+
console.error(`Unknown subcommand: state ${sub}. Use show|record-step|increment-questions|reset`);
|
|
602
|
+
return 2;
|
|
603
|
+
}
|
|
604
|
+
async function cmdOnboardFaqExtract(args) {
|
|
605
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
606
|
+
const inputFile = args.flags.get("input");
|
|
607
|
+
const topic = args.flags.get("topic") ?? "general";
|
|
608
|
+
const minOcc = Number(args.flags.get("min-occurrences") ?? 1);
|
|
609
|
+
if (inputFile === undefined) {
|
|
610
|
+
console.error("Usage: yohaku onboard faq extract --input <dialog-log.md> [--topic <name>] [--min-occurrences 1]");
|
|
611
|
+
return 2;
|
|
612
|
+
}
|
|
613
|
+
let inputAbs;
|
|
614
|
+
try {
|
|
615
|
+
inputAbs = resolveWithinRoot(root, inputFile, "--input");
|
|
616
|
+
}
|
|
617
|
+
catch (err) {
|
|
618
|
+
console.error(`[yohaku] ${err.message}`);
|
|
619
|
+
return 2;
|
|
620
|
+
}
|
|
621
|
+
const content = readFileSync(inputAbs, "utf8");
|
|
622
|
+
const candidates = extractFaq(content, { minOccurrences: Number.isNaN(minOcc) ? 1 : minOcc });
|
|
623
|
+
const md = renderFaqMarkdown(topic, candidates);
|
|
624
|
+
console.log(md);
|
|
625
|
+
return 0;
|
|
626
|
+
}
|
|
627
|
+
async function cmdValidate(args) {
|
|
628
|
+
const targetPath = args.flags.get("target");
|
|
629
|
+
if (targetPath === undefined) {
|
|
630
|
+
console.error("Usage: yohaku validate --target <path-to-json-graph>");
|
|
631
|
+
return 2;
|
|
632
|
+
}
|
|
633
|
+
let resolvedTarget;
|
|
634
|
+
try {
|
|
635
|
+
resolvedTarget = resolveWithinRoot(process.cwd(), targetPath, "--target");
|
|
636
|
+
}
|
|
637
|
+
catch (err) {
|
|
638
|
+
console.error(`[yohaku] ${err.message}`);
|
|
639
|
+
return 2;
|
|
640
|
+
}
|
|
641
|
+
let raw;
|
|
642
|
+
try {
|
|
643
|
+
raw = readFileSync(resolvedTarget, "utf8");
|
|
644
|
+
}
|
|
645
|
+
catch (err) {
|
|
646
|
+
console.error(`[yohaku] cannot read --target: ${err.message}`);
|
|
647
|
+
return 1;
|
|
648
|
+
}
|
|
649
|
+
let data;
|
|
650
|
+
try {
|
|
651
|
+
data = JSON.parse(raw);
|
|
652
|
+
}
|
|
653
|
+
catch (err) {
|
|
654
|
+
console.error(`[yohaku] --target is not valid JSON: ${err.message}`);
|
|
655
|
+
return 1;
|
|
656
|
+
}
|
|
657
|
+
try {
|
|
658
|
+
validateGraph(data);
|
|
659
|
+
console.log("[yohaku] validate: OK");
|
|
660
|
+
return 0;
|
|
661
|
+
}
|
|
662
|
+
catch (err) {
|
|
663
|
+
console.error(`[yohaku] validate: FAILED — ${err.message}`);
|
|
664
|
+
return 1;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
async function cmdVersion() {
|
|
668
|
+
console.log(YOHAKU_VERSION);
|
|
669
|
+
return 0;
|
|
670
|
+
}
|
|
671
|
+
async function cmdMetricsShow(args) {
|
|
672
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
673
|
+
const period = (args.flags.get("period") ?? "month");
|
|
674
|
+
const store = new MetricsStore({ rootPath: root });
|
|
675
|
+
const summary = summarize(store.read(), period);
|
|
676
|
+
const output = {
|
|
677
|
+
period: summary.period,
|
|
678
|
+
since: summary.since,
|
|
679
|
+
totals: summary.totals,
|
|
680
|
+
byModel: Object.fromEntries(summary.byModel),
|
|
681
|
+
byCommand: Object.fromEntries(summary.byCommand),
|
|
682
|
+
};
|
|
683
|
+
console.log(JSON.stringify(output, null, 2));
|
|
684
|
+
return 0;
|
|
685
|
+
}
|
|
686
|
+
async function cmdMetricsRecord(args) {
|
|
687
|
+
const root = args.flags.get("root") ?? process.cwd();
|
|
688
|
+
const model = args.flags.get("model");
|
|
689
|
+
const command = args.flags.get("command");
|
|
690
|
+
const tokensIn = Number(args.flags.get("in") ?? 0);
|
|
691
|
+
const tokensOut = Number(args.flags.get("out") ?? 0);
|
|
692
|
+
const note = args.flags.get("note");
|
|
693
|
+
if (model === undefined ||
|
|
694
|
+
command === undefined ||
|
|
695
|
+
Number.isNaN(tokensIn) ||
|
|
696
|
+
Number.isNaN(tokensOut)) {
|
|
697
|
+
console.error('Usage: yohaku metrics record --model <id> --command <name> --in <tokens> --out <tokens> [--note "<text>"]');
|
|
698
|
+
return 2;
|
|
699
|
+
}
|
|
700
|
+
const store = new MetricsStore({ rootPath: root });
|
|
701
|
+
const event = store.record({
|
|
702
|
+
model,
|
|
703
|
+
command,
|
|
704
|
+
tokensIn,
|
|
705
|
+
tokensOut,
|
|
706
|
+
...(note !== undefined ? { note } : {}),
|
|
707
|
+
});
|
|
708
|
+
console.log(JSON.stringify(event, null, 2));
|
|
709
|
+
return 0;
|
|
710
|
+
}
|
|
711
|
+
async function cmdInit(args) {
|
|
712
|
+
const targetDir = args.flags.get("target") ?? args.flags.get("root") ?? process.cwd();
|
|
713
|
+
const profile = (args.flags.get("profile") ?? "standard");
|
|
714
|
+
const projectName = args.flags.get("project-name") ?? args.flags.get("name") ?? defaultProjectName(targetDir);
|
|
715
|
+
const language = (args.flags.get("language") ?? "ja");
|
|
716
|
+
const apiVersion = args.flags.get("api") ?? DEFAULT_API;
|
|
717
|
+
const segment = (args.flags.get("segment") ?? "unspecified");
|
|
718
|
+
const repoUrl = args.flags.get("repo") ?? "";
|
|
719
|
+
const conflict = (args.flags.get("conflict") ?? "skip");
|
|
720
|
+
const scaffoldDir = args.flags.get("scaffold") ?? BUNDLED_SCAFFOLD;
|
|
721
|
+
if (!existsSync(scaffoldDir)) {
|
|
722
|
+
console.error(`[yohaku] init: scaffold directory not found at ${scaffoldDir}`);
|
|
723
|
+
return 1;
|
|
724
|
+
}
|
|
725
|
+
const result = await runInit({
|
|
726
|
+
targetDir: resolve(targetDir),
|
|
727
|
+
scaffoldDir,
|
|
728
|
+
conflict,
|
|
729
|
+
variables: {
|
|
730
|
+
projectName,
|
|
731
|
+
profile,
|
|
732
|
+
primaryLanguage: language,
|
|
733
|
+
salesforceApiVersion: apiVersion,
|
|
734
|
+
yohakuVersion: YOHAKU_VERSION,
|
|
735
|
+
segment,
|
|
736
|
+
repoUrl,
|
|
737
|
+
now: new Date().toISOString(),
|
|
738
|
+
enabledCommands: [],
|
|
739
|
+
enabledAgents: [],
|
|
740
|
+
includeDxMcpAdapter: false,
|
|
741
|
+
includeStaticAnalysis: false,
|
|
742
|
+
},
|
|
743
|
+
});
|
|
744
|
+
console.log(`[yohaku] init complete: written=${result.written.length} skipped=${result.skipped.length} renamed=${result.renamed.length}`);
|
|
745
|
+
if (args.flags.get("verbose") === "true") {
|
|
746
|
+
console.log(JSON.stringify(result, null, 2));
|
|
747
|
+
}
|
|
748
|
+
if (args.flags.get("bootstrap") === "true") {
|
|
749
|
+
const root = resolve(targetDir);
|
|
750
|
+
const dbPath = resolve(root, DEFAULT_DB);
|
|
751
|
+
const outDir = resolve(root, DEFAULT_OUT);
|
|
752
|
+
console.log("[yohaku] bootstrap: graph build ...");
|
|
753
|
+
await buildAndStore({ root, dbPath, apiVersion, incremental: false, quiet: false });
|
|
754
|
+
console.log("[yohaku] bootstrap: render (all) ...");
|
|
755
|
+
const graph = readGraphFromStore(dbPath);
|
|
756
|
+
reportRender(renderAll(graph, outDir));
|
|
757
|
+
console.log("[yohaku] bootstrap: complete. Open Claude Code and try /onboard.");
|
|
758
|
+
}
|
|
759
|
+
return 0;
|
|
760
|
+
}
|
|
761
|
+
function defaultProjectName(targetDir) {
|
|
762
|
+
// Windows 互換: パス区切りは OS 依存。両方を受け入れる
|
|
763
|
+
const segments = resolve(targetDir).split(/[/\\]/);
|
|
764
|
+
return segments.at(-1) ?? "salesforce-project";
|
|
765
|
+
}
|
|
766
|
+
const COMMANDS = new Map([
|
|
767
|
+
["init", { handler: cmdInit }],
|
|
768
|
+
["sync", { handler: cmdSync }],
|
|
769
|
+
["graph build", { handler: cmdGraphBuild }],
|
|
770
|
+
["graph query", { handler: cmdGraphQuery }],
|
|
771
|
+
["graph schema", { handler: cmdGraphSchema }],
|
|
772
|
+
["render", { handler: cmdRender }],
|
|
773
|
+
["diff", { handler: cmdDiff }],
|
|
774
|
+
["validate", { handler: cmdValidate }],
|
|
775
|
+
["metrics show", { handler: cmdMetricsShow }],
|
|
776
|
+
["metrics record", { handler: cmdMetricsRecord }],
|
|
777
|
+
["metrics", { handler: cmdMetricsShow }],
|
|
778
|
+
["onboard context", { handler: cmdOnboardContext }],
|
|
779
|
+
["onboard state", { handler: cmdOnboardState }],
|
|
780
|
+
["onboard faq", { handler: cmdOnboardFaqExtract }],
|
|
781
|
+
["explain-write", { handler: cmdExplainWrite }],
|
|
782
|
+
["version", { handler: cmdVersion }],
|
|
783
|
+
]);
|
|
784
|
+
async function cmdExplainWrite(args) {
|
|
785
|
+
const kindRaw = args.flags.get("kind");
|
|
786
|
+
const fqn = args.flags.get("fqn");
|
|
787
|
+
const projectRoot = args.flags.get("project-root") ?? process.cwd();
|
|
788
|
+
const inputPath = args.flags.get("input");
|
|
789
|
+
const outputDir = args.flags.get("output-dir");
|
|
790
|
+
if (kindRaw === undefined || fqn === undefined || inputPath === undefined) {
|
|
791
|
+
console.error(`[yohaku] explain-write requires --kind <${EXPLAIN_KINDS.join("|")}> --fqn <name> --input <file.json>`);
|
|
792
|
+
return 2;
|
|
793
|
+
}
|
|
794
|
+
const validKinds = new Set(EXPLAIN_KINDS);
|
|
795
|
+
if (!validKinds.has(kindRaw)) {
|
|
796
|
+
console.error(`[yohaku] invalid --kind: ${kindRaw} (allowed: ${EXPLAIN_KINDS.join(" | ")})`);
|
|
797
|
+
return 2;
|
|
798
|
+
}
|
|
799
|
+
const kind = kindRaw;
|
|
800
|
+
let inputAbs;
|
|
801
|
+
try {
|
|
802
|
+
inputAbs = resolveWithinRoot(projectRoot, inputPath, "--input");
|
|
803
|
+
}
|
|
804
|
+
catch (err) {
|
|
805
|
+
console.error(`[yohaku] ${err.message}`);
|
|
806
|
+
return 2;
|
|
807
|
+
}
|
|
808
|
+
if (!existsSync(inputAbs)) {
|
|
809
|
+
console.error(`[yohaku] input file not found: ${inputAbs}`);
|
|
810
|
+
return 1;
|
|
811
|
+
}
|
|
812
|
+
let parsed;
|
|
813
|
+
try {
|
|
814
|
+
parsed = JSON.parse(readFileSync(inputAbs, "utf8"));
|
|
815
|
+
}
|
|
816
|
+
catch (e) {
|
|
817
|
+
console.error(`[yohaku] invalid JSON: ${e.message}`);
|
|
818
|
+
return 1;
|
|
819
|
+
}
|
|
820
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
821
|
+
console.error("[yohaku] input JSON must be an object: { blockId: content, ... }");
|
|
822
|
+
return 1;
|
|
823
|
+
}
|
|
824
|
+
const blocks = {};
|
|
825
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
826
|
+
if (typeof v !== "string") {
|
|
827
|
+
console.error(`[yohaku] block "${k}" must be a string`);
|
|
828
|
+
return 1;
|
|
829
|
+
}
|
|
830
|
+
blocks[k] = v;
|
|
831
|
+
}
|
|
832
|
+
const result = applyExplain({ kind, fqn, projectRoot, outputDir }, { blocks });
|
|
833
|
+
console.log(`[yohaku] explain-write: updated=${result.updated.length} skipped=${result.skipped.length} → ${result.markdownPath}`);
|
|
834
|
+
if (result.skipped.length > 0) {
|
|
835
|
+
console.log(`[yohaku] skipped ids: ${result.skipped.join(", ")}`);
|
|
836
|
+
}
|
|
837
|
+
return 0;
|
|
838
|
+
}
|
|
839
|
+
function findCommand(args) {
|
|
840
|
+
const candidates = [args.command.slice(0, 2).join(" "), args.command[0] ?? ""];
|
|
841
|
+
for (const candidate of candidates) {
|
|
842
|
+
const cmd = COMMANDS.get(candidate);
|
|
843
|
+
if (cmd !== undefined)
|
|
844
|
+
return { key: candidate, handler: cmd };
|
|
845
|
+
}
|
|
846
|
+
return undefined;
|
|
847
|
+
}
|
|
848
|
+
function printHelp() {
|
|
849
|
+
console.log(`yohaku ${YOHAKU_VERSION} — Salesforce AI-driven knowledge graph CLI
|
|
850
|
+
|
|
851
|
+
Quick start (recommended):
|
|
852
|
+
yohaku init --bootstrap [--profile minimal|standard|full] [--project-name <name>]
|
|
853
|
+
[--language ja|en] [--api <version>]
|
|
854
|
+
# init + graph build + render を 1 コマンドで実行
|
|
855
|
+
yohaku sync [--full-rebuild] [--quiet]
|
|
856
|
+
# 日常運用: graph build --incremental + render を 1 コマンドで実行
|
|
857
|
+
|
|
858
|
+
Setup:
|
|
859
|
+
yohaku init [--bootstrap] [--target <dir>] [--profile minimal|standard|full]
|
|
860
|
+
[--project-name <name>] [--language ja|en] [--api <version>]
|
|
861
|
+
[--segment enterprise|smb|vendor] [--conflict skip|overwrite|rename]
|
|
862
|
+
|
|
863
|
+
Knowledge graph:
|
|
864
|
+
yohaku graph build [--incremental] [--source local|dx-mcp] [--quiet]
|
|
865
|
+
[--async] [--no-timing-log]
|
|
866
|
+
# --async: 子プロセスを detach、即座に戻る (Claude Code hook 向け)
|
|
867
|
+
# 実行時間ログ: .yohaku/hook-timings.jsonl (--no-timing-log で抑止)
|
|
868
|
+
yohaku graph query "<SQL>"
|
|
869
|
+
yohaku graph schema [--format json|markdown]
|
|
870
|
+
# meta schema (validation 用)
|
|
871
|
+
yohaku graph schema --tables [--table <name>] [--format json|markdown]
|
|
872
|
+
# 実 SQLite テーブル定義 (LLM 向けの PRAGMA 代替)
|
|
873
|
+
|
|
874
|
+
Render (Phase 1〜7-A 全 7 ターゲット):
|
|
875
|
+
yohaku render # system-index + objects (後方互換)
|
|
876
|
+
yohaku render all # 全種を一括 (Phase 7-A)
|
|
877
|
+
yohaku render system-index # プロジェクト全体像
|
|
878
|
+
yohaku render objects # SObject 個別 (+ field / VR / dependencies)
|
|
879
|
+
yohaku render flows # Flow 個別 (Phase 7-A1)
|
|
880
|
+
yohaku render apex # ApexClass 個別 (Phase 7-A2)
|
|
881
|
+
yohaku render triggers # ApexTrigger 個別 (Phase 7-A3)
|
|
882
|
+
yohaku render permissions # PermissionSet + Profile (Phase 7-A4)
|
|
883
|
+
yohaku render validation-rules # ValidationRule 個別 (Phase 7-A4)
|
|
884
|
+
yohaku render --output <dir>
|
|
885
|
+
|
|
886
|
+
Diff (Phase 3):
|
|
887
|
+
yohaku diff --from <ref> [--to <ref>] [--json] [--path-prefix force-app/]
|
|
888
|
+
[--limit 1000] [--include-static-analysis <sarif-file>]
|
|
889
|
+
|
|
890
|
+
Onboarding (Phase 5):
|
|
891
|
+
yohaku onboard context --role <new_joiner|reviewer|release_manager|customer_facing>
|
|
892
|
+
yohaku onboard state show
|
|
893
|
+
yohaku onboard state record-step --role <persona> --step <id> [--entities a,b,c]
|
|
894
|
+
yohaku onboard state increment-questions --role <persona>
|
|
895
|
+
yohaku onboard state reset [--role <persona>]
|
|
896
|
+
yohaku onboard faq extract --input <dialog.md> [--topic <name>] [--min-occurrences 1]
|
|
897
|
+
|
|
898
|
+
Explain (Phase 8 — /yohaku-explain skill 連携):
|
|
899
|
+
yohaku explain-write --kind apexClass|apexTrigger|flow --fqn <name>
|
|
900
|
+
--input <blocks.json> [--project-root <dir>] [--output-dir <dir>]
|
|
901
|
+
# AI_MANAGED ブロックだけを安全に上書き。他ブロックには触らない。
|
|
902
|
+
|
|
903
|
+
Other:
|
|
904
|
+
yohaku validate --target <graph.json>
|
|
905
|
+
yohaku metrics show [--period day|week|month|all]
|
|
906
|
+
yohaku metrics record --model <id> --command <name> --in <tokens> --out <tokens>
|
|
907
|
+
yohaku version
|
|
908
|
+
`);
|
|
909
|
+
}
|
|
910
|
+
export async function main(argv) {
|
|
911
|
+
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h") {
|
|
912
|
+
printHelp();
|
|
913
|
+
return 0;
|
|
914
|
+
}
|
|
915
|
+
const args = parseArgs(argv);
|
|
916
|
+
const cmd = findCommand(args);
|
|
917
|
+
if (cmd === undefined) {
|
|
918
|
+
printHelp();
|
|
919
|
+
return 2;
|
|
920
|
+
}
|
|
921
|
+
try {
|
|
922
|
+
return await cmd.handler.handler(args);
|
|
923
|
+
}
|
|
924
|
+
catch (err) {
|
|
925
|
+
console.error(`[yohaku] error: ${err.message}`);
|
|
926
|
+
return 1;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
function isDirectInvoke() {
|
|
930
|
+
const argvPath = process.argv[1];
|
|
931
|
+
if (argvPath === undefined)
|
|
932
|
+
return false;
|
|
933
|
+
try {
|
|
934
|
+
const resolvedArgv = realpathSync(argvPath);
|
|
935
|
+
const resolvedMeta = realpathSync(fileURLToPath(import.meta.url));
|
|
936
|
+
return resolvedArgv === resolvedMeta;
|
|
937
|
+
}
|
|
938
|
+
catch {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (isDirectInvoke()) {
|
|
943
|
+
main(process.argv.slice(2)).then((code) => process.exit(code));
|
|
944
|
+
}
|
|
945
|
+
//# sourceMappingURL=cli.js.map
|