@pikku/cli 0.12.126 → 0.12.127
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/CHANGELOG.md +65 -0
- package/console-app/assets/{abnfDiagram-N423BO3Z-B2suyn6i.js → abnfDiagram-N423BO3Z-BY2LM8wi.js} +1 -1
- package/console-app/assets/architecture-TIHT7OUA-CWwmvxZF.js +1 -0
- package/console-app/assets/{architectureDiagram-T3A2C74G-BQ5Dfvpo.js → architectureDiagram-T3A2C74G-CeqjY3Kw.js} +1 -1
- package/console-app/assets/{blockDiagram-VBNYF7ZC-D4pVRDiF.js → blockDiagram-VBNYF7ZC-BW5174xj.js} +1 -1
- package/console-app/assets/{c4Diagram-5PPSVZJV-Da04jGpq.js → c4Diagram-5PPSVZJV-B7zXAFL0.js} +1 -1
- package/console-app/assets/channel-pOkwZ_Ot.js +1 -0
- package/console-app/assets/{chunk-2GRJ4B5K-CwODIPP4.js → chunk-2GRJ4B5K-BfRYzQ4t.js} +1 -1
- package/console-app/assets/{chunk-4I5QYGJK-Bep4akjR.js → chunk-4I5QYGJK-DBA7-Nu4.js} +1 -1
- package/console-app/assets/{chunk-5RXB4S5H-CGyCRU9L.js → chunk-5RXB4S5H-D03lNzwi.js} +1 -1
- package/console-app/assets/{chunk-6Q2QTUOP-D0IK0SMT.js → chunk-6Q2QTUOP-DloGRHJZ.js} +1 -1
- package/console-app/assets/{chunk-7Z6QIM7H-D12vS1jX.js → chunk-7Z6QIM7H-DH3uHtl2.js} +1 -1
- package/console-app/assets/{chunk-GF5L2VYU-kOLwTzIA.js → chunk-GF5L2VYU-Cu252lza.js} +1 -1
- package/console-app/assets/{chunk-I66GZJ75-Cb2nDoa3.js → chunk-I66GZJ75-DH54FcuO.js} +1 -1
- package/console-app/assets/{chunk-JQJVKLGR-B3a_ctfQ.js → chunk-JQJVKLGR-CeFuTL-V.js} +1 -1
- package/console-app/assets/{chunk-KBJHAD2P-DeP2Lqwp.js → chunk-KBJHAD2P-B-prFo0-.js} +1 -1
- package/console-app/assets/{chunk-NSK5VX7P-BO8vlGrO.js → chunk-NSK5VX7P-C10iA4GS.js} +1 -1
- package/console-app/assets/{chunk-QR6OTTB3-sX5V0Lok.js → chunk-QR6OTTB3-Cd8apAsA.js} +1 -1
- package/console-app/assets/{chunk-RYQCIY6F-DoCObEhk.js → chunk-RYQCIY6F-rfPUp2Fj.js} +1 -1
- package/console-app/assets/{chunk-UBXNYLIW-BndMXU5r.js → chunk-UBXNYLIW-D25wqJBc.js} +1 -1
- package/console-app/assets/{chunk-W5SLKNZC--VrZN8EC.js → chunk-W5SLKNZC-CJvxkxuK.js} +1 -1
- package/console-app/assets/{chunk-WRU74C26-DdS0mzXO.js → chunk-WRU74C26-B9Wju92P.js} +1 -1
- package/console-app/assets/chunk-XXDRQBXY-BU_UP6f5.js +1 -0
- package/console-app/assets/classDiagram-JCYQIIEL-CLBKUuxj.js +1 -0
- package/console-app/assets/classDiagram-v2-OCEON4UE-CLBKUuxj.js +1 -0
- package/console-app/assets/{cose-bilkent-JH36ORCC-C5EnHkFn.js → cose-bilkent-JH36ORCC-CwA1VCP5.js} +1 -1
- package/console-app/assets/{cynefin-VYW2F7L2-9irdkTt4.js → cynefin-VYW2F7L2-C_qsD7eR.js} +1 -1
- package/console-app/assets/{cynefinDiagram-MW4NZA55-DY19660c.js → cynefinDiagram-MW4NZA55-CkSLreFW.js} +1 -1
- package/console-app/assets/{dagre-VZM6K2ZE-BYFZSaSb.js → dagre-VZM6K2ZE-0ssqLoHs.js} +1 -1
- package/console-app/assets/{dagre-nXgDYqvf.js → dagre-WqgBlKb7.js} +1 -1
- package/console-app/assets/{diagram-7IWD3JNH-oDftiTp1.js → diagram-7IWD3JNH-DmRL3lmL.js} +1 -1
- package/console-app/assets/{diagram-B4RE2ZJO-Cbj-pPbH.js → diagram-B4RE2ZJO-Bsr9wG4I.js} +1 -1
- package/console-app/assets/{diagram-LBJQPF4R-Ch53oSKw.js → diagram-LBJQPF4R-DdMw1FSY.js} +1 -1
- package/console-app/assets/{diagram-Q27KOJAE-DA7K814v.js → diagram-Q27KOJAE-TPx5TB2B.js} +1 -1
- package/console-app/assets/{diagram-UB23O5K3-B-_C-ctS.js → diagram-UB23O5K3-e_1zSlZR.js} +1 -1
- package/console-app/assets/{ebnfDiagram-BXEA7PRR-DsOdsKXy.js → ebnfDiagram-BXEA7PRR-BACajh2b.js} +1 -1
- package/console-app/assets/{erDiagram-JOGREHBK-XB1mP5_A.js → erDiagram-JOGREHBK-CojomKqL.js} +1 -1
- package/console-app/assets/eventmodeling-45OFAUF4-DkN2KCrT.js +1 -0
- package/console-app/assets/flowDiagram-UKHOOZJN-DL0M9lBc.js +1 -0
- package/console-app/assets/{ganttDiagram-PKOTCBZU-knk0XSHi.js → ganttDiagram-PKOTCBZU-yoOX4Xj2.js} +1 -1
- package/console-app/assets/{gitGraph-TEB2WS4Q-COJnK2tM.js → gitGraph-TEB2WS4Q-BcUY5hIc.js} +1 -1
- package/console-app/assets/{gitGraphDiagram-DS77QQ5N-sF0v605q.js → gitGraphDiagram-DS77QQ5N-BtuIPjuB.js} +1 -1
- package/console-app/assets/{index-DMnbsgzs.js → index-CzWW052c.js} +151 -151
- package/console-app/assets/{info-DKCQHKI2-Cbatr0w6.js → info-DKCQHKI2-B-iR9PUz.js} +1 -1
- package/console-app/assets/{infoDiagram-6WML65LV-93TFPCu2.js → infoDiagram-6WML65LV-CuXKIFH2.js} +1 -1
- package/console-app/assets/{ishikawaDiagram-WSZJBQD7-BBR8_Qms.js → ishikawaDiagram-WSZJBQD7-CSueMFD6.js} +1 -1
- package/console-app/assets/{journeyDiagram-NVQOT4AX-zG55yDoc.js → journeyDiagram-NVQOT4AX-kvnKStZp.js} +1 -1
- package/console-app/assets/{kanban-definition-27J2QSJJ-DonGcEAY.js → kanban-definition-27J2QSJJ-CGGDEz30.js} +1 -1
- package/console-app/assets/{line-D1WdVm1S.js → line-mtMM5-xO.js} +1 -1
- package/console-app/assets/{linear-D2GQL4Cm.js → linear-CLSje0O_.js} +1 -1
- package/console-app/assets/{mermaid-parser.core-b4yKyO56.js → mermaid-parser.core-Cx6yvn3j.js} +3 -3
- package/console-app/assets/{mermaid.core-Cwfec1gr.js → mermaid.core-BebGyklS.js} +4 -4
- package/console-app/assets/{mindmap-definition-FAOFIHXS-D0G4yKgw.js → mindmap-definition-FAOFIHXS-C2_WUUJ9.js} +1 -1
- package/console-app/assets/{packet-7NZHBO7P-DDa4HL2T.js → packet-7NZHBO7P-Dh5yNCA8.js} +1 -1
- package/console-app/assets/{pegDiagram-VL7TDLO6-fPdN5VZs.js → pegDiagram-VL7TDLO6-XgUxesi8.js} +1 -1
- package/console-app/assets/{pie-RZYD4A2V-DRHURUqo.js → pie-RZYD4A2V-D2x2RAXI.js} +1 -1
- package/console-app/assets/{pieDiagram-7S7Q4E2Y-DMYn8ga_.js → pieDiagram-7S7Q4E2Y-Bbor0KbG.js} +1 -1
- package/console-app/assets/{quadrantDiagram-CIZ2JOQS-C190OamC.js → quadrantDiagram-CIZ2JOQS-DZmnMHpM.js} +1 -1
- package/console-app/assets/{radar-I7S5WNFK-Djvqzz9A.js → radar-I7S5WNFK-CPeriDtN.js} +1 -1
- package/console-app/assets/{railroad-3IZDKUUU-C9YvFeFq.js → railroad-3IZDKUUU-2iKAyaie.js} +1 -1
- package/console-app/assets/railroad-abnf-AHOZXSZD-D26xz4MM.js +1 -0
- package/console-app/assets/railroad-ebnf-EBAXGLYW-CCAiMPWc.js +1 -0
- package/console-app/assets/railroad-peg-LSFZ7HO6-BA1zcisq.js +1 -0
- package/console-app/assets/{railroadDiagram-AXF67PYL-IRFg1VrU.js → railroadDiagram-AXF67PYL-DVEqCXoo.js} +1 -1
- package/console-app/assets/{requirementDiagram-LRYGKXZP-L-7ubbcT.js → requirementDiagram-LRYGKXZP-CSgSNL8p.js} +1 -1
- package/console-app/assets/{sankeyDiagram-W5VNT64P-DBttV6Gt.js → sankeyDiagram-W5VNT64P-CFk11odN.js} +1 -1
- package/console-app/assets/{sequenceDiagram-SI44F4Z6-Bg15oKAB.js → sequenceDiagram-SI44F4Z6-Cb5u6FsJ.js} +1 -1
- package/console-app/assets/{src-DUC7tLWb.js → src-LceHEY_Q.js} +1 -1
- package/console-app/assets/{stateDiagram-OKZ733FA-PWl0XGs5.js → stateDiagram-OKZ733FA-DM1jWlkU.js} +1 -1
- package/console-app/assets/stateDiagram-v2-UEYNNEHI-COVnPYic.js +1 -0
- package/console-app/assets/{swimlanes-SLNWSIFB-CyXEtGBV.js → swimlanes-SLNWSIFB-DD6MchlE.js} +1 -1
- package/console-app/assets/swimlanesDiagram-ULZ7WXOC-B5q8iRCQ.js +8 -0
- package/console-app/assets/{timeline-definition-Z64GVDOM-BLA-DhBt.js → timeline-definition-Z64GVDOM-zu5cNnVv.js} +1 -1
- package/console-app/assets/{treeView-QDETBFTQ-Bfnmn2UY.js → treeView-QDETBFTQ-D_4IbvCG.js} +1 -1
- package/console-app/assets/{treemap-6X3UGDF4-DTA0wveO.js → treemap-6X3UGDF4-DNc6bjUc.js} +1 -1
- package/console-app/assets/{vennDiagram-T6HMQDX7-CLXYZln0.js → vennDiagram-T6HMQDX7-DfqoG28f.js} +1 -1
- package/console-app/assets/{wardley-OPB4EBWU-zwxqisG0.js → wardley-OPB4EBWU-BqpI2Lx-.js} +1 -1
- package/console-app/assets/{wardleyDiagram-T6FBY63Y-hKtKvNlv.js → wardleyDiagram-T6FBY63Y-CLIZSvNi.js} +1 -1
- package/console-app/assets/{xychartDiagram-ELKLHX3M-BGf8p4bo.js → xychartDiagram-ELKLHX3M-Cni-XXa6.js} +1 -1
- package/console-app/index.html +1 -1
- package/dist/.pikku/addon/index.d.ts +1 -1
- package/dist/.pikku/addon/index.js +1 -1
- package/dist/.pikku/addon/pikku-addon-types.gen.d.ts +1 -1
- package/dist/.pikku/addon/pikku-addon-types.gen.js +1 -1
- package/dist/.pikku/agent/index.d.ts +1 -1
- package/dist/.pikku/agent/index.js +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/agent/pikku-model-aliases.gen.js +1 -1
- package/dist/.pikku/auth/index.d.ts +1 -1
- package/dist/.pikku/auth/index.js +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.d.ts +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.js +1 -1
- package/dist/.pikku/channel/index.d.ts +1 -1
- package/dist/.pikku/channel/index.js +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/index.d.ts +1 -1
- package/dist/.pikku/cli/index.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +21 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.json +103 -0
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +103 -0
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/error/index.d.ts +1 -1
- package/dist/.pikku/error/index.js +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.d.ts +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.js +1 -1
- package/dist/.pikku/function/index.d.ts +1 -1
- package/dist/.pikku/function/index.js +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +79 -3
- package/dist/.pikku/function/pikku-functions.gen.js +1 -1
- package/dist/.pikku/gateway/index.d.ts +1 -1
- package/dist/.pikku/gateway/index.js +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.d.ts +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.js +1 -1
- package/dist/.pikku/http/index.d.ts +1 -1
- package/dist/.pikku/http/index.js +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/mcp/index.d.ts +1 -1
- package/dist/.pikku/mcp/index.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/middleware/index.d.ts +1 -1
- package/dist/.pikku/middleware/index.js +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.d.ts +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +1 -1
- package/dist/.pikku/queue/index.d.ts +1 -1
- package/dist/.pikku/queue/index.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +4 -0
- package/dist/.pikku/scenarios/index.d.ts +1 -1
- package/dist/.pikku/scenarios/index.js +1 -1
- package/dist/.pikku/scenarios/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-types.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
- package/dist/.pikku/scheduler/index.d.ts +1 -1
- package/dist/.pikku/scheduler/index.js +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +17 -1
- package/dist/.pikku/schemas/schemas/FabricFindingsClearInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsClearOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsFlushInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsFlushOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsListInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricFindingsListOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricReportInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricReportOutput.schema.json +1 -0
- package/dist/.pikku/scopes/index.d.ts +1 -1
- package/dist/.pikku/scopes/index.js +1 -1
- package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/index.d.ts +1 -1
- package/dist/.pikku/secrets/index.js +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/setup/index.d.ts +1 -1
- package/dist/.pikku/setup/index.js +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.d.ts +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.js +1 -1
- package/dist/.pikku/trigger/index.d.ts +1 -1
- package/dist/.pikku/trigger/index.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/index.d.ts +1 -1
- package/dist/.pikku/variables/index.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/index.d.ts +1 -1
- package/dist/.pikku/workflow/index.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/src/fabric/fabric-commands.d.ts +138 -0
- package/dist/src/fabric/fabric-commands.js +65 -0
- package/dist/src/fabric/functions/findings-clear.function.d.ts +12 -0
- package/dist/src/fabric/functions/findings-clear.function.js +17 -0
- package/dist/src/fabric/functions/findings-flush.function.d.ts +33 -0
- package/dist/src/fabric/functions/findings-flush.function.js +36 -0
- package/dist/src/fabric/functions/findings-list.function.d.ts +55 -0
- package/dist/src/fabric/functions/findings-list.function.js +52 -0
- package/dist/src/fabric/functions/report.function.d.ts +121 -0
- package/dist/src/fabric/functions/report.function.js +84 -0
- package/dist/src/fabric/lib/finding-spool.d.ts +56 -0
- package/dist/src/fabric/lib/finding-spool.js +105 -0
- package/dist/src/fabric/lib/finding.d.ts +92 -0
- package/dist/src/fabric/lib/finding.js +156 -0
- package/dist/src/fabric/lib/report-environment.d.ts +53 -0
- package/dist/src/fabric/lib/report-environment.js +119 -0
- package/dist/src/functions/commands/environment.d.ts +5 -0
- package/dist/src/functions/commands/persona.js +1 -0
- package/dist/src/functions/commands/scenario.js +1 -0
- package/dist/src/functions/validate/auth-plugin-checks.d.ts +1 -1
- package/dist/src/functions/validate/auth-plugin-checks.js +8 -5
- package/dist/src/functions/validate/persona-checks.js +8 -6
- package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +10 -5
- package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.d.ts +1 -1
- package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +3 -3
- package/dist/src/services.js +9 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/snippets.json +1 -1
- package/surface.json +2 -2
- package/console-app/assets/architecture-TIHT7OUA-DmG0bXDT.js +0 -1
- package/console-app/assets/channel-BgCT5gon.js +0 -1
- package/console-app/assets/chunk-XXDRQBXY-EP2C9tTO.js +0 -1
- package/console-app/assets/classDiagram-JCYQIIEL-D9wGqB4J.js +0 -1
- package/console-app/assets/classDiagram-v2-OCEON4UE-D9wGqB4J.js +0 -1
- package/console-app/assets/eventmodeling-45OFAUF4-NKFCZ8Fj.js +0 -1
- package/console-app/assets/flowDiagram-UKHOOZJN-BpdPkmum.js +0 -1
- package/console-app/assets/railroad-abnf-AHOZXSZD-B3CYVW4p.js +0 -1
- package/console-app/assets/railroad-ebnf-EBAXGLYW-DrZ2yF62.js +0 -1
- package/console-app/assets/railroad-peg-LSFZ7HO6-CWAmMyxd.js +0 -1
- package/console-app/assets/stateDiagram-v2-UEYNNEHI-Celbgz4u.js +0 -1
- package/console-app/assets/swimlanesDiagram-ULZ7WXOC-zxpNaB4U.js +0 -8
|
@@ -46,6 +46,10 @@ import { FabricValidate, renderValidate, } from './functions/validate.function.j
|
|
|
46
46
|
import { FabricSmoke, renderSmoke } from './functions/smoke.function.js';
|
|
47
47
|
import { FabricPublish } from './functions/publish.function.js';
|
|
48
48
|
import { FabricAdd } from './functions/add.function.js';
|
|
49
|
+
import { FabricReport } from './functions/report.function.js';
|
|
50
|
+
import { FabricFindingsList, renderFindingsList, } from './functions/findings-list.function.js';
|
|
51
|
+
import { FabricFindingsFlush } from './functions/findings-flush.function.js';
|
|
52
|
+
import { FabricFindingsClear } from './functions/findings-clear.function.js';
|
|
49
53
|
import { FabricAddonVerify, renderAddonVerify, } from './functions/addon-verify.function.js';
|
|
50
54
|
export const fabricCommands = defineCLICommands({
|
|
51
55
|
validate: pikkuCLICommand({
|
|
@@ -302,6 +306,67 @@ export const fabricCommands = defineCLICommands({
|
|
|
302
306
|
json: { description: 'Machine-readable output', default: false },
|
|
303
307
|
},
|
|
304
308
|
}),
|
|
309
|
+
report: pikkuCLICommand({
|
|
310
|
+
parameters: '[title]',
|
|
311
|
+
func: FabricReport,
|
|
312
|
+
description: 'Report a finding — something about pikku that cost time — to fabric',
|
|
313
|
+
options: {
|
|
314
|
+
stdin: {
|
|
315
|
+
description: 'Read the whole finding as JSON on stdin instead of from flags (prose survives the shell intact)',
|
|
316
|
+
default: false,
|
|
317
|
+
},
|
|
318
|
+
kind: {
|
|
319
|
+
description: 'product (fix pikku) or harness (fix the skill that misled you)',
|
|
320
|
+
},
|
|
321
|
+
model: { description: 'The model that hit this' },
|
|
322
|
+
expected: { description: 'What you expected pikku to do' },
|
|
323
|
+
actual: { description: 'What it did instead' },
|
|
324
|
+
skill: {
|
|
325
|
+
description: 'For a harness finding, the skill that misled you',
|
|
326
|
+
},
|
|
327
|
+
passage: { description: 'The passage in that skill it contradicts' },
|
|
328
|
+
command: { description: 'The command you ran' },
|
|
329
|
+
error: { description: "The error's message line, verbatim" },
|
|
330
|
+
repro: { description: 'The shortest way to reach it again' },
|
|
331
|
+
workaround: { description: 'What you did instead, inside the app' },
|
|
332
|
+
proposal: {
|
|
333
|
+
description: 'What pikku should do — named file and function, mechanism, suggested change',
|
|
334
|
+
},
|
|
335
|
+
tried: {
|
|
336
|
+
description: 'For an unresolved finding, what you tried and how each attempt failed',
|
|
337
|
+
},
|
|
338
|
+
unresolved: {
|
|
339
|
+
description: 'No workaround was found — a blocker, not a tax',
|
|
340
|
+
default: false,
|
|
341
|
+
},
|
|
342
|
+
area: { description: 'The part of pikku this is about' },
|
|
343
|
+
surface: { description: 'Where it showed up: local, deployed or both' },
|
|
344
|
+
cost: { description: 'What it cost, measured or estimated' },
|
|
345
|
+
run: { description: 'Run id, to group findings from one build' },
|
|
346
|
+
deployTarget: { description: 'The deploy target in use' },
|
|
347
|
+
},
|
|
348
|
+
}),
|
|
349
|
+
findings: {
|
|
350
|
+
description: 'Inspect the findings held locally because they could not be sent',
|
|
351
|
+
subcommands: {
|
|
352
|
+
list: pikkuCLICommand({
|
|
353
|
+
func: FabricFindingsList,
|
|
354
|
+
render: renderFindingsList,
|
|
355
|
+
description: 'List the findings queued locally, waiting to be sent',
|
|
356
|
+
}),
|
|
357
|
+
flush: pikkuCLICommand({
|
|
358
|
+
func: FabricFindingsFlush,
|
|
359
|
+
description: 'Send every finding queued locally',
|
|
360
|
+
options: {
|
|
361
|
+
apiUrl: { description: 'Override the fabric-api URL for this call' },
|
|
362
|
+
},
|
|
363
|
+
}),
|
|
364
|
+
clear: pikkuCLICommand({
|
|
365
|
+
func: FabricFindingsClear,
|
|
366
|
+
description: 'Discard every queued finding without sending it',
|
|
367
|
+
}),
|
|
368
|
+
},
|
|
369
|
+
},
|
|
305
370
|
metrics: pikkuCLICommand({
|
|
306
371
|
func: FabricMetrics,
|
|
307
372
|
description: 'Show request rate / error rate / latency for a stage',
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const FabricFindingsClearInput: z.ZodObject<{}, z.core.$strip>;
|
|
3
|
+
export declare const FabricFindingsClearOutput: z.ZodObject<{
|
|
4
|
+
dropped: z.ZodNumber;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
export declare const FabricFindingsClear: import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<Record<string, never>, {
|
|
7
|
+
dropped: number;
|
|
8
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<Record<string, never>, {
|
|
9
|
+
dropped: number;
|
|
10
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown> | import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<Record<string, never>, {
|
|
11
|
+
dropped: number;
|
|
12
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
3
|
+
import { clearSpool } from '../lib/finding-spool.js';
|
|
4
|
+
export const FabricFindingsClearInput = z.object({});
|
|
5
|
+
export const FabricFindingsClearOutput = z.object({
|
|
6
|
+
dropped: z.number(),
|
|
7
|
+
});
|
|
8
|
+
export const FabricFindingsClear = pikkuSessionlessFunc({
|
|
9
|
+
description: 'Discard every finding queued locally without sending it.',
|
|
10
|
+
input: FabricFindingsClearInput,
|
|
11
|
+
output: FabricFindingsClearOutput,
|
|
12
|
+
func: async () => {
|
|
13
|
+
const dropped = await clearSpool();
|
|
14
|
+
console.log(`[fabric] dropped ${dropped} queued finding(s)`);
|
|
15
|
+
return { dropped };
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const FabricFindingsFlushInput: z.ZodObject<{
|
|
3
|
+
apiUrl: z.ZodOptional<z.ZodString>;
|
|
4
|
+
}, z.core.$strip>;
|
|
5
|
+
export declare const FabricFindingsFlushOutput: z.ZodObject<{
|
|
6
|
+
sent: z.ZodNumber;
|
|
7
|
+
remaining: z.ZodNumber;
|
|
8
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
/**
|
|
11
|
+
* Explicitly asked for, so unlike `report` this one says plainly that it
|
|
12
|
+
* cannot run: someone who typed `flush` wants to know the login is missing,
|
|
13
|
+
* not to have the queue quietly stay put.
|
|
14
|
+
*/
|
|
15
|
+
export declare const FabricFindingsFlush: import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
16
|
+
apiUrl?: string | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
sent: number;
|
|
19
|
+
remaining: number;
|
|
20
|
+
reason?: string | undefined;
|
|
21
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<{
|
|
22
|
+
apiUrl?: string | undefined;
|
|
23
|
+
}, {
|
|
24
|
+
sent: number;
|
|
25
|
+
remaining: number;
|
|
26
|
+
reason?: string | undefined;
|
|
27
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown> | import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<{
|
|
28
|
+
apiUrl?: string | undefined;
|
|
29
|
+
}, {
|
|
30
|
+
sent: number;
|
|
31
|
+
remaining: number;
|
|
32
|
+
reason?: string | undefined;
|
|
33
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
3
|
+
import { resolveApiContext } from '../lib/config.js';
|
|
4
|
+
import { flushSpool } from '../lib/finding-spool.js';
|
|
5
|
+
export const FabricFindingsFlushInput = z.object({
|
|
6
|
+
apiUrl: z.string().optional(),
|
|
7
|
+
});
|
|
8
|
+
export const FabricFindingsFlushOutput = z.object({
|
|
9
|
+
sent: z.number(),
|
|
10
|
+
remaining: z.number(),
|
|
11
|
+
reason: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* Explicitly asked for, so unlike `report` this one says plainly that it
|
|
15
|
+
* cannot run: someone who typed `flush` wants to know the login is missing,
|
|
16
|
+
* not to have the queue quietly stay put.
|
|
17
|
+
*/
|
|
18
|
+
export const FabricFindingsFlush = pikkuSessionlessFunc({
|
|
19
|
+
description: 'Send every finding queued locally.',
|
|
20
|
+
input: FabricFindingsFlushInput,
|
|
21
|
+
output: FabricFindingsFlushOutput,
|
|
22
|
+
func: async (_services, { apiUrl: apiUrlOverride }) => {
|
|
23
|
+
const ctx = await resolveApiContext({ apiUrlOverride });
|
|
24
|
+
if (!ctx.token)
|
|
25
|
+
throw new Error('Not logged in. Run `pikku fabric login` first.');
|
|
26
|
+
const result = await flushSpool({
|
|
27
|
+
apiUrl: ctx.apiUrl,
|
|
28
|
+
token: ctx.token,
|
|
29
|
+
projectId: ctx.projectId,
|
|
30
|
+
});
|
|
31
|
+
console.log(result.remaining === 0
|
|
32
|
+
? `[fabric] sent ${result.sent} finding(s)`
|
|
33
|
+
: `[fabric] sent ${result.sent}, ${result.remaining} still queued (${result.reason})`);
|
|
34
|
+
return result;
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const FabricFindingsListInput: z.ZodObject<{}, z.core.$strip>;
|
|
3
|
+
export declare const FabricFindingsListOutput: z.ZodObject<{
|
|
4
|
+
findings: z.ZodArray<z.ZodObject<{
|
|
5
|
+
title: z.ZodString;
|
|
6
|
+
kind: z.ZodString;
|
|
7
|
+
reason: z.ZodString;
|
|
8
|
+
reportedAt: z.ZodString;
|
|
9
|
+
projectId: z.ZodNullable<z.ZodString>;
|
|
10
|
+
file: z.ZodString;
|
|
11
|
+
}, z.core.$strip>>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
/**
|
|
14
|
+
* What is waiting to be sent. Without this the spool is invisible, and an
|
|
15
|
+
* agent has no way to tell a finding that reached fabric from one still
|
|
16
|
+
* sitting on the machine.
|
|
17
|
+
*/
|
|
18
|
+
export declare const FabricFindingsList: import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<Record<string, never>, {
|
|
19
|
+
findings: {
|
|
20
|
+
title: string;
|
|
21
|
+
kind: string;
|
|
22
|
+
reason: string;
|
|
23
|
+
reportedAt: string;
|
|
24
|
+
projectId: string | null;
|
|
25
|
+
file: string;
|
|
26
|
+
}[];
|
|
27
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<Record<string, never>, {
|
|
28
|
+
findings: {
|
|
29
|
+
title: string;
|
|
30
|
+
kind: string;
|
|
31
|
+
reason: string;
|
|
32
|
+
reportedAt: string;
|
|
33
|
+
projectId: string | null;
|
|
34
|
+
file: string;
|
|
35
|
+
}[];
|
|
36
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown> | import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<Record<string, never>, {
|
|
37
|
+
findings: {
|
|
38
|
+
title: string;
|
|
39
|
+
kind: string;
|
|
40
|
+
reason: string;
|
|
41
|
+
reportedAt: string;
|
|
42
|
+
projectId: string | null;
|
|
43
|
+
file: string;
|
|
44
|
+
}[];
|
|
45
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>;
|
|
46
|
+
type QueuedFinding = {
|
|
47
|
+
title: string;
|
|
48
|
+
kind: string;
|
|
49
|
+
reason: string;
|
|
50
|
+
reportedAt: string;
|
|
51
|
+
};
|
|
52
|
+
export declare const renderFindingsList: (_s: unknown, { findings }: {
|
|
53
|
+
findings: QueuedFinding[];
|
|
54
|
+
}) => void;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
3
|
+
import { readSpool } from '../lib/finding-spool.js';
|
|
4
|
+
import { dim, table } from '../lib/output.js';
|
|
5
|
+
export const FabricFindingsListInput = z.object({});
|
|
6
|
+
export const FabricFindingsListOutput = z.object({
|
|
7
|
+
findings: z.array(z.object({
|
|
8
|
+
title: z.string(),
|
|
9
|
+
kind: z.string(),
|
|
10
|
+
reason: z.string(),
|
|
11
|
+
reportedAt: z.string(),
|
|
12
|
+
projectId: z.string().nullable(),
|
|
13
|
+
file: z.string(),
|
|
14
|
+
})),
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* What is waiting to be sent. Without this the spool is invisible, and an
|
|
18
|
+
* agent has no way to tell a finding that reached fabric from one still
|
|
19
|
+
* sitting on the machine.
|
|
20
|
+
*/
|
|
21
|
+
export const FabricFindingsList = pikkuSessionlessFunc({
|
|
22
|
+
description: 'List the findings queued locally, waiting to be sent.',
|
|
23
|
+
input: FabricFindingsListInput,
|
|
24
|
+
output: FabricFindingsListOutput,
|
|
25
|
+
func: async () => ({
|
|
26
|
+
findings: (await readSpool()).map((entry) => ({
|
|
27
|
+
title: entry.payload.title,
|
|
28
|
+
kind: entry.payload.kind,
|
|
29
|
+
reason: entry.reason,
|
|
30
|
+
reportedAt: entry.payload.reportedAt,
|
|
31
|
+
projectId: entry.projectId,
|
|
32
|
+
file: entry.file,
|
|
33
|
+
})),
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
export const renderFindingsList = (_s, { findings }) => {
|
|
37
|
+
console.log('');
|
|
38
|
+
if (findings.length === 0) {
|
|
39
|
+
console.log(dim(' Nothing queued — every finding you filed was sent.'));
|
|
40
|
+
console.log('');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.log(table(['REPORTED', 'KIND', 'HELD BECAUSE', 'TITLE'], findings.map((f) => [
|
|
44
|
+
f.reportedAt.slice(0, 16).replace('T', ' '),
|
|
45
|
+
f.kind,
|
|
46
|
+
f.reason,
|
|
47
|
+
f.title,
|
|
48
|
+
])));
|
|
49
|
+
console.log('');
|
|
50
|
+
console.log(dim(' `pikku fabric findings flush` sends them.'));
|
|
51
|
+
console.log('');
|
|
52
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Every field is optional here and the strictness lives in `FindingInput`,
|
|
4
|
+
* because `--stdin` supplies the whole finding at once and the flags then
|
|
5
|
+
* carry nothing. Whichever path was used, the same schema decides whether a
|
|
6
|
+
* finding is well-formed.
|
|
7
|
+
*/
|
|
8
|
+
export declare const FabricReportInput: z.ZodObject<{
|
|
9
|
+
title: z.ZodOptional<z.ZodString>;
|
|
10
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
11
|
+
product: "product";
|
|
12
|
+
harness: "harness";
|
|
13
|
+
}>>;
|
|
14
|
+
model: z.ZodOptional<z.ZodString>;
|
|
15
|
+
expected: z.ZodOptional<z.ZodString>;
|
|
16
|
+
actual: z.ZodOptional<z.ZodString>;
|
|
17
|
+
skill: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
18
|
+
passage: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
19
|
+
command: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
20
|
+
error: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
21
|
+
repro: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
22
|
+
workaround: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
23
|
+
proposal: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
24
|
+
tried: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
25
|
+
unresolved: z.ZodOptional<z.ZodOptional<z.ZodBoolean>>;
|
|
26
|
+
area: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
27
|
+
surface: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
|
|
28
|
+
local: "local";
|
|
29
|
+
deployed: "deployed";
|
|
30
|
+
both: "both";
|
|
31
|
+
}>>>;
|
|
32
|
+
cost: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
33
|
+
run: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
34
|
+
deployTarget: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
35
|
+
stdin: z.ZodOptional<z.ZodBoolean>;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
export declare const FabricReportOutput: z.ZodObject<{
|
|
38
|
+
sent: z.ZodBoolean;
|
|
39
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
40
|
+
spooled: z.ZodBoolean;
|
|
41
|
+
queued: z.ZodNumber;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
export declare const FabricReport: import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
44
|
+
title?: string | undefined;
|
|
45
|
+
kind?: "product" | "harness" | undefined;
|
|
46
|
+
model?: string | undefined;
|
|
47
|
+
expected?: string | undefined;
|
|
48
|
+
actual?: string | undefined;
|
|
49
|
+
skill?: string | undefined;
|
|
50
|
+
passage?: string | undefined;
|
|
51
|
+
command?: string | undefined;
|
|
52
|
+
error?: string | undefined;
|
|
53
|
+
repro?: string | undefined;
|
|
54
|
+
workaround?: string | undefined;
|
|
55
|
+
proposal?: string | undefined;
|
|
56
|
+
tried?: string | undefined;
|
|
57
|
+
unresolved?: boolean | undefined;
|
|
58
|
+
area?: string | undefined;
|
|
59
|
+
surface?: "local" | "deployed" | "both" | undefined;
|
|
60
|
+
cost?: string | undefined;
|
|
61
|
+
run?: string | undefined;
|
|
62
|
+
deployTarget?: string | undefined;
|
|
63
|
+
stdin?: boolean | undefined;
|
|
64
|
+
}, {
|
|
65
|
+
sent: boolean;
|
|
66
|
+
spooled: boolean;
|
|
67
|
+
queued: number;
|
|
68
|
+
reason?: string | undefined;
|
|
69
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<{
|
|
70
|
+
title?: string | undefined;
|
|
71
|
+
kind?: "product" | "harness" | undefined;
|
|
72
|
+
model?: string | undefined;
|
|
73
|
+
expected?: string | undefined;
|
|
74
|
+
actual?: string | undefined;
|
|
75
|
+
skill?: string | undefined;
|
|
76
|
+
passage?: string | undefined;
|
|
77
|
+
command?: string | undefined;
|
|
78
|
+
error?: string | undefined;
|
|
79
|
+
repro?: string | undefined;
|
|
80
|
+
workaround?: string | undefined;
|
|
81
|
+
proposal?: string | undefined;
|
|
82
|
+
tried?: string | undefined;
|
|
83
|
+
unresolved?: boolean | undefined;
|
|
84
|
+
area?: string | undefined;
|
|
85
|
+
surface?: "local" | "deployed" | "both" | undefined;
|
|
86
|
+
cost?: string | undefined;
|
|
87
|
+
run?: string | undefined;
|
|
88
|
+
deployTarget?: string | undefined;
|
|
89
|
+
stdin?: boolean | undefined;
|
|
90
|
+
}, {
|
|
91
|
+
sent: boolean;
|
|
92
|
+
spooled: boolean;
|
|
93
|
+
queued: number;
|
|
94
|
+
reason?: string | undefined;
|
|
95
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown> | import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<{
|
|
96
|
+
title?: string | undefined;
|
|
97
|
+
kind?: "product" | "harness" | undefined;
|
|
98
|
+
model?: string | undefined;
|
|
99
|
+
expected?: string | undefined;
|
|
100
|
+
actual?: string | undefined;
|
|
101
|
+
skill?: string | undefined;
|
|
102
|
+
passage?: string | undefined;
|
|
103
|
+
command?: string | undefined;
|
|
104
|
+
error?: string | undefined;
|
|
105
|
+
repro?: string | undefined;
|
|
106
|
+
workaround?: string | undefined;
|
|
107
|
+
proposal?: string | undefined;
|
|
108
|
+
tried?: string | undefined;
|
|
109
|
+
unresolved?: boolean | undefined;
|
|
110
|
+
area?: string | undefined;
|
|
111
|
+
surface?: "local" | "deployed" | "both" | undefined;
|
|
112
|
+
cost?: string | undefined;
|
|
113
|
+
run?: string | undefined;
|
|
114
|
+
deployTarget?: string | undefined;
|
|
115
|
+
stdin?: boolean | undefined;
|
|
116
|
+
}, {
|
|
117
|
+
sent: boolean;
|
|
118
|
+
spooled: boolean;
|
|
119
|
+
queued: number;
|
|
120
|
+
reason?: string | undefined;
|
|
121
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
3
|
+
import { resolveApiContext } from '../lib/config.js';
|
|
4
|
+
import { collectReportEnvironment } from '../lib/report-environment.js';
|
|
5
|
+
import { FindingInput, buildFindingPayload, parseFinding, parseFindingJson, postFinding, renderReceipt, validateFinding, } from '../lib/finding.js';
|
|
6
|
+
import { flushSpool, readSpool, spoolFinding } from '../lib/finding-spool.js';
|
|
7
|
+
/**
|
|
8
|
+
* Every field is optional here and the strictness lives in `FindingInput`,
|
|
9
|
+
* because `--stdin` supplies the whole finding at once and the flags then
|
|
10
|
+
* carry nothing. Whichever path was used, the same schema decides whether a
|
|
11
|
+
* finding is well-formed.
|
|
12
|
+
*/
|
|
13
|
+
export const FabricReportInput = FindingInput.partial().extend({
|
|
14
|
+
stdin: z.boolean().optional(),
|
|
15
|
+
});
|
|
16
|
+
export const FabricReportOutput = z.object({
|
|
17
|
+
sent: z.boolean(),
|
|
18
|
+
reason: z.string().optional(),
|
|
19
|
+
spooled: z.boolean(),
|
|
20
|
+
queued: z.number(),
|
|
21
|
+
});
|
|
22
|
+
const readStdin = async () => {
|
|
23
|
+
if (process.stdin.isTTY) {
|
|
24
|
+
throw new Error('--stdin expects the finding as JSON on standard input, and nothing was piped in.');
|
|
25
|
+
}
|
|
26
|
+
const chunks = [];
|
|
27
|
+
for await (const chunk of process.stdin)
|
|
28
|
+
chunks.push(Buffer.from(chunk));
|
|
29
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Every path that cannot send holds the finding instead. The states that stop
|
|
33
|
+
* a send — logged out, fabric unreachable — are the states a finding is most
|
|
34
|
+
* likely to be describing, so dropping it loses exactly the reports worth
|
|
35
|
+
* having.
|
|
36
|
+
*/
|
|
37
|
+
const hold = async (payload, reason, projectId, message) => {
|
|
38
|
+
await spoolFinding({ payload, reason, projectId });
|
|
39
|
+
const queued = (await readSpool()).length;
|
|
40
|
+
console.log(`[fabric] ${message} — finding queued (${queued} waiting, sent on your next report)`);
|
|
41
|
+
return { sent: false, reason, spooled: true, queued };
|
|
42
|
+
};
|
|
43
|
+
export const FabricReport = pikkuSessionlessFunc({
|
|
44
|
+
description: 'Report a finding — something about pikku that cost time — to fabric.',
|
|
45
|
+
input: FabricReportInput,
|
|
46
|
+
output: FabricReportOutput,
|
|
47
|
+
func: async (_services, { stdin, ...flags }) => {
|
|
48
|
+
const parsed = stdin
|
|
49
|
+
? parseFindingJson(await readStdin())
|
|
50
|
+
: parseFinding(flags);
|
|
51
|
+
if ('problems' in parsed) {
|
|
52
|
+
throw new Error(parsed.problems.join('\n'));
|
|
53
|
+
}
|
|
54
|
+
const problems = validateFinding(parsed.finding);
|
|
55
|
+
if (problems.length > 0) {
|
|
56
|
+
throw new Error(problems.join('\n'));
|
|
57
|
+
}
|
|
58
|
+
const payload = buildFindingPayload(parsed.finding, await collectReportEnvironment());
|
|
59
|
+
console.log(renderReceipt(payload));
|
|
60
|
+
const ctx = await resolveApiContext();
|
|
61
|
+
if (!ctx.token) {
|
|
62
|
+
return hold(payload, 'not-logged-in', ctx.projectId, 'not logged in');
|
|
63
|
+
}
|
|
64
|
+
const flushed = await flushSpool({
|
|
65
|
+
apiUrl: ctx.apiUrl,
|
|
66
|
+
token: ctx.token,
|
|
67
|
+
projectId: ctx.projectId,
|
|
68
|
+
});
|
|
69
|
+
if (flushed.sent > 0) {
|
|
70
|
+
console.log(`[fabric] sent ${flushed.sent} finding(s) held from earlier`);
|
|
71
|
+
}
|
|
72
|
+
const result = await postFinding({
|
|
73
|
+
apiUrl: ctx.apiUrl,
|
|
74
|
+
token: ctx.token,
|
|
75
|
+
projectId: ctx.projectId,
|
|
76
|
+
payload,
|
|
77
|
+
});
|
|
78
|
+
if (!result.sent) {
|
|
79
|
+
return hold(payload, result.reason ?? 'send-failed', ctx.projectId, `fabric did not accept it (${result.reason})`);
|
|
80
|
+
}
|
|
81
|
+
console.log('[fabric] finding sent');
|
|
82
|
+
return { sent: true, spooled: false, queued: flushed.remaining };
|
|
83
|
+
},
|
|
84
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type FindingPayload } from './finding.js';
|
|
2
|
+
/**
|
|
3
|
+
* A finding that could not be sent when it was filed, held until it can be.
|
|
4
|
+
*
|
|
5
|
+
* The cases that keep a finding from leaving — no token, no linked project, a
|
|
6
|
+
* fabric that is down — are the same cases the finding is most likely to be
|
|
7
|
+
* about: a scaffold that never got far enough to log in is exactly the thing
|
|
8
|
+
* worth hearing about, and printing it and dropping it loses it. The spool
|
|
9
|
+
* lives in `~/.fabric`, not the repo, so nothing goes stale on an abandoned
|
|
10
|
+
* branch and git never sees it.
|
|
11
|
+
*/
|
|
12
|
+
export interface SpooledFinding {
|
|
13
|
+
file: string;
|
|
14
|
+
spooledAt: string;
|
|
15
|
+
reason: string;
|
|
16
|
+
projectId: string | null;
|
|
17
|
+
payload: FindingPayload;
|
|
18
|
+
}
|
|
19
|
+
/** Oldest entries past this are dropped, so a logged-out machine stays bounded. */
|
|
20
|
+
export declare const SPOOL_LIMIT = 100;
|
|
21
|
+
export declare function spoolDir(): string;
|
|
22
|
+
export declare function spoolFinding(entry: {
|
|
23
|
+
payload: FindingPayload;
|
|
24
|
+
reason: string;
|
|
25
|
+
projectId: string | null;
|
|
26
|
+
}): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Chronological, by the timestamp inside each finding rather than the one its
|
|
29
|
+
* name carries — the name is for a human reading the directory, and ordering
|
|
30
|
+
* the queue by it would make the send order a property of how a filename
|
|
31
|
+
* happens to sort. A file that no longer parses is skipped rather than thrown
|
|
32
|
+
* for: one corrupt entry is not a reason to lose the rest, or to fail the
|
|
33
|
+
* command that happened to notice.
|
|
34
|
+
*/
|
|
35
|
+
export declare function readSpool(): Promise<SpooledFinding[]>;
|
|
36
|
+
export declare function clearSpool(): Promise<number>;
|
|
37
|
+
export interface FlushResult {
|
|
38
|
+
sent: number;
|
|
39
|
+
remaining: number;
|
|
40
|
+
reason?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Drain the spool oldest-first, stopping at the first entry fabric does not
|
|
44
|
+
* accept — a refusal usually means the next one will be refused too, and
|
|
45
|
+
* hammering an endpoint that just said no is the wrong thing for a command
|
|
46
|
+
* whose real job is something else.
|
|
47
|
+
*
|
|
48
|
+
* An entry keeps the project it was filed against; one spooled before the repo
|
|
49
|
+
* was linked adopts the project linked now, and sends without one if there is
|
|
50
|
+
* still none.
|
|
51
|
+
*/
|
|
52
|
+
export declare function flushSpool(ctx: {
|
|
53
|
+
apiUrl: string;
|
|
54
|
+
token: string;
|
|
55
|
+
projectId: string | null;
|
|
56
|
+
}): Promise<FlushResult>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { randomBytes } from 'node:crypto';
|
|
6
|
+
import { postFinding } from './finding.js';
|
|
7
|
+
/** Oldest entries past this are dropped, so a logged-out machine stays bounded. */
|
|
8
|
+
export const SPOOL_LIMIT = 100;
|
|
9
|
+
export function spoolDir() {
|
|
10
|
+
return (process.env.FABRIC_FINDINGS_DIR ?? join(homedir(), '.fabric', 'findings'));
|
|
11
|
+
}
|
|
12
|
+
export async function spoolFinding(entry) {
|
|
13
|
+
const dir = spoolDir();
|
|
14
|
+
await mkdir(dir, { recursive: true });
|
|
15
|
+
const stamp = entry.payload.reportedAt.replace(/[:.]/g, '-');
|
|
16
|
+
const file = join(dir, `${stamp}-${randomBytes(3).toString('hex')}.json`);
|
|
17
|
+
await writeFile(file, JSON.stringify({
|
|
18
|
+
spooledAt: new Date().toISOString(),
|
|
19
|
+
reason: entry.reason,
|
|
20
|
+
projectId: entry.projectId,
|
|
21
|
+
payload: entry.payload,
|
|
22
|
+
}, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 });
|
|
23
|
+
await pruneSpool();
|
|
24
|
+
return file;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Chronological, by the timestamp inside each finding rather than the one its
|
|
28
|
+
* name carries — the name is for a human reading the directory, and ordering
|
|
29
|
+
* the queue by it would make the send order a property of how a filename
|
|
30
|
+
* happens to sort. A file that no longer parses is skipped rather than thrown
|
|
31
|
+
* for: one corrupt entry is not a reason to lose the rest, or to fail the
|
|
32
|
+
* command that happened to notice.
|
|
33
|
+
*/
|
|
34
|
+
export async function readSpool() {
|
|
35
|
+
const dir = spoolDir();
|
|
36
|
+
if (!existsSync(dir))
|
|
37
|
+
return [];
|
|
38
|
+
const names = (await readdir(dir)).filter((n) => n.endsWith('.json'));
|
|
39
|
+
const entries = [];
|
|
40
|
+
for (const name of names) {
|
|
41
|
+
const file = join(dir, name);
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(await readFile(file, 'utf8'));
|
|
44
|
+
if (!parsed?.payload)
|
|
45
|
+
continue;
|
|
46
|
+
entries.push({
|
|
47
|
+
file,
|
|
48
|
+
spooledAt: parsed.spooledAt ?? '',
|
|
49
|
+
reason: parsed.reason ?? 'unknown',
|
|
50
|
+
projectId: parsed.projectId ?? null,
|
|
51
|
+
payload: parsed.payload,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return entries.sort((a, b) => a.payload.reportedAt.localeCompare(b.payload.reportedAt) ||
|
|
59
|
+
a.file.localeCompare(b.file));
|
|
60
|
+
}
|
|
61
|
+
export async function clearSpool() {
|
|
62
|
+
const entries = await readSpool();
|
|
63
|
+
for (const entry of entries)
|
|
64
|
+
await rm(entry.file, { force: true });
|
|
65
|
+
return entries.length;
|
|
66
|
+
}
|
|
67
|
+
async function pruneSpool() {
|
|
68
|
+
const entries = await readSpool();
|
|
69
|
+
const excess = Math.max(0, entries.length - SPOOL_LIMIT);
|
|
70
|
+
for (const entry of entries.slice(0, excess)) {
|
|
71
|
+
await rm(entry.file, { force: true });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Drain the spool oldest-first, stopping at the first entry fabric does not
|
|
76
|
+
* accept — a refusal usually means the next one will be refused too, and
|
|
77
|
+
* hammering an endpoint that just said no is the wrong thing for a command
|
|
78
|
+
* whose real job is something else.
|
|
79
|
+
*
|
|
80
|
+
* An entry keeps the project it was filed against; one spooled before the repo
|
|
81
|
+
* was linked adopts the project linked now, and sends without one if there is
|
|
82
|
+
* still none.
|
|
83
|
+
*/
|
|
84
|
+
export async function flushSpool(ctx) {
|
|
85
|
+
const entries = await readSpool();
|
|
86
|
+
let sent = 0;
|
|
87
|
+
for (const [index, entry] of entries.entries()) {
|
|
88
|
+
const result = await postFinding({
|
|
89
|
+
apiUrl: ctx.apiUrl,
|
|
90
|
+
token: ctx.token,
|
|
91
|
+
projectId: entry.projectId ?? ctx.projectId,
|
|
92
|
+
payload: entry.payload,
|
|
93
|
+
});
|
|
94
|
+
if (!result.sent) {
|
|
95
|
+
return {
|
|
96
|
+
sent,
|
|
97
|
+
remaining: entries.length - index,
|
|
98
|
+
reason: result.reason,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
await rm(entry.file, { force: true });
|
|
102
|
+
sent++;
|
|
103
|
+
}
|
|
104
|
+
return { sent, remaining: 0 };
|
|
105
|
+
}
|