@oscharko-dev/keiko 0.2.0-beta.7 → 0.2.0-beta.9
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/dist/ui/csp-hashes.json +14 -14
- package/dist/ui/static/404.html +1 -1
- package/dist/ui/static/__next.__PAGE__.txt +2 -2
- package/dist/ui/static/__next._full.txt +3 -3
- package/dist/ui/static/__next._head.txt +1 -1
- package/dist/ui/static/__next._index.txt +2 -2
- package/dist/ui/static/__next._tree.txt +2 -2
- package/dist/ui/static/_next/static/chunks/06-q1ntr51v8r.js +1 -0
- package/dist/ui/static/_next/static/chunks/0y9qlvrxsyign.js +109 -0
- package/dist/ui/static/_next/static/chunks/1h0v66-p9cx19.css +1 -0
- package/dist/ui/static/_next/static/chunks/3ewv4mguqzooj.js +1 -0
- package/dist/ui/static/_not-found/__next._full.txt +2 -2
- package/dist/ui/static/_not-found/__next._head.txt +1 -1
- package/dist/ui/static/_not-found/__next._index.txt +2 -2
- package/dist/ui/static/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/dist/ui/static/_not-found/__next._not-found.txt +1 -1
- package/dist/ui/static/_not-found/__next._tree.txt +2 -2
- package/dist/ui/static/_not-found.html +1 -1
- package/dist/ui/static/_not-found.txt +2 -2
- package/dist/ui/static/fonts/OFL.txt +93 -0
- package/dist/ui/static/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
- package/dist/ui/static/index.html +1 -1
- package/dist/ui/static/index.txt +3 -3
- package/dist/ui/static/launch/__next._full.txt +3 -3
- package/dist/ui/static/launch/__next._head.txt +1 -1
- package/dist/ui/static/launch/__next._index.txt +2 -2
- package/dist/ui/static/launch/__next._tree.txt +2 -2
- package/dist/ui/static/launch/__next.launch.__PAGE__.txt +2 -2
- package/dist/ui/static/launch/__next.launch.txt +1 -1
- package/dist/ui/static/launch.html +1 -1
- package/dist/ui/static/launch.txt +3 -3
- package/dist/ui/static/local-knowledge/__next._full.txt +3 -3
- package/dist/ui/static/local-knowledge/__next._head.txt +1 -1
- package/dist/ui/static/local-knowledge/__next._index.txt +2 -2
- package/dist/ui/static/local-knowledge/__next._tree.txt +2 -2
- package/dist/ui/static/local-knowledge/__next.local-knowledge.__PAGE__.txt +2 -2
- package/dist/ui/static/local-knowledge/__next.local-knowledge.txt +1 -1
- package/dist/ui/static/local-knowledge/capsule/__next._full.txt +3 -3
- package/dist/ui/static/local-knowledge/capsule/__next._head.txt +1 -1
- package/dist/ui/static/local-knowledge/capsule/__next._index.txt +2 -2
- package/dist/ui/static/local-knowledge/capsule/__next._tree.txt +2 -2
- package/dist/ui/static/local-knowledge/capsule/__next.local-knowledge.capsule.__PAGE__.txt +2 -2
- package/dist/ui/static/local-knowledge/capsule/__next.local-knowledge.capsule.txt +1 -1
- package/dist/ui/static/local-knowledge/capsule/__next.local-knowledge.txt +1 -1
- package/dist/ui/static/local-knowledge/capsule.html +1 -1
- package/dist/ui/static/local-knowledge/capsule.txt +3 -3
- package/dist/ui/static/local-knowledge.html +1 -1
- package/dist/ui/static/local-knowledge.txt +3 -3
- package/dist/ui/static/memoriaviva/__next._full.txt +2 -2
- package/dist/ui/static/memoriaviva/__next._head.txt +1 -1
- package/dist/ui/static/memoriaviva/__next._index.txt +2 -2
- package/dist/ui/static/memoriaviva/__next._tree.txt +2 -2
- package/dist/ui/static/memoriaviva/__next.memoriaviva.__PAGE__.txt +1 -1
- package/dist/ui/static/memoriaviva/__next.memoriaviva.txt +1 -1
- package/dist/ui/static/memoriaviva/consolidation/__next._full.txt +2 -2
- package/dist/ui/static/memoriaviva/consolidation/__next._head.txt +1 -1
- package/dist/ui/static/memoriaviva/consolidation/__next._index.txt +2 -2
- package/dist/ui/static/memoriaviva/consolidation/__next._tree.txt +2 -2
- package/dist/ui/static/memoriaviva/consolidation/__next.memoriaviva.consolidation.__PAGE__.txt +1 -1
- package/dist/ui/static/memoriaviva/consolidation/__next.memoriaviva.consolidation.txt +1 -1
- package/dist/ui/static/memoriaviva/consolidation/__next.memoriaviva.txt +1 -1
- package/dist/ui/static/memoriaviva/consolidation.html +1 -1
- package/dist/ui/static/memoriaviva/consolidation.txt +2 -2
- package/dist/ui/static/memoriaviva/detail/__next._full.txt +2 -2
- package/dist/ui/static/memoriaviva/detail/__next._head.txt +1 -1
- package/dist/ui/static/memoriaviva/detail/__next._index.txt +2 -2
- package/dist/ui/static/memoriaviva/detail/__next._tree.txt +2 -2
- package/dist/ui/static/memoriaviva/detail/__next.memoriaviva.detail.__PAGE__.txt +1 -1
- package/dist/ui/static/memoriaviva/detail/__next.memoriaviva.detail.txt +1 -1
- package/dist/ui/static/memoriaviva/detail/__next.memoriaviva.txt +1 -1
- package/dist/ui/static/memoriaviva/detail.html +1 -1
- package/dist/ui/static/memoriaviva/detail.txt +2 -2
- package/dist/ui/static/memoriaviva/review-queue/__next._full.txt +2 -2
- package/dist/ui/static/memoriaviva/review-queue/__next._head.txt +1 -1
- package/dist/ui/static/memoriaviva/review-queue/__next._index.txt +2 -2
- package/dist/ui/static/memoriaviva/review-queue/__next._tree.txt +2 -2
- package/dist/ui/static/memoriaviva/review-queue/__next.memoriaviva.review-queue.__PAGE__.txt +1 -1
- package/dist/ui/static/memoriaviva/review-queue/__next.memoriaviva.review-queue.txt +1 -1
- package/dist/ui/static/memoriaviva/review-queue/__next.memoriaviva.txt +1 -1
- package/dist/ui/static/memoriaviva/review-queue.html +1 -1
- package/dist/ui/static/memoriaviva/review-queue.txt +2 -2
- package/dist/ui/static/memoriaviva.html +1 -1
- package/dist/ui/static/memoriaviva.txt +2 -2
- package/dist/ui/static/sw.js +7 -3
- package/node_modules/@oscharko-dev/keiko-cli/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-cli/dist/memory.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-cli/dist/memory.js +4 -5
- package/node_modules/@oscharko-dev/keiko-cli/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/index.d.ts +2 -2
- package/node_modules/@oscharko-dev/keiko-contracts/dist/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/index.js +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/bffWire.d.ts +36 -4
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/bffWire.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/index.d.ts +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-evaluations/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-evaluations/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/dist/index.d.ts +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/dist/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/dist/qualityIntelligence/figmaSnapshot/schema.d.ts +15 -0
- package/node_modules/@oscharko-dev/keiko-evidence/dist/qualityIntelligence/figmaSnapshot/schema.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/dist/qualityIntelligence/figmaSnapshot/schema.js +13 -3
- package/node_modules/@oscharko-dev/keiko-evidence/dist/qualityIntelligence/figmaSnapshot/store.d.ts +13 -0
- package/node_modules/@oscharko-dev/keiko-evidence/dist/qualityIntelligence/figmaSnapshot/store.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/dist/qualityIntelligence/figmaSnapshot/store.js +46 -2
- package/node_modules/@oscharko-dev/keiko-evidence/dist/qualityIntelligence/index.d.ts +2 -2
- package/node_modules/@oscharko-dev/keiko-evidence/dist/qualityIntelligence/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-harness/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-harness/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/parsers/pdf-parser.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/parsers/pdf-parser.js +0 -10
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/parsers/types.d.ts +2 -2
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/parsers/types.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/parsers/types.js +3 -3
- package/node_modules/@oscharko-dev/keiko-local-knowledge/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-capture/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-consolidation/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/index.d.ts +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/index.js +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/maintenance.d.ts +2 -16
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/maintenance.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/maintenance.js +49 -48
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/retention.d.ts +2 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/retention.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/dist/retention.js +15 -0
- package/node_modules/@oscharko-dev/keiko-memory-governance/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/decay.d.ts +2 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/decay.d.ts.map +1 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/decay.js +22 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/diversity.d.ts +8 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/diversity.d.ts.map +1 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/diversity.js +87 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/index.d.ts +4 -2
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/index.js +4 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/ranking.d.ts +5 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/ranking.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/ranking.js +140 -21
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/recency.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/recency.js +4 -10
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/retrieve.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/retrieve.js +11 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/strength.d.ts +9 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/strength.d.ts.map +1 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/strength.js +51 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/types.d.ts +11 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/types.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/dist/types.js +7 -0
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/access.d.ts +3 -0
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/access.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/access.js +31 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/schema.d.ts +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/schema.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/schema.js +16 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/types.d.ts +1 -0
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/types.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/vault.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/vault.js +4 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-model-gateway/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-model-gateway/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/figma/screenIrTestBaseline.d.ts +8 -0
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/figma/screenIrTestBaseline.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/figma/screenIrTestBaseline.js +9 -5
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/testDesignModel.d.ts +6 -0
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/testDesignModel.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/testDesignModel.js +116 -21
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/testQualityRubric.d.ts +6 -0
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/testQualityRubric.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/testQualityRubric.js +12 -0
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/validation.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/domain/validation.js +8 -7
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/generation/parseGeneratedCandidates.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/generation/parseGeneratedCandidates.js +29 -7
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/generation/prompt.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/generation/prompt.js +61 -24
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/index.d.ts +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/index.js +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-sdk/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-sdk/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-security/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-security/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/chat-handlers.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/chat-handlers.js +44 -65
- package/node_modules/@oscharko-dev/keiko-server/dist/conversation-prompt.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/conversation-prompt.js +2 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/deps.d.ts +2 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/deps.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/deps.js +1 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/gateway-setup.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/gateway-setup.js +333 -70
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-orchestrator.d.ts +1 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-orchestrator.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-orchestrator.js +410 -18
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-prompt.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-prompt.js +1 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-qa-hybrid.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-qa-hybrid.js +7 -5
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-qa-multi-source.js +4 -3
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-qa.d.ts +1 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-qa.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/grounded-qa.js +4 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/local-knowledge-grounded-qa.d.ts +1 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/local-knowledge-grounded-qa.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/local-knowledge-grounded-qa.js +8 -3
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-conv-handlers.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-conv-handlers.js +34 -5
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-embedding.d.ts +12 -2
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-embedding.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-embedding.js +127 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-handlers.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-handlers.js +40 -11
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-maintenance-handlers.d.ts +16 -3
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-maintenance-handlers.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-maintenance-handlers.js +72 -50
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-retrieval-signals.d.ts +12 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-retrieval-signals.d.ts.map +1 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-retrieval-signals.js +84 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-salience.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-salience.js +11 -6
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaConnector.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaConnector.js +9 -4
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaScopedPagination.d.ts +6 -5
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaScopedPagination.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaScopedPagination.js +10 -9
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotBuilder.d.ts +2 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotBuilder.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotBuilder.js +62 -26
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotHash.d.ts +2 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotHash.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotHash.js +6 -3
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotTypes.d.ts +14 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotTypes.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts +33 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figmaSnapshotRoutes.js +263 -5
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figmaSnapshotScreenIds.d.ts +19 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figmaSnapshotScreenIds.d.ts.map +1 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figmaSnapshotScreenIds.js +75 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/judgePort.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/judgePort.js +13 -12
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/modelSelection.d.ts +6 -6
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/modelSelection.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/modelSelection.js +12 -7
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/reCheckRoutes.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/reCheckRoutes.js +34 -3
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runIngestion.d.ts +4 -2
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runIngestion.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runIngestion.js +222 -35
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runRoutes.d.ts +7 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runRoutes.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runRoutes.js +68 -16
- package/node_modules/@oscharko-dev/keiko-server/dist/routes.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/routes.js +7 -1
- package/node_modules/@oscharko-dev/keiko-server/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-tools/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-tools/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-verification/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-verification/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/anchors.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/anchors.js +45 -0
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/index.d.ts +2 -0
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/index.js +1 -0
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/intent.d.ts +8 -0
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/intent.d.ts.map +1 -0
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/intent.js +140 -0
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/plan.d.ts +2 -0
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/plan.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/planner/plan.js +21 -5
- package/node_modules/@oscharko-dev/keiko-workflows/dist/qualityIntelligence/modelRoutedTestDesign.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/qualityIntelligence/modelRoutedTestDesign.js +86 -40
- package/node_modules/@oscharko-dev/keiko-workflows/dist/ranking/rank.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/ranking/rank.js +9 -0
- package/node_modules/@oscharko-dev/keiko-workflows/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/index.d.ts +1 -0
- package/node_modules/@oscharko-dev/keiko-workspace/dist/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearch.d.ts +3 -0
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearch.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearch.js +23 -6
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchMatchers.d.ts +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchMatchers.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchMatchers.js +24 -3
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchPolicy.d.ts +34 -0
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchPolicy.d.ts.map +1 -0
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchPolicy.js +342 -0
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchScan.d.ts +6 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchScan.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/repoSearchScan.js +57 -9
- package/node_modules/@oscharko-dev/keiko-workspace/package.json +1 -1
- package/package.json +2 -1
- package/dist/ui/static/_next/static/chunks/0-qhhdvxg2j_y.js +0 -1
- package/dist/ui/static/_next/static/chunks/0ke4ratkgvcxo.css +0 -1
- package/dist/ui/static/_next/static/chunks/3vf3oh2-sl2nc.js +0 -1
- package/dist/ui/static/_next/static/chunks/3wmd4-2vznp2g.js +0 -106
- /package/dist/ui/static/_next/static/{frhs0YcUqCPLHal-wHjDP → a5sUbXeTgQ9A2LRTMu_Q_}/_buildManifest.js +0 -0
- /package/dist/ui/static/_next/static/{frhs0YcUqCPLHal-wHjDP → a5sUbXeTgQ9A2LRTMu_Q_}/_clientMiddlewareManifest.js +0 -0
- /package/dist/ui/static/_next/static/{frhs0YcUqCPLHal-wHjDP → a5sUbXeTgQ9A2LRTMu_Q_}/_ssgManifest.js +0 -0
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
// 2. downloads the PNG bytes from that ephemeral url via the injectable render port (no auth
|
|
8
8
|
// header — the url is pre-signed);
|
|
9
9
|
// 3. assembles the immutable Snapshot value: per-screen IR + image + deterministic integrity
|
|
10
|
-
// hashes + provenance, with a `skippedScreens` list
|
|
10
|
+
// hashes + provenance, with a `skippedScreens` list plus structural-only IR rows for any
|
|
11
|
+
// screen that failed to render.
|
|
11
12
|
//
|
|
12
13
|
// Once this returns, the Snapshot is the communication boundary: nothing downstream contacts
|
|
13
14
|
// Figma. The token flows ONLY into the images-call header; it never reaches the snapshot value,
|
|
@@ -16,7 +17,7 @@ import { FigmaConnectorError } from "./figmaConnectorErrors.js";
|
|
|
16
17
|
import { mapWithConcurrency } from "./figmaConcurrency.js";
|
|
17
18
|
import { classifyTokenFailure } from "./figmaTokenSource.js";
|
|
18
19
|
import { DEFAULT_FIGMA_RETRY_POLICY, fetchWithBackoff, realFigmaRetrySleep, } from "./figmaRetry.js";
|
|
19
|
-
import { hashBytes, hashScreen, hashSnapshot } from "./figmaSnapshotHash.js";
|
|
20
|
+
import { hashBytes, hashScreen, hashSnapshot, hashStructuralScreen } from "./figmaSnapshotHash.js";
|
|
20
21
|
import { DEFAULT_SCOPED_PAGINATION_LIMITS, SCOPED_PAGINATION_LIMIT_CEILINGS, } from "./figmaScopedPagination.js";
|
|
21
22
|
const FIGMA_API_ORIGIN = "https://api.figma.com";
|
|
22
23
|
const SNAPSHOT_SCHEMA_VERSION = 1;
|
|
@@ -130,15 +131,24 @@ const extractImageUrls = (json) => {
|
|
|
130
131
|
}
|
|
131
132
|
return out;
|
|
132
133
|
};
|
|
134
|
+
// Figma's render endpoint can reject a subset of otherwise readable screen node ids with a client
|
|
135
|
+
// status (observed on large boards where some detected screen frames cannot be rendered). That is a
|
|
136
|
+
// renderability problem, not an auth/egress/build integrity problem: keep the snapshot usable by
|
|
137
|
+
// returning an empty render-url map for that batch so the affected screens become structural-only.
|
|
138
|
+
// Auth/scope/proxy/rate-limit/upstream failures remain hard coded errors below.
|
|
139
|
+
const isRenderEndpointSoftFailure = (status) => status === 400 || status === 404 || status === 422;
|
|
133
140
|
// Resolve one `/v1/images` batch to its ephemeral-url map. The fetch is wrapped in the deterministic
|
|
134
|
-
// 429 backoff;
|
|
135
|
-
//
|
|
136
|
-
//
|
|
141
|
+
// 429 backoff; auth/scope/upstream non-2xx responses are hard coded errors, while renderability
|
|
142
|
+
// client failures degrade this batch to structural-only. A 2xx with a malformed body is a transient
|
|
143
|
+
// render-overload signal that is retried up to MAX_RENDER_BODY_RETRIES, then degrades to an empty map
|
|
144
|
+
// so the affected screens skip (render-url-missing) instead of aborting the build (F8).
|
|
137
145
|
const resolveRenderBatch = async (input, batch, policy, sleep) => {
|
|
138
146
|
const requestUrl = buildImagesUrl(input.provenance.fileKey, batch, input.provenance.version);
|
|
139
147
|
for (let attempt = 0;; attempt += 1) {
|
|
140
148
|
const response = await fetchWithBackoff(() => input.imagesPort({ url: requestUrl, headers: { "X-Figma-Token": input.token } }), policy, sleep);
|
|
141
149
|
if (response.status < 200 || response.status >= 300) {
|
|
150
|
+
if (isRenderEndpointSoftFailure(response.status))
|
|
151
|
+
return {};
|
|
142
152
|
throw statusToError(response.status, response.json);
|
|
143
153
|
}
|
|
144
154
|
const map = extractImageUrls(response.json);
|
|
@@ -164,8 +174,14 @@ const requestRenderUrls = async (input, screenIds) => {
|
|
|
164
174
|
}
|
|
165
175
|
return urls;
|
|
166
176
|
};
|
|
167
|
-
const
|
|
168
|
-
skipped: { screenId, reason },
|
|
177
|
+
const structuralOnly = (ir, reason) => ({
|
|
178
|
+
skipped: { screenId: ir.id, reason },
|
|
179
|
+
structuralScreen: {
|
|
180
|
+
screenId: ir.id,
|
|
181
|
+
ir,
|
|
182
|
+
reason,
|
|
183
|
+
integrityHash: hashStructuralScreen(ir.id, ir),
|
|
184
|
+
},
|
|
169
185
|
});
|
|
170
186
|
// Classifies a finished render download into a skip reason, or null when the bytes are usable.
|
|
171
187
|
const renderSkipReason = (response, maxBytes) => {
|
|
@@ -201,18 +217,18 @@ const classifyRenderError = (screenId, err) => {
|
|
|
201
217
|
if (err instanceof FigmaConnectorError) {
|
|
202
218
|
if (RENDER_EGRESS_ABORT_CODES.has(err.code))
|
|
203
219
|
throw err;
|
|
204
|
-
return
|
|
220
|
+
return { skipped: { screenId, reason: `render-fetch-failed:${err.code}` } };
|
|
205
221
|
}
|
|
206
|
-
return
|
|
222
|
+
return { skipped: { screenId, reason: "render-fetch-failed" } };
|
|
207
223
|
};
|
|
208
224
|
// Downloads one screen's render bytes and classifies the result into a kept screen or a skip.
|
|
209
225
|
// A single screen failing after retries degrades to a skip (partial render), never aborting.
|
|
210
226
|
// Exception: hard egress errors (TLS/proxy misconfiguration) abort via classifyRenderError.
|
|
211
227
|
const resolveScreen = async (input, ir, renderUrl) => {
|
|
212
228
|
if (renderUrl === null)
|
|
213
|
-
return
|
|
229
|
+
return structuralOnly(ir, "render-url-missing");
|
|
214
230
|
if (!isRenderUrlSafe(renderUrl))
|
|
215
|
-
return
|
|
231
|
+
return structuralOnly(ir, "render-url-blocked");
|
|
216
232
|
const maxBytes = input.maxImageBytes ?? DEFAULT_MAX_IMAGE_BYTES;
|
|
217
233
|
const policy = input.retryPolicy ?? DEFAULT_FIGMA_RETRY_POLICY;
|
|
218
234
|
const sleep = input.sleep ?? realFigmaRetrySleep;
|
|
@@ -221,11 +237,15 @@ const resolveScreen = async (input, ir, renderUrl) => {
|
|
|
221
237
|
response = await fetchWithBackoff(() => input.renderPort({ url: renderUrl, headers: {} }), policy, sleep);
|
|
222
238
|
}
|
|
223
239
|
catch (err) {
|
|
224
|
-
|
|
240
|
+
const classified = classifyRenderError(ir.id, err);
|
|
241
|
+
if (classified.skipped !== undefined) {
|
|
242
|
+
return structuralOnly(ir, classified.skipped.reason);
|
|
243
|
+
}
|
|
244
|
+
return classified;
|
|
225
245
|
}
|
|
226
246
|
const reason = renderSkipReason(response, maxBytes);
|
|
227
247
|
if (reason !== null)
|
|
228
|
-
return
|
|
248
|
+
return structuralOnly(ir, reason);
|
|
229
249
|
const sha256 = hashBytes(response.bytes);
|
|
230
250
|
const screen = {
|
|
231
251
|
screenId: ir.id,
|
|
@@ -240,9 +260,31 @@ const resolveScreen = async (input, ir, renderUrl) => {
|
|
|
240
260
|
};
|
|
241
261
|
return { screen };
|
|
242
262
|
};
|
|
263
|
+
function collectSnapshotRows(outcomes, cappedScreens) {
|
|
264
|
+
const screens = [];
|
|
265
|
+
const skippedScreens = [];
|
|
266
|
+
const structuralScreens = [];
|
|
267
|
+
for (const outcome of outcomes) {
|
|
268
|
+
if (outcome.screen !== undefined)
|
|
269
|
+
screens.push(outcome.screen);
|
|
270
|
+
if (outcome.skipped !== undefined)
|
|
271
|
+
skippedScreens.push(outcome.skipped);
|
|
272
|
+
if (outcome.structuralScreen !== undefined)
|
|
273
|
+
structuralScreens.push(outcome.structuralScreen);
|
|
274
|
+
}
|
|
275
|
+
for (const ir of cappedScreens) {
|
|
276
|
+
const outcome = structuralOnly(ir, "render-screen-cap-exceeded");
|
|
277
|
+
if (outcome.skipped !== undefined)
|
|
278
|
+
skippedScreens.push(outcome.skipped);
|
|
279
|
+
if (outcome.structuralScreen !== undefined)
|
|
280
|
+
structuralScreens.push(outcome.structuralScreen);
|
|
281
|
+
}
|
|
282
|
+
return { screens, skippedScreens, structuralScreens };
|
|
283
|
+
}
|
|
243
284
|
/**
|
|
244
285
|
* Render the screens and assemble the immutable Figma Snapshot. Render failures degrade to a
|
|
245
|
-
* `skippedScreens` entry (partial render); a non-2xx `/v1/images` call is
|
|
286
|
+
* `skippedScreens` entry plus structural-only IR (partial render); a non-2xx `/v1/images` call is
|
|
287
|
+
* a hard coded error.
|
|
246
288
|
*/
|
|
247
289
|
export const buildFigmaSnapshot = async (input) => {
|
|
248
290
|
const maxScreensRendered = boundedPositiveInt(input.maxScreensRendered, DEFAULT_SCOPED_PAGINATION_LIMITS.maxScreensDeep, SCOPED_PAGINATION_LIMIT_CEILINGS.maxScreensDeep);
|
|
@@ -254,25 +296,19 @@ export const buildFigmaSnapshot = async (input) => {
|
|
|
254
296
|
: await requestRenderUrls(input, screenIds);
|
|
255
297
|
const concurrency = boundedPositiveInt(input.downloadConcurrency, DEFAULT_DOWNLOAD_CONCURRENCY, Number.MAX_SAFE_INTEGER);
|
|
256
298
|
const outcomes = await mapWithConcurrency(renderableScreens, concurrency, (ir) => resolveScreen(input, ir, renderUrls.get(ir.id) ?? null));
|
|
257
|
-
const screens =
|
|
258
|
-
const skippedScreens = [];
|
|
259
|
-
for (const outcome of outcomes) {
|
|
260
|
-
if (outcome.screen !== undefined)
|
|
261
|
-
screens.push(outcome.screen);
|
|
262
|
-
if (outcome.skipped !== undefined)
|
|
263
|
-
skippedScreens.push(outcome.skipped);
|
|
264
|
-
}
|
|
265
|
-
for (const ir of cappedScreens) {
|
|
266
|
-
skippedScreens.push({ screenId: ir.id, reason: "render-screen-cap-exceeded" });
|
|
267
|
-
}
|
|
299
|
+
const { screens, skippedScreens, structuralScreens } = collectSnapshotRows(outcomes, cappedScreens);
|
|
268
300
|
return {
|
|
269
301
|
snapshotSchemaVersion: SNAPSHOT_SCHEMA_VERSION,
|
|
270
302
|
provenance: input.provenance,
|
|
271
303
|
screens,
|
|
272
304
|
skippedScreens,
|
|
305
|
+
structuralScreens,
|
|
273
306
|
// Carried verbatim from the Screen-IR (#752) for the navigation/flow graph (#811). NOT folded
|
|
274
307
|
// into the integrity hash below — `links` is non-identity metadata, so drift (#735) is stable.
|
|
275
308
|
links: input.ir.links,
|
|
276
|
-
integrityHash: hashSnapshot(SNAPSHOT_SCHEMA_VERSION, input.provenance.version,
|
|
309
|
+
integrityHash: hashSnapshot(SNAPSHOT_SCHEMA_VERSION, input.provenance.version, [
|
|
310
|
+
...screens,
|
|
311
|
+
...structuralScreens,
|
|
312
|
+
]),
|
|
277
313
|
};
|
|
278
314
|
};
|
|
@@ -2,6 +2,8 @@ import type { QualityIntelligenceFigma } from "@oscharko-dev/keiko-quality-intel
|
|
|
2
2
|
type ScreenIr = QualityIntelligenceFigma.ScreenIr;
|
|
3
3
|
/** sha256 over the canonical per-screen identity: {screenId, ir, imageSha256}. */
|
|
4
4
|
export declare const hashScreen: (screenId: string, ir: ScreenIr, imageSha256: string) => string;
|
|
5
|
+
/** sha256 over a structural-only screen identity: {screenId, ir, structuralOnly:true}. */
|
|
6
|
+
export declare const hashStructuralScreen: (screenId: string, ir: ScreenIr) => string;
|
|
5
7
|
/**
|
|
6
8
|
* sha256 over the canonical snapshot identity: schema version + pinned Figma version + the
|
|
7
9
|
* per-screen hashes sorted by screenId. EXCLUDES `fetchedAt` so the hash is drift-stable across
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figmaSnapshotHash.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaSnapshotHash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"figmaSnapshotHash.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaSnapshotHash.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AAEzF,KAAK,QAAQ,GAAG,wBAAwB,CAAC,QAAQ,CAAC;AAwDlD,kFAAkF;AAClF,eAAO,MAAM,UAAU,GAAI,UAAU,MAAM,EAAE,IAAI,QAAQ,EAAE,aAAa,MAAM,KAAG,MACV,CAAC;AAExE,0FAA0F;AAC1F,eAAO,MAAM,oBAAoB,GAAI,UAAU,MAAM,EAAE,IAAI,QAAQ,KAAG,MACU,CAAC;AAEjF;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,uBAAuB,MAAM,EAC7B,SAAS,MAAM,GAAG,SAAS,EAC3B,WAAW,SAAS;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EAAE,KAClF,MAKF,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,OAAO,UAAU,KAAG,MACI,CAAC"}
|
package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figma/figmaSnapshotHash.js
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
// The hash is the drift identity: same unchanged design ⇒ byte-identical hash, regardless of when
|
|
4
4
|
// it was fetched. We therefore canonicalise to a stable key order and EXCLUDE the wall-clock
|
|
5
5
|
// `fetchedAt`. The snapshot identity is the pinned Figma `version` + the sorted per-screen
|
|
6
|
-
// identities (each = screenId + structural IR + image content sha256
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// identities (each = screenId + structural IR + image content sha256, or a structural-only marker
|
|
7
|
+
// for screens whose PNG render was deliberately skipped/could not be fetched). `version` and the IR
|
|
8
|
+
// are deterministic outputs of #751/#752; the image sha is included so an unexpected render-byte
|
|
9
|
+
// change surfaces as drift too, while structural-only screens still participate in drift detection.
|
|
9
10
|
import { createHash } from "node:crypto";
|
|
10
11
|
const sha256Hex = (input) => createHash("sha256").update(input, "utf8").digest("hex");
|
|
11
12
|
// Stable stringify: object keys are emitted in sorted order at every depth so the serialisation is
|
|
@@ -46,6 +47,8 @@ const hashStableIr = (ir) => ({
|
|
|
46
47
|
});
|
|
47
48
|
/** sha256 over the canonical per-screen identity: {screenId, ir, imageSha256}. */
|
|
48
49
|
export const hashScreen = (screenId, ir, imageSha256) => sha256Hex(canonical({ imageSha256, ir: hashStableIr(ir), screenId }));
|
|
50
|
+
/** sha256 over a structural-only screen identity: {screenId, ir, structuralOnly:true}. */
|
|
51
|
+
export const hashStructuralScreen = (screenId, ir) => sha256Hex(canonical({ ir: hashStableIr(ir), screenId, structuralOnly: true }));
|
|
49
52
|
/**
|
|
50
53
|
* sha256 over the canonical snapshot identity: schema version + pinned Figma version + the
|
|
51
54
|
* per-screen hashes sorted by screenId. EXCLUDES `fetchedAt` so the hash is drift-stable across
|
|
@@ -16,6 +16,14 @@ export interface FigmaSnapshotScreen {
|
|
|
16
16
|
/** sha256 over the canonical {screenId, ir, imageSha256} body — the per-screen drift identity. */
|
|
17
17
|
readonly integrityHash: string;
|
|
18
18
|
}
|
|
19
|
+
/** One screen whose structural IR is captured but no PNG side-file exists. */
|
|
20
|
+
export interface FigmaSnapshotStructuralScreen {
|
|
21
|
+
readonly screenId: string;
|
|
22
|
+
readonly ir: ScreenIr;
|
|
23
|
+
readonly reason: FigmaSkippedScreenReason;
|
|
24
|
+
/** sha256 over the canonical {screenId, ir, structuralOnly:true} body. */
|
|
25
|
+
readonly integrityHash: string;
|
|
26
|
+
}
|
|
19
27
|
/** Why a detected screen produced no render and was excluded from `screens` (partial-render).
|
|
20
28
|
* The `render-fetch-failed` member also appears as `render-fetch-failed:<CODE>` when the fetch
|
|
21
29
|
* threw a FigmaConnectorError — the code suffix lets metrics distinguish an egress
|
|
@@ -37,6 +45,12 @@ export interface FigmaSnapshot {
|
|
|
37
45
|
readonly provenance: FigmaProvenance;
|
|
38
46
|
readonly screens: readonly FigmaSnapshotScreen[];
|
|
39
47
|
readonly skippedScreens: readonly FigmaSkippedScreen[];
|
|
48
|
+
/**
|
|
49
|
+
* Structural IR for screens that did not produce a PNG render. This keeps QI/code consumers from
|
|
50
|
+
* losing JSON evidence when render fan-out is capped or a single render fetch degrades. Optional
|
|
51
|
+
* for older snapshots/builders; new builds emit it for every skipped screen that has IR.
|
|
52
|
+
*/
|
|
53
|
+
readonly structuralScreens?: readonly FigmaSnapshotStructuralScreen[];
|
|
40
54
|
/**
|
|
41
55
|
* Raw inter-screen transitions carried from the Screen-IR (#752) for the navigation/flow graph
|
|
42
56
|
* (#811). OPTIONAL and additive — a constructor that omits it (e.g. an older builder or a test
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figmaSnapshotTypes.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaSnapshotTypes.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,KAAK,QAAQ,GAAG,wBAAwB,CAAC,QAAQ,CAAC;AAElD,+FAA+F;AAC/F,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,kGAAkG;IAClG,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAChC,oBAAoB,GACpB,oBAAoB,GACpB,4BAA4B,GAC5B,qBAAqB,GACrB,uBAAuB,MAAM,EAAE,GAC/B,cAAc,GACd,kBAAkB,CAAC;AAEvB,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;CAC3C;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACjD,QAAQ,CAAC,cAAc,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACvD;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,wBAAwB,CAAC,eAAe,EAAE,CAAC;IACrE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC"}
|
|
1
|
+
{"version":3,"file":"figmaSnapshotTypes.d.ts","sourceRoot":"","sources":["../../../src/qualityIntelligence/figma/figmaSnapshotTypes.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,KAAK,QAAQ,GAAG,wBAAwB,CAAC,QAAQ,CAAC;AAElD,+FAA+F;AAC/F,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,kGAAkG;IAClG,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,8EAA8E;AAC9E,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,0EAA0E;IAC1E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAChC,oBAAoB,GACpB,oBAAoB,GACpB,4BAA4B,GAC5B,qBAAqB,GACrB,uBAAuB,MAAM,EAAE,GAC/B,cAAc,GACd,kBAAkB,CAAC;AAEvB,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;CAC3C;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACjD,QAAQ,CAAC,cAAc,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACvD;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,6BAA6B,EAAE,CAAC;IACtE;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,wBAAwB,CAAC,eAAe,EAAE,CAAC;IACrE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC"}
|
package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export interface FigmaSnapshotSummary {
|
|
|
17
17
|
* "3 screens from 1 section (2 skipped)".
|
|
18
18
|
*/
|
|
19
19
|
readonly reductionHint: string;
|
|
20
|
+
/** Skipped/non-rendered screens that still carry persisted structural Screen-IR JSON. */
|
|
21
|
+
readonly structuralOnlyCount: number;
|
|
20
22
|
/** Integrity hash over the snapshot content — deterministic for drift detection (#735). */
|
|
21
23
|
readonly integrityHash: string;
|
|
22
24
|
/**
|
|
@@ -37,6 +39,11 @@ export interface FigmaSnapshotSummary {
|
|
|
37
39
|
* the token-free PNG side-file through /api/figma/snapshots/:runId/screens/:screenIndex/image.
|
|
38
40
|
*/
|
|
39
41
|
readonly screens: readonly FigmaScreenSummary[];
|
|
42
|
+
/**
|
|
43
|
+
* Screen-IR summaries for detected screens that have JSON evidence but no rendered PNG side-file.
|
|
44
|
+
* These are selectable as QI sources, but the browser cannot request an image for them.
|
|
45
|
+
*/
|
|
46
|
+
readonly structuralScreens: readonly FigmaStructuralScreenSummary[];
|
|
40
47
|
}
|
|
41
48
|
export interface FigmaScreenSummary {
|
|
42
49
|
readonly screenId: string;
|
|
@@ -51,6 +58,30 @@ export interface FigmaScreenSummary {
|
|
|
51
58
|
/** Byte size of the rendered PNG. */
|
|
52
59
|
readonly imageByteLength: number;
|
|
53
60
|
}
|
|
61
|
+
export interface FigmaStructuralScreenSummary {
|
|
62
|
+
readonly screenId: string;
|
|
63
|
+
/** Display name derived from the IR (ir.name). */
|
|
64
|
+
readonly name: string;
|
|
65
|
+
/** A brief structural description (field count, control count) for the gallery card. */
|
|
66
|
+
readonly irSummary: string;
|
|
67
|
+
/** Why no rendered PNG side-file exists for this screen. */
|
|
68
|
+
readonly reason: string;
|
|
69
|
+
}
|
|
70
|
+
export interface FigmaSnapshotListEntry {
|
|
71
|
+
readonly runId: string;
|
|
72
|
+
readonly fileKey: string;
|
|
73
|
+
readonly nodeId: string;
|
|
74
|
+
readonly version: string | undefined;
|
|
75
|
+
readonly fetchedAt: string;
|
|
76
|
+
readonly screenCount: number;
|
|
77
|
+
readonly skippedCount: number;
|
|
78
|
+
readonly structuralOnlyCount: number;
|
|
79
|
+
readonly reductionHint: string;
|
|
80
|
+
readonly integrityHash: string;
|
|
81
|
+
}
|
|
82
|
+
export interface FigmaSnapshotListResponse {
|
|
83
|
+
readonly snapshots: readonly FigmaSnapshotListEntry[];
|
|
84
|
+
}
|
|
54
85
|
export declare function figmaPaginationFromEnv(env: EnvSource): ScopedPaginationLimits;
|
|
55
86
|
interface CoalescedBuildEntry {
|
|
56
87
|
readonly promise: Promise<RouteResult>;
|
|
@@ -61,7 +92,9 @@ export declare function makeInFlightMap(): Map<string, CoalescedBuildEntry>;
|
|
|
61
92
|
export declare function resetInFlightMap(): void;
|
|
62
93
|
export declare function handleFigmaTriggerSnapshot(ctx: RouteContext, deps: UiHandlerDeps, inFlight?: Map<string, CoalescedBuildEntry>): Promise<RouteResult>;
|
|
63
94
|
export declare function handleFigmaRevokeToken(ctx: RouteContext, deps: UiHandlerDeps): RouteResult;
|
|
95
|
+
export declare function handleFigmaListSnapshots(ctx: RouteContext, deps: UiHandlerDeps): RouteResult;
|
|
64
96
|
export declare function handleFigmaLoadSnapshot(ctx: RouteContext, deps: UiHandlerDeps): RouteResult;
|
|
97
|
+
export declare function handleFigmaInspectSnapshotScreenJson(ctx: RouteContext, deps: UiHandlerDeps): RouteResult;
|
|
65
98
|
export declare function handleFigmaLoadSnapshotImage(ctx: RouteContext, deps: UiHandlerDeps): HandlerOutcome;
|
|
66
99
|
export {};
|
|
67
100
|
//# sourceMappingURL=figmaSnapshotRoutes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figmaSnapshotRoutes.d.ts","sourceRoot":"","sources":["../../src/qualityIntelligence/figmaSnapshotRoutes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"figmaSnapshotRoutes.d.ts","sourceRoot":"","sources":["../../src/qualityIntelligence/figmaSnapshotRoutes.ts"],"names":[],"mappings":"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"}
|
package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/figmaSnapshotRoutes.js
CHANGED
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
// The coalesced build continues — other waiters (if any) are unaffected and will
|
|
45
45
|
// receive the result when the build settles.
|
|
46
46
|
import { randomUUID } from "node:crypto";
|
|
47
|
+
import { lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
48
|
+
import { join } from "node:path";
|
|
47
49
|
import { STREAMING } from "../routes.js";
|
|
48
50
|
import { currentGatewayConfig, currentGatewayEgressConfig, currentRedactionSecrets, } from "../deps.js";
|
|
49
51
|
import { redact } from "@oscharko-dev/keiko-security";
|
|
@@ -155,12 +157,19 @@ function readBody(req) {
|
|
|
155
157
|
req.on("error", reject);
|
|
156
158
|
});
|
|
157
159
|
}
|
|
158
|
-
function buildReductionHint(screenCount, skippedCount) {
|
|
160
|
+
function buildReductionHint(screenCount, skippedCount, structuralOnlyCount = 0) {
|
|
159
161
|
const total = screenCount + skippedCount;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
if (skippedCount === 0) {
|
|
163
|
+
return `${screenCount.toString()} screen${screenCount !== 1 ? "s" : ""} from ${total.toString()} detected`;
|
|
164
|
+
}
|
|
165
|
+
const structuralClause = structuralOnlyCount > 0
|
|
166
|
+
? `${structuralOnlyCount.toString()} structural-only`
|
|
167
|
+
: `${skippedCount.toString()} render${skippedCount !== 1 ? "s" : ""} skipped`;
|
|
168
|
+
const missingIrCount = Math.max(0, skippedCount - structuralOnlyCount);
|
|
169
|
+
const missingClause = structuralOnlyCount > 0 && missingIrCount > 0
|
|
170
|
+
? `; ${missingIrCount.toString()} without structural IR`
|
|
162
171
|
: "";
|
|
163
|
-
return `${screenCount.toString()} screen${screenCount !== 1 ? "s" : ""} from ${total.toString()} detected${
|
|
172
|
+
return `${screenCount.toString()} rendered screen${screenCount !== 1 ? "s" : ""} from ${total.toString()} detected (${structuralClause}${missingClause})`;
|
|
164
173
|
}
|
|
165
174
|
// Counts interaction-hint roles over a stored ScreenIr node tree (`{ root: { interactionHint,
|
|
166
175
|
// children } }`). Duck-typed: it does NOT import the IR domain, only walks the serialised shape the
|
|
@@ -212,6 +221,7 @@ function screenNameFromIrJson(irJson) {
|
|
|
212
221
|
function recordToSummary(record, coverage, metrics) {
|
|
213
222
|
const screenCount = record.screens.length;
|
|
214
223
|
const skippedCount = record.skippedScreens.length;
|
|
224
|
+
const structuralOnlyCount = record.structuralScreens?.length ?? 0;
|
|
215
225
|
const truncatedClause = coverage !== undefined && (coverage.screensTruncated > 0 || coverage.capped)
|
|
216
226
|
? `; ${coverage.screensTruncated.toString()} partially captured (deep content bounded)`
|
|
217
227
|
: "";
|
|
@@ -223,7 +233,8 @@ function recordToSummary(record, coverage, metrics) {
|
|
|
223
233
|
fetchedAt: record.provenance.fetchedAt,
|
|
224
234
|
screenCount,
|
|
225
235
|
skippedCount,
|
|
226
|
-
|
|
236
|
+
structuralOnlyCount,
|
|
237
|
+
reductionHint: `${buildReductionHint(screenCount, skippedCount, structuralOnlyCount)}${truncatedClause}`,
|
|
227
238
|
integrityHash: record.integrityHash,
|
|
228
239
|
...(coverage !== undefined ? { coverage } : {}),
|
|
229
240
|
...(metrics !== undefined ? { metrics } : {}),
|
|
@@ -235,6 +246,126 @@ function recordToSummary(record, coverage, metrics) {
|
|
|
235
246
|
imageSha256: s.image.sha256,
|
|
236
247
|
imageByteLength: s.image.byteLength,
|
|
237
248
|
})),
|
|
249
|
+
structuralScreens: (record.structuralScreens ?? []).map((s) => ({
|
|
250
|
+
screenId: s.screenId,
|
|
251
|
+
name: screenNameFromIrJson(s.irJson),
|
|
252
|
+
irSummary: irSummaryFromJson(s.irJson),
|
|
253
|
+
reason: s.reason,
|
|
254
|
+
})),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function decodeRouteParam(raw) {
|
|
258
|
+
if (raw === undefined || raw.length === 0)
|
|
259
|
+
return "";
|
|
260
|
+
try {
|
|
261
|
+
return decodeURIComponent(raw);
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
return "";
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function collectIrIds(value, out = new Set()) {
|
|
268
|
+
if (typeof value !== "object" || value === null)
|
|
269
|
+
return out;
|
|
270
|
+
if (Array.isArray(value)) {
|
|
271
|
+
for (const entry of value)
|
|
272
|
+
collectIrIds(entry, out);
|
|
273
|
+
return out;
|
|
274
|
+
}
|
|
275
|
+
const record = value;
|
|
276
|
+
if (typeof record.id === "string" && record.id.length > 0)
|
|
277
|
+
out.add(record.id);
|
|
278
|
+
for (const entry of Object.values(record))
|
|
279
|
+
collectIrIds(entry, out);
|
|
280
|
+
return out;
|
|
281
|
+
}
|
|
282
|
+
function relatedLinksForScreen(irJson, links) {
|
|
283
|
+
if (links === undefined || links.length === 0)
|
|
284
|
+
return [];
|
|
285
|
+
const ids = collectIrIds(irJson);
|
|
286
|
+
return links.filter((link) => ids.has(link.sourceNodeId) || ids.has(link.targetNodeId));
|
|
287
|
+
}
|
|
288
|
+
function screenJsonSnapshot(record) {
|
|
289
|
+
return {
|
|
290
|
+
screenCount: record.screens.length,
|
|
291
|
+
skippedCount: record.skippedScreens.length,
|
|
292
|
+
structuralOnlyCount: record.structuralScreens?.length ?? 0,
|
|
293
|
+
integrityHash: record.integrityHash,
|
|
294
|
+
redactionSummary: record.redactionSummary,
|
|
295
|
+
...(record.metrics !== undefined ? { metrics: record.metrics } : {}),
|
|
296
|
+
...(record.tokens !== undefined ? { tokens: record.tokens } : {}),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function renderedScreenJsonResponse(record, rendered) {
|
|
300
|
+
return {
|
|
301
|
+
runId: record.runId,
|
|
302
|
+
fileKey: record.provenance.fileKey,
|
|
303
|
+
nodeId: record.provenance.nodeId,
|
|
304
|
+
version: record.provenance.version,
|
|
305
|
+
fetchedAt: record.provenance.fetchedAt,
|
|
306
|
+
source: {
|
|
307
|
+
kind: "figma-snapshot",
|
|
308
|
+
snapshotRunId: record.runId,
|
|
309
|
+
screenIds: [rendered.screenId],
|
|
310
|
+
},
|
|
311
|
+
snapshot: screenJsonSnapshot(record),
|
|
312
|
+
screen: {
|
|
313
|
+
kind: "rendered",
|
|
314
|
+
screenId: rendered.screenId,
|
|
315
|
+
name: screenNameFromIrJson(rendered.irJson),
|
|
316
|
+
irSummary: irSummaryFromJson(rendered.irJson),
|
|
317
|
+
integrityHash: rendered.integrityHash,
|
|
318
|
+
irJson: rendered.irJson,
|
|
319
|
+
image: rendered.image,
|
|
320
|
+
},
|
|
321
|
+
relatedLinks: relatedLinksForScreen(rendered.irJson, record.links),
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
function structuralScreenJsonResponse(record, structural) {
|
|
325
|
+
return {
|
|
326
|
+
runId: record.runId,
|
|
327
|
+
fileKey: record.provenance.fileKey,
|
|
328
|
+
nodeId: record.provenance.nodeId,
|
|
329
|
+
version: record.provenance.version,
|
|
330
|
+
fetchedAt: record.provenance.fetchedAt,
|
|
331
|
+
source: {
|
|
332
|
+
kind: "figma-snapshot",
|
|
333
|
+
snapshotRunId: record.runId,
|
|
334
|
+
screenIds: [structural.screenId],
|
|
335
|
+
},
|
|
336
|
+
snapshot: screenJsonSnapshot(record),
|
|
337
|
+
screen: {
|
|
338
|
+
kind: "structural",
|
|
339
|
+
screenId: structural.screenId,
|
|
340
|
+
name: screenNameFromIrJson(structural.irJson),
|
|
341
|
+
irSummary: irSummaryFromJson(structural.irJson),
|
|
342
|
+
integrityHash: structural.integrityHash,
|
|
343
|
+
irJson: structural.irJson,
|
|
344
|
+
structuralReason: structural.reason,
|
|
345
|
+
},
|
|
346
|
+
relatedLinks: relatedLinksForScreen(structural.irJson, record.links),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function screenJsonResponse(record, screenId) {
|
|
350
|
+
const rendered = record.screens.find((screen) => screen.screenId === screenId);
|
|
351
|
+
if (rendered !== undefined)
|
|
352
|
+
return renderedScreenJsonResponse(record, rendered);
|
|
353
|
+
const structural = record.structuralScreens?.find((screen) => screen.screenId === screenId);
|
|
354
|
+
return structural === undefined ? undefined : structuralScreenJsonResponse(record, structural);
|
|
355
|
+
}
|
|
356
|
+
function recordToListEntry(record) {
|
|
357
|
+
const structuralOnlyCount = record.structuralScreens?.length ?? 0;
|
|
358
|
+
return {
|
|
359
|
+
runId: record.runId,
|
|
360
|
+
fileKey: record.provenance.fileKey,
|
|
361
|
+
nodeId: record.provenance.nodeId,
|
|
362
|
+
version: record.provenance.version,
|
|
363
|
+
fetchedAt: record.provenance.fetchedAt,
|
|
364
|
+
screenCount: record.screens.length,
|
|
365
|
+
skippedCount: record.skippedScreens.length,
|
|
366
|
+
structuralOnlyCount,
|
|
367
|
+
reductionHint: buildReductionHint(record.screens.length, record.skippedScreens.length, structuralOnlyCount),
|
|
368
|
+
integrityHash: record.integrityHash,
|
|
238
369
|
};
|
|
239
370
|
}
|
|
240
371
|
function persistedAuditCounts(record, metrics) {
|
|
@@ -410,6 +541,16 @@ function persistSnapshot(evidenceDir, runId, result, deps) {
|
|
|
410
541
|
integrityHash: s.integrityHash,
|
|
411
542
|
image: { mimeType: "image/png", bytes: s.image.bytes },
|
|
412
543
|
})),
|
|
544
|
+
...(result.snapshot.structuralScreens !== undefined
|
|
545
|
+
? {
|
|
546
|
+
structuralScreens: result.snapshot.structuralScreens.map((s) => ({
|
|
547
|
+
screenId: s.screenId,
|
|
548
|
+
reason: s.reason,
|
|
549
|
+
irJson: s.ir,
|
|
550
|
+
integrityHash: s.integrityHash,
|
|
551
|
+
})),
|
|
552
|
+
}
|
|
553
|
+
: {}),
|
|
413
554
|
skippedScreens: result.snapshot.skippedScreens.map((ss) => ({
|
|
414
555
|
screenId: ss.screenId,
|
|
415
556
|
reason: ss.reason,
|
|
@@ -583,6 +724,96 @@ export function handleFigmaRevokeToken(ctx, deps) {
|
|
|
583
724
|
},
|
|
584
725
|
};
|
|
585
726
|
}
|
|
727
|
+
// ─── GET /api/figma/snapshots — list stored snapshots for dashboard/history ────────────────
|
|
728
|
+
const DEFAULT_FIGMA_SNAPSHOT_LIST_LIMIT = 12;
|
|
729
|
+
const MAX_FIGMA_SNAPSHOT_LIST_LIMIT = 50;
|
|
730
|
+
const FIGMA_SNAPSHOT_RECORD_SUFFIX = ".figma-snapshot.json";
|
|
731
|
+
const FIGMA_EVIDENCE_SUBDIR = "qi";
|
|
732
|
+
function parseSnapshotListLimit(url) {
|
|
733
|
+
const raw = url.searchParams.get("limit");
|
|
734
|
+
if (raw === null || raw.length === 0)
|
|
735
|
+
return DEFAULT_FIGMA_SNAPSHOT_LIST_LIMIT;
|
|
736
|
+
const parsed = Number(raw);
|
|
737
|
+
if (!Number.isInteger(parsed) || parsed <= 0)
|
|
738
|
+
return DEFAULT_FIGMA_SNAPSHOT_LIST_LIMIT;
|
|
739
|
+
return Math.min(parsed, MAX_FIGMA_SNAPSHOT_LIST_LIMIT);
|
|
740
|
+
}
|
|
741
|
+
function parseSnapshotListScope(url) {
|
|
742
|
+
const fileKey = (url.searchParams.get("fileKey") ?? "").trim();
|
|
743
|
+
const nodeId = (url.searchParams.get("nodeId") ?? "").trim();
|
|
744
|
+
return fileKey.length > 0 && nodeId.length > 0 ? { fileKey, nodeId } : undefined;
|
|
745
|
+
}
|
|
746
|
+
function loadSnapshotListEntries(store, runIds) {
|
|
747
|
+
const entries = [];
|
|
748
|
+
for (const runId of runIds) {
|
|
749
|
+
let record;
|
|
750
|
+
try {
|
|
751
|
+
record = store.loadMetadata(runId);
|
|
752
|
+
}
|
|
753
|
+
catch {
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
if (record !== undefined)
|
|
757
|
+
entries.push(recordToListEntry(record));
|
|
758
|
+
}
|
|
759
|
+
return entries;
|
|
760
|
+
}
|
|
761
|
+
function readSnapshotFetchedAt(qiDir, fileName) {
|
|
762
|
+
try {
|
|
763
|
+
const parsed = JSON.parse(readFileSync(join(qiDir, fileName), "utf8"));
|
|
764
|
+
const provenance = typeof parsed.provenance === "object" && parsed.provenance !== null
|
|
765
|
+
? parsed.provenance
|
|
766
|
+
: undefined;
|
|
767
|
+
const fetchedAt = provenance?.fetchedAt;
|
|
768
|
+
return typeof fetchedAt === "string" && fetchedAt.length > 0 ? fetchedAt : undefined;
|
|
769
|
+
}
|
|
770
|
+
catch {
|
|
771
|
+
return undefined;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
function listRecentSnapshotRunIds(evidenceDir, limit) {
|
|
775
|
+
const qiDir = join(evidenceDir, FIGMA_EVIDENCE_SUBDIR);
|
|
776
|
+
const stat = lstatSync(qiDir, { throwIfNoEntry: false });
|
|
777
|
+
if (stat?.isDirectory() !== true)
|
|
778
|
+
return [];
|
|
779
|
+
const records = [];
|
|
780
|
+
for (const entry of readdirSync(qiDir, { withFileTypes: true })) {
|
|
781
|
+
if (!entry.isFile() || !entry.name.endsWith(FIGMA_SNAPSHOT_RECORD_SUFFIX))
|
|
782
|
+
continue;
|
|
783
|
+
const runId = entry.name.slice(0, -FIGMA_SNAPSHOT_RECORD_SUFFIX.length);
|
|
784
|
+
const fetchedAt = readSnapshotFetchedAt(qiDir, entry.name);
|
|
785
|
+
if (fetchedAt !== undefined)
|
|
786
|
+
records.push({ runId, fetchedAt });
|
|
787
|
+
}
|
|
788
|
+
records.sort((a, b) => (a.fetchedAt > b.fetchedAt ? -1 : a.fetchedAt < b.fetchedAt ? 1 : 0));
|
|
789
|
+
return records.slice(0, limit).map((record) => record.runId);
|
|
790
|
+
}
|
|
791
|
+
export function handleFigmaListSnapshots(ctx, deps) {
|
|
792
|
+
const evidenceDir = deps.evidenceDir;
|
|
793
|
+
if (evidenceDir === undefined || evidenceDir.length === 0) {
|
|
794
|
+
return { status: 503, body: figmaErrorBody("FIGMA_NO_EVIDENCE_DIR") };
|
|
795
|
+
}
|
|
796
|
+
const limit = parseSnapshotListLimit(ctx.url);
|
|
797
|
+
const scope = parseSnapshotListScope(ctx.url);
|
|
798
|
+
const store = createNodeFigmaSnapshotStore(evidenceDir);
|
|
799
|
+
try {
|
|
800
|
+
if (scope !== undefined) {
|
|
801
|
+
const snapshots = store
|
|
802
|
+
.listByScope(scope.fileKey, scope.nodeId)
|
|
803
|
+
.slice(0, limit)
|
|
804
|
+
.flatMap((entry) => {
|
|
805
|
+
const record = store.loadMetadata(entry.runId);
|
|
806
|
+
return record === undefined ? [] : [recordToListEntry(record)];
|
|
807
|
+
});
|
|
808
|
+
return { status: 200, body: { snapshots } };
|
|
809
|
+
}
|
|
810
|
+
const snapshots = loadSnapshotListEntries(store, listRecentSnapshotRunIds(evidenceDir, limit));
|
|
811
|
+
return { status: 200, body: { snapshots } };
|
|
812
|
+
}
|
|
813
|
+
catch {
|
|
814
|
+
return { status: 500, body: figmaErrorBody("FIGMA_INTERNAL") };
|
|
815
|
+
}
|
|
816
|
+
}
|
|
586
817
|
// ─── GET /api/figma/snapshots/:runId ──────────────────────────────────────────
|
|
587
818
|
export function handleFigmaLoadSnapshot(ctx, deps) {
|
|
588
819
|
const evidenceDir = deps.evidenceDir;
|
|
@@ -606,6 +837,33 @@ export function handleFigmaLoadSnapshot(ctx, deps) {
|
|
|
606
837
|
}
|
|
607
838
|
return { status: 200, body: recordToSummary(record, undefined, record.metrics) };
|
|
608
839
|
}
|
|
840
|
+
// ─── GET /api/figma/snapshots/:runId/screens/:screenId/json ───────────────────
|
|
841
|
+
export function handleFigmaInspectSnapshotScreenJson(ctx, deps) {
|
|
842
|
+
const evidenceDir = deps.evidenceDir;
|
|
843
|
+
if (evidenceDir === undefined || evidenceDir.length === 0) {
|
|
844
|
+
return { status: 503, body: figmaErrorBody("FIGMA_NO_EVIDENCE_DIR") };
|
|
845
|
+
}
|
|
846
|
+
const runId = decodeRouteParam(ctx.params.runId);
|
|
847
|
+
const screenId = decodeRouteParam(ctx.params.screenId);
|
|
848
|
+
if (runId.length === 0 || screenId.length === 0) {
|
|
849
|
+
return { status: 404, body: figmaErrorBody("FIGMA_SCREEN_NOT_FOUND") };
|
|
850
|
+
}
|
|
851
|
+
const store = createNodeFigmaSnapshotStore(evidenceDir);
|
|
852
|
+
let record;
|
|
853
|
+
try {
|
|
854
|
+
record = store.loadMetadata(runId);
|
|
855
|
+
}
|
|
856
|
+
catch {
|
|
857
|
+
return { status: 500, body: figmaErrorBody("FIGMA_INTERNAL") };
|
|
858
|
+
}
|
|
859
|
+
if (record === undefined) {
|
|
860
|
+
return { status: 404, body: figmaErrorBody("FIGMA_SNAPSHOT_NOT_FOUND") };
|
|
861
|
+
}
|
|
862
|
+
const body = screenJsonResponse(record, screenId);
|
|
863
|
+
return body === undefined
|
|
864
|
+
? { status: 404, body: figmaErrorBody("FIGMA_SCREEN_NOT_FOUND") }
|
|
865
|
+
: { status: 200, body };
|
|
866
|
+
}
|
|
609
867
|
// ─── GET /api/figma/snapshots/:runId/screens/:screenIndex/image ──────────────
|
|
610
868
|
function parseScreenIndex(raw) {
|
|
611
869
|
if (raw === undefined || raw.length === 0)
|