diff --git a/.bitcode/v43-deposit-option-admission.json b/.bitcode/v43-deposit-option-admission.json index e4eb8793..d0e9f9c0 100644 --- a/.bitcode/v43-deposit-option-admission.json +++ b/.bitcode/v43-deposit-option-admission.json @@ -5,7 +5,7 @@ "currentTarget": "V42", "sourceSafetyVerdict": "source-safe-deposit-option-admission-metadata", "generatedAt": "deterministic", - "artifactRoot": "v43-deposit-option-admission:00e82f1309f4798e342d3317", + "artifactRoot": "v43-deposit-option-admission:067243f03ca79fcc0c48e30e", "passed": true, "objectIds": [ "DepositAssetPackOptionAdmissionReport", @@ -111,16 +111,16 @@ ], "sourceRoots": { "activePointer": "BITCODE_SPEC.txt:75f3f6d81f999da998f40cb6", - "spec": "BITCODE_SPEC_V43.md:be395a7424e1cda9f9a6db95", - "delta": "BITCODE_SPEC_V43_DELTA.md:bfdc638747d2b26e3f2e9198", - "notes": "BITCODE_SPEC_V43_NOTES.md:0b63f2a957175089051d64c5", - "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:8fec04876421410dd51ec879", - "roadmap": "SPECIFICATIONS_ROADMAP.md:8bbf62cb7261a6f2bc55e9bc", - "readme": "README.md:7a6eb7df6034f3f7ae18a4b6", - "protocolReadme": "packages/protocol/README.md:d338afce1b165d7da3bf9fc3", - "packageJson": "package.json:4eb71d824b7ac57b57e7eaa7", - "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:2fa0b3b3648ff6a9ce463290", - "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:232544cd143619fc8c2597a8", + "spec": "BITCODE_SPEC_V43.md:279f284912ed058bbc8ef430", + "delta": "BITCODE_SPEC_V43_DELTA.md:e236e6fc7e4afc685d86fd09", + "notes": "BITCODE_SPEC_V43_NOTES.md:67426dc28a11c11e057fac66", + "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:b40d7cde0c978e29c2881707", + "roadmap": "SPECIFICATIONS_ROADMAP.md:5caa3c41627fdacae5fcb4f9", + "readme": "README.md:ee3b21e97e291519280e685e", + "protocolReadme": "packages/protocol/README.md:ffcf019b6434251a61e54d13", + "packageJson": "package.json:12ffbd25e34c85aa70fc21bf", + "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:024a1e47cfe1854c52e4da80", + "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:b6dcf389972fed22e5176e76", "optionModel": "packages/pipelines/asset-pack/src/deposit-asset-pack-options.ts:df560ea2544282645f57a6b5", "policyModel": "packages/pipelines/asset-pack/src/deposit-asset-pack-option-policy.ts:12816b23b2d8e304ab4a1638", "admissionModel": "packages/pipelines/asset-pack/src/deposit-asset-pack-option-admission.ts:4d2b0c5e6e10c2b14a75a8c8", @@ -128,16 +128,16 @@ "policyModelTest": "packages/pipelines/asset-pack/src/__tests__/deposit-asset-pack-option-policy.test.ts:1af7adccac488298ccd7f048", "admissionModelTest": "packages/pipelines/asset-pack/src/__tests__/deposit-asset-pack-option-admission.test.ts:9f156ea0d8c603487a7a8152", "routeModel": "uapi/app/deposit/deposit-route-model.ts:7354c10d543af2cb65ba0ade", - "client": "uapi/app/deposit/DepositPageClient.tsx:f8db0f58dd4ec01c5fca10b6", + "client": "uapi/app/deposit/DepositPageClient.tsx:ee78319e6a48ccf12e2eb925", "routeModelTest": "uapi/tests/depositRouteModel.test.ts:0fb7d8d4d58d7e231ada4510", - "pageTest": "uapi/tests/depositPageClient.test.tsx:18c44b7a03b74d9ca8b17536", + "pageTest": "uapi/tests/depositPageClient.test.tsx:b1acbca83d8f3244147217dc", "packActivityModel": "uapi/components/base/bitcode/activity/pack-activity-model.ts:d848bb7a06bc8f4c46c2fc8a", "packActivityModelTest": "uapi/tests/packActivityModel.test.ts:7854762895ce63b0de8b6940", "uapiJestConfig": "uapi/jest.config.cjs:352ee765a17823c7a486fe92", "packageIndex": "packages/pipelines/asset-pack/src/index.ts:24854bd26b47ce7700e02380", "packageManifest": "packages/pipelines/asset-pack/package.json:f998601555d9f21de1393f74", - "protocolIndex": "packages/protocol/src/index.js:da82c2ca8c20849a6fa0b931", - "protocolTypes": "packages/protocol/src/index.d.ts:c04dd7f96f54a112437e39f9", + "protocolIndex": "packages/protocol/src/index.js:4f9fea5557edf88d1e1ae521", + "protocolTypes": "packages/protocol/src/index.d.ts:6a766f2d554a2558bf6ddbd3", "protocolTest": "packages/protocol/test/v43-deposit-option-admission.test.js:53ae55cfef55536ebc552b65", "generator": "scripts/generate-v43-deposit-option-admission.mjs:b7101699843c09250a84d41f", "checker": "scripts/check-v43-gate7-deposit-option-admission.mjs:6a857acf8b23f5fdb15fb02d" diff --git a/.bitcode/v43-deposit-policy-compensation.json b/.bitcode/v43-deposit-policy-compensation.json index 4461a403..4209d73a 100644 --- a/.bitcode/v43-deposit-policy-compensation.json +++ b/.bitcode/v43-deposit-policy-compensation.json @@ -5,7 +5,7 @@ "currentTarget": "V42", "sourceSafetyVerdict": "source-safe-deposit-policy-compensation-metadata", "generatedAt": "deterministic", - "artifactRoot": "v43-deposit-policy-compensation:0d74b0d78748ef57697c114a", + "artifactRoot": "v43-deposit-policy-compensation:56fa7738a2f6ae24e1e416aa", "passed": true, "objectIds": [ "DepositAssetPackOptionPolicy", @@ -100,28 +100,28 @@ ], "sourceRoots": { "activePointer": "BITCODE_SPEC.txt:75f3f6d81f999da998f40cb6", - "spec": "BITCODE_SPEC_V43.md:be395a7424e1cda9f9a6db95", - "delta": "BITCODE_SPEC_V43_DELTA.md:bfdc638747d2b26e3f2e9198", - "notes": "BITCODE_SPEC_V43_NOTES.md:0b63f2a957175089051d64c5", - "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:8fec04876421410dd51ec879", - "roadmap": "SPECIFICATIONS_ROADMAP.md:8bbf62cb7261a6f2bc55e9bc", - "readme": "README.md:7a6eb7df6034f3f7ae18a4b6", - "protocolReadme": "packages/protocol/README.md:d338afce1b165d7da3bf9fc3", - "packageJson": "package.json:4eb71d824b7ac57b57e7eaa7", - "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:2fa0b3b3648ff6a9ce463290", - "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:232544cd143619fc8c2597a8", + "spec": "BITCODE_SPEC_V43.md:279f284912ed058bbc8ef430", + "delta": "BITCODE_SPEC_V43_DELTA.md:e236e6fc7e4afc685d86fd09", + "notes": "BITCODE_SPEC_V43_NOTES.md:67426dc28a11c11e057fac66", + "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:b40d7cde0c978e29c2881707", + "roadmap": "SPECIFICATIONS_ROADMAP.md:5caa3c41627fdacae5fcb4f9", + "readme": "README.md:ee3b21e97e291519280e685e", + "protocolReadme": "packages/protocol/README.md:ffcf019b6434251a61e54d13", + "packageJson": "package.json:12ffbd25e34c85aa70fc21bf", + "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:024a1e47cfe1854c52e4da80", + "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:b6dcf389972fed22e5176e76", "optionModel": "packages/pipelines/asset-pack/src/deposit-asset-pack-options.ts:df560ea2544282645f57a6b5", "policyModel": "packages/pipelines/asset-pack/src/deposit-asset-pack-option-policy.ts:12816b23b2d8e304ab4a1638", "optionModelTest": "packages/pipelines/asset-pack/src/__tests__/deposit-asset-pack-options.test.ts:66cfc8c728f134087476a3a3", "policyModelTest": "packages/pipelines/asset-pack/src/__tests__/deposit-asset-pack-option-policy.test.ts:1af7adccac488298ccd7f048", "routeModel": "uapi/app/deposit/deposit-route-model.ts:7354c10d543af2cb65ba0ade", - "client": "uapi/app/deposit/DepositPageClient.tsx:f8db0f58dd4ec01c5fca10b6", + "client": "uapi/app/deposit/DepositPageClient.tsx:ee78319e6a48ccf12e2eb925", "routeModelTest": "uapi/tests/depositRouteModel.test.ts:0fb7d8d4d58d7e231ada4510", - "pageTest": "uapi/tests/depositPageClient.test.tsx:18c44b7a03b74d9ca8b17536", + "pageTest": "uapi/tests/depositPageClient.test.tsx:b1acbca83d8f3244147217dc", "packageIndex": "packages/pipelines/asset-pack/src/index.ts:24854bd26b47ce7700e02380", "packageManifest": "packages/pipelines/asset-pack/package.json:f998601555d9f21de1393f74", - "protocolIndex": "packages/protocol/src/index.js:da82c2ca8c20849a6fa0b931", - "protocolTypes": "packages/protocol/src/index.d.ts:c04dd7f96f54a112437e39f9", + "protocolIndex": "packages/protocol/src/index.js:4f9fea5557edf88d1e1ae521", + "protocolTypes": "packages/protocol/src/index.d.ts:6a766f2d554a2558bf6ddbd3", "protocolTest": "packages/protocol/test/v43-deposit-policy-compensation.test.js:f84b0c016065b10f796eb775", "generator": "scripts/generate-v43-deposit-policy-compensation.mjs:0117b1222d0f4a4640324b47", "checker": "scripts/check-v43-gate6-deposit-policy-compensation.mjs:03412b725c36f24991a6325e" diff --git a/.bitcode/v43-deposit-route-options.json b/.bitcode/v43-deposit-route-options.json index 88b79373..ae02a582 100644 --- a/.bitcode/v43-deposit-route-options.json +++ b/.bitcode/v43-deposit-route-options.json @@ -5,7 +5,7 @@ "currentTarget": "V42", "sourceSafetyVerdict": "source-safe-deposit-route-option-metadata", "generatedAt": "deterministic", - "artifactRoot": "v43-deposit-route-options:f122a3ca36cdc73e0215ce07", + "artifactRoot": "v43-deposit-route-options:d3e2ed7af5b1553aea4a71c7", "passed": true, "stepIds": [ "connect-source", @@ -111,20 +111,20 @@ ], "sourceRoots": { "activePointer": "BITCODE_SPEC.txt:75f3f6d81f999da998f40cb6", - "spec": "BITCODE_SPEC_V43.md:be395a7424e1cda9f9a6db95", - "delta": "BITCODE_SPEC_V43_DELTA.md:bfdc638747d2b26e3f2e9198", - "notes": "BITCODE_SPEC_V43_NOTES.md:0b63f2a957175089051d64c5", - "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:8fec04876421410dd51ec879", - "roadmap": "SPECIFICATIONS_ROADMAP.md:8bbf62cb7261a6f2bc55e9bc", - "readme": "README.md:7a6eb7df6034f3f7ae18a4b6", - "protocolReadme": "packages/protocol/README.md:d338afce1b165d7da3bf9fc3", - "packageJson": "package.json:4eb71d824b7ac57b57e7eaa7", - "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:2fa0b3b3648ff6a9ce463290", - "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:232544cd143619fc8c2597a8", + "spec": "BITCODE_SPEC_V43.md:279f284912ed058bbc8ef430", + "delta": "BITCODE_SPEC_V43_DELTA.md:e236e6fc7e4afc685d86fd09", + "notes": "BITCODE_SPEC_V43_NOTES.md:67426dc28a11c11e057fac66", + "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:b40d7cde0c978e29c2881707", + "roadmap": "SPECIFICATIONS_ROADMAP.md:5caa3c41627fdacae5fcb4f9", + "readme": "README.md:ee3b21e97e291519280e685e", + "protocolReadme": "packages/protocol/README.md:ffcf019b6434251a61e54d13", + "packageJson": "package.json:12ffbd25e34c85aa70fc21bf", + "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:024a1e47cfe1854c52e4da80", + "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:b6dcf389972fed22e5176e76", "terminalRoutes": "uapi/app/terminal/terminal-routes.ts:80f478da2673f1a64ada9bfb", "routeModel": "uapi/app/deposit/deposit-route-model.ts:7354c10d543af2cb65ba0ade", "page": "uapi/app/deposit/page.tsx:6bab6a9debab3f4350d0ddca", - "client": "uapi/app/deposit/DepositPageClient.tsx:f8db0f58dd4ec01c5fca10b6", + "client": "uapi/app/deposit/DepositPageClient.tsx:ee78319e6a48ccf12e2eb925", "optionModel": "packages/pipelines/asset-pack/src/deposit-asset-pack-options.ts:df560ea2544282645f57a6b5", "optionModelTest": "packages/pipelines/asset-pack/src/__tests__/deposit-asset-pack-options.test.ts:66cfc8c728f134087476a3a3", "packageIndex": "packages/pipelines/asset-pack/src/index.ts:24854bd26b47ce7700e02380", @@ -135,9 +135,9 @@ "nav": "uapi/components/base/bitcode/layout/nav.tsx:d7d1a8104e780bb7c25f1880", "footer": "uapi/components/base/bitcode/layout/footer.tsx:44749b98e5f63e7ac8f9f574", "routeModelTest": "uapi/tests/depositRouteModel.test.ts:0fb7d8d4d58d7e231ada4510", - "pageTest": "uapi/tests/depositPageClient.test.tsx:18c44b7a03b74d9ca8b17536", - "protocolIndex": "packages/protocol/src/index.js:da82c2ca8c20849a6fa0b931", - "protocolTypes": "packages/protocol/src/index.d.ts:c04dd7f96f54a112437e39f9", + "pageTest": "uapi/tests/depositPageClient.test.tsx:b1acbca83d8f3244147217dc", + "protocolIndex": "packages/protocol/src/index.js:4f9fea5557edf88d1e1ae521", + "protocolTypes": "packages/protocol/src/index.d.ts:6a766f2d554a2558bf6ddbd3", "protocolTest": "packages/protocol/test/v43-deposit-route-options.test.js:6576a3d4947b9bc23f7a786d", "generator": "scripts/generate-v43-deposit-route-options.mjs:2d92d5e9c25e2e66712953f9", "checker": "scripts/check-v43-gate5-deposit-route-options.mjs:10c6ad1594ea8bd06f97d7d5" diff --git a/.bitcode/v43-packs-activity-master-detail.json b/.bitcode/v43-packs-activity-master-detail.json index dda6d2fc..d8f0a811 100644 --- a/.bitcode/v43-packs-activity-master-detail.json +++ b/.bitcode/v43-packs-activity-master-detail.json @@ -5,7 +5,7 @@ "currentTarget": "V42", "sourceSafetyVerdict": "source-safe-packs-activity-master-detail-metadata", "generatedAt": "deterministic", - "artifactRoot": "v43-packs-activity-master-detail:2f9452517c1357333359e855", + "artifactRoot": "v43-packs-activity-master-detail:e96591ce2ff0c79e81a348b7", "passed": true, "typeIds": [ "deposit-option", @@ -138,27 +138,27 @@ ], "sourceRoots": { "activePointer": "BITCODE_SPEC.txt:75f3f6d81f999da998f40cb6", - "spec": "BITCODE_SPEC_V43.md:be395a7424e1cda9f9a6db95", - "delta": "BITCODE_SPEC_V43_DELTA.md:bfdc638747d2b26e3f2e9198", - "notes": "BITCODE_SPEC_V43_NOTES.md:0b63f2a957175089051d64c5", - "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:8fec04876421410dd51ec879", - "roadmap": "SPECIFICATIONS_ROADMAP.md:8bbf62cb7261a6f2bc55e9bc", - "readme": "README.md:7a6eb7df6034f3f7ae18a4b6", - "protocolReadme": "packages/protocol/README.md:d338afce1b165d7da3bf9fc3", - "packageJson": "package.json:4eb71d824b7ac57b57e7eaa7", - "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:2fa0b3b3648ff6a9ce463290", - "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:232544cd143619fc8c2597a8", + "spec": "BITCODE_SPEC_V43.md:279f284912ed058bbc8ef430", + "delta": "BITCODE_SPEC_V43_DELTA.md:e236e6fc7e4afc685d86fd09", + "notes": "BITCODE_SPEC_V43_NOTES.md:67426dc28a11c11e057fac66", + "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:b40d7cde0c978e29c2881707", + "roadmap": "SPECIFICATIONS_ROADMAP.md:5caa3c41627fdacae5fcb4f9", + "readme": "README.md:ee3b21e97e291519280e685e", + "protocolReadme": "packages/protocol/README.md:ffcf019b6434251a61e54d13", + "packageJson": "package.json:12ffbd25e34c85aa70fc21bf", + "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:024a1e47cfe1854c52e4da80", + "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:b6dcf389972fed22e5176e76", "model": "uapi/components/base/bitcode/activity/pack-activity-model.ts:d848bb7a06bc8f4c46c2fc8a", "route": "uapi/app/api/packs/activity/route.ts:8a524f1dd16889733ce418a7", "page": "uapi/app/packs/page.tsx:1b3d7a1cc00500a13042e8dd", - "client": "uapi/app/packs/PacksPageClient.tsx:d777458df28f47a360c6601c", + "client": "uapi/app/packs/PacksPageClient.tsx:9a225a3462967b4b8c2adc00", "exchangeRedirect": "uapi/app/exchange/page.tsx:be7a744d1f9c9252d1b6eba9", "nav": "uapi/components/base/bitcode/layout/nav.tsx:d7d1a8104e780bb7c25f1880", "workspaceSurface": "uapi/components/base/bitcode/layout/workspace-surface.ts:12418d5db9c3ddad6d10c841", "publicCopy": "uapi/components/base/bitcode/layout/bitcode-public-copy.ts:3a45184ba8d2a4e71858c597", "publicExplainers": "uapi/components/base/bitcode/layout/bitcode-public-explainers.ts:282d915eac3c9f22ba8c07f1", - "packageIndex": "packages/protocol/src/index.js:da82c2ca8c20849a6fa0b931", - "packageTypes": "packages/protocol/src/index.d.ts:c04dd7f96f54a112437e39f9", + "packageIndex": "packages/protocol/src/index.js:4f9fea5557edf88d1e1ae521", + "packageTypes": "packages/protocol/src/index.d.ts:6a766f2d554a2558bf6ddbd3", "packageTest": "packages/protocol/test/v43-packs-activity-master-detail.test.js:baf3e44b2fbe4e62590c1824", "uapiTest": "uapi/tests/packActivityModel.test.ts:7854762895ce63b0de8b6940", "generator": "scripts/generate-v43-packs-activity-master-detail.mjs:f342bc9b3ebb8de4e7aa2882", diff --git a/.bitcode/v43-read-route-five-step-ux.json b/.bitcode/v43-read-route-five-step-ux.json index 077611f0..eb92206d 100644 --- a/.bitcode/v43-read-route-five-step-ux.json +++ b/.bitcode/v43-read-route-five-step-ux.json @@ -5,7 +5,7 @@ "currentTarget": "V42", "sourceSafetyVerdict": "source-safe-read-route-five-step-metadata", "generatedAt": "deterministic", - "artifactRoot": "v43-read-route-five-step-ux:1248824b6cb0951af8b4ba2e", + "artifactRoot": "v43-read-route-five-step-ux:4b4d23ad0a311624dead69d8", "passed": true, "stepIds": [ "request-read", @@ -117,19 +117,19 @@ ], "sourceRoots": { "activePointer": "BITCODE_SPEC.txt:75f3f6d81f999da998f40cb6", - "spec": "BITCODE_SPEC_V43.md:be395a7424e1cda9f9a6db95", - "delta": "BITCODE_SPEC_V43_DELTA.md:bfdc638747d2b26e3f2e9198", - "notes": "BITCODE_SPEC_V43_NOTES.md:0b63f2a957175089051d64c5", - "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:8fec04876421410dd51ec879", - "roadmap": "SPECIFICATIONS_ROADMAP.md:8bbf62cb7261a6f2bc55e9bc", - "readme": "README.md:7a6eb7df6034f3f7ae18a4b6", - "protocolReadme": "packages/protocol/README.md:d338afce1b165d7da3bf9fc3", - "packageJson": "package.json:4eb71d824b7ac57b57e7eaa7", - "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:2fa0b3b3648ff6a9ce463290", - "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:232544cd143619fc8c2597a8", + "spec": "BITCODE_SPEC_V43.md:279f284912ed058bbc8ef430", + "delta": "BITCODE_SPEC_V43_DELTA.md:e236e6fc7e4afc685d86fd09", + "notes": "BITCODE_SPEC_V43_NOTES.md:67426dc28a11c11e057fac66", + "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:b40d7cde0c978e29c2881707", + "roadmap": "SPECIFICATIONS_ROADMAP.md:5caa3c41627fdacae5fcb4f9", + "readme": "README.md:ee3b21e97e291519280e685e", + "protocolReadme": "packages/protocol/README.md:ffcf019b6434251a61e54d13", + "packageJson": "package.json:12ffbd25e34c85aa70fc21bf", + "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:024a1e47cfe1854c52e4da80", + "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:b6dcf389972fed22e5176e76", "routeModel": "uapi/app/read/read-route-model.ts:a9324b0d92cd6c5176fa7940", "page": "uapi/app/read/page.tsx:37a723ed87feac05c0504249", - "client": "uapi/app/read/ReadPageClient.tsx:d14f0fbb65af0edfa68d774f", + "client": "uapi/app/read/ReadPageClient.tsx:8e75873706918b22d7ddf8ed", "terminalRoutes": "uapi/app/terminal/terminal-routes.ts:80f478da2673f1a64ada9bfb", "terminalWorkbench": "uapi/app/terminal/TerminalDepositReadWorkbench.tsx:beeb39fa4f8568619d16f343", "terminalReadingState": "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts:fb152fb0cc1d0799d1d616d6", @@ -138,11 +138,11 @@ "publicCopy": "uapi/components/base/bitcode/layout/bitcode-public-copy.ts:3a45184ba8d2a4e71858c597", "publicExplainers": "uapi/components/base/bitcode/layout/bitcode-public-explainers.ts:282d915eac3c9f22ba8c07f1", "footer": "uapi/components/base/bitcode/layout/footer.tsx:44749b98e5f63e7ac8f9f574", - "packageIndex": "packages/protocol/src/index.js:da82c2ca8c20849a6fa0b931", - "packageTypes": "packages/protocol/src/index.d.ts:c04dd7f96f54a112437e39f9", + "packageIndex": "packages/protocol/src/index.js:4f9fea5557edf88d1e1ae521", + "packageTypes": "packages/protocol/src/index.d.ts:6a766f2d554a2558bf6ddbd3", "packageTest": "packages/protocol/test/v43-read-route-five-step-ux.test.js:fedf825a49244098367f6388", "routeModelTest": "uapi/tests/readRouteModel.test.ts:47d613cef4ab6dce86846c8f", - "pageTest": "uapi/tests/readPageClient.test.tsx:9bd621c200f02082d0159cc5", + "pageTest": "uapi/tests/readPageClient.test.tsx:39abee8e499c491b5a33cbf1", "generator": "scripts/generate-v43-read-route-five-step-ux.mjs:04954a1f66c27e21ef86a08f", "checker": "scripts/check-v43-gate4-read-route-five-step-ux.mjs:86ba9a96169452ceeb347f10" }, diff --git a/.bitcode/v43-route-ux-product-excellence.json b/.bitcode/v43-route-ux-product-excellence.json new file mode 100644 index 00000000..1dcddd2b --- /dev/null +++ b/.bitcode/v43-route-ux-product-excellence.json @@ -0,0 +1,318 @@ +{ + "artifactId": "v43-route-ux-product-excellence", + "schemaId": "bitcode.v43.routeUxProductExcellence.v1", + "version": "V43", + "currentTarget": "V42", + "sourceSafetyVerdict": "source-safe-product-route-ux-metadata", + "generatedAt": "deterministic", + "artifactRoot": "v43-route-ux-product-excellence:ebb5a3e35fa1b4b3b7c0b6b6", + "passed": true, + "objectIds": [ + "ProductRouteShell", + "ProductRouteStepGrid", + "ProductRouteStatePanel", + "ProductRouteDisclosure", + "/packs product route", + "/read product route", + "/deposit product route" + ], + "fieldIds": [ + "routeLabel", + "routeTitle", + "routeSummary", + "metric", + "step", + "statePanel", + "progressiveDisclosure", + "sourceSafeBoundary" + ], + "forbiddenPayloadIds": [ + "protected_source_payload", + "raw_source_text", + "unpaid_assetpack_source", + "raw_protected_prompt", + "interpolated_prompt", + "raw_provider_response", + "wallet_private_material", + "settlement_private_payload" + ], + "contractRows": [ + { + "rowId": "shared-product-route-shell", + "owner": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "contract": "Packs, Reading, and Depositing render through a shared themed product shell with route label, title, concise summary, and source-safe route metrics.", + "requiredFields": [ + "ProductRouteShell", + "route-shell-packs", + "route-shell-read", + "route-shell-deposit" + ], + "rowRoot": "v43-route-ux-contract:952044a7fa7cefa2bd20ec0e", + "sourceSafeMetadataOnly": true, + "protectedSourceVisible": false, + "unpaidAssetPackSourceVisible": false + }, + { + "rowId": "keyboard-five-step-navigation", + "owner": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "contract": "Reading and Depositing use a shared button-based step grid with visible active state, aria-current step semantics, and stable data attributes for route state tests.", + "requiredFields": [ + "ProductRouteStepGrid", + "aria-current", + "data-reading-step-state", + "data-deposit-step-state" + ], + "rowRoot": "v43-route-ux-contract:ccb4ddbe71913d5359dd86e7", + "sourceSafeMetadataOnly": true, + "protectedSourceVisible": false, + "unpaidAssetPackSourceVisible": false + }, + { + "rowId": "state-panels-empty-error-loading", + "owner": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "contract": "Packs, Reading, and Depositing share compact loading, empty, and error state panels without leaking source-bearing payloads.", + "requiredFields": [ + "ProductRouteStatePanel", + "loading", + "empty", + "error" + ], + "rowRoot": "v43-route-ux-contract:3583e5c5a45c2edb116d7035", + "sourceSafeMetadataOnly": true, + "protectedSourceVisible": false, + "unpaidAssetPackSourceVisible": false + }, + { + "rowId": "progressive-source-safe-detail", + "owner": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "contract": "Read and Deposit route proof detail remains expandable by default, with visible metadata and withheld protected-source boundaries stated as route state.", + "requiredFields": [ + "ProductRouteDisclosure", + "Disclosure boundary", + "Withheld" + ], + "rowRoot": "v43-route-ux-contract:8feb4861984ad0ded6b4641a", + "sourceSafeMetadataOnly": true, + "protectedSourceVisible": false, + "unpaidAssetPackSourceVisible": false + }, + { + "rowId": "product-copy-reduced", + "owner": "BITCODE_SPEC_V43.md", + "contract": "In-app product copy is concise route/status vocabulary rather than self-referential instructions, while deeper protocol explanation stays in public documentation and proof artifacts.", + "requiredFields": [ + "self-referential product copy", + "route structure", + "progressive proof detail" + ], + "rowRoot": "v43-route-ux-contract:928c56bbf864b4790c8f107b", + "sourceSafeMetadataOnly": true, + "protectedSourceVisible": false, + "unpaidAssetPackSourceVisible": false + } + ], + "sourceRoots": { + "activePointer": "BITCODE_SPEC.txt:75f3f6d81f999da998f40cb6", + "spec": "BITCODE_SPEC_V43.md:279f284912ed058bbc8ef430", + "delta": "BITCODE_SPEC_V43_DELTA.md:e236e6fc7e4afc685d86fd09", + "notes": "BITCODE_SPEC_V43_NOTES.md:67426dc28a11c11e057fac66", + "parity": "BITCODE_SPEC_V43_PARITY_MATRIX.md:b40d7cde0c978e29c2881707", + "roadmap": "SPECIFICATIONS_ROADMAP.md:5caa3c41627fdacae5fcb4f9", + "readme": "README.md:ee3b21e97e291519280e685e", + "protocolReadme": "packages/protocol/README.md:ffcf019b6434251a61e54d13", + "packageJson": "package.json:12ffbd25e34c85aa70fc21bf", + "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml:024a1e47cfe1854c52e4da80", + "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml:b6dcf389972fed22e5176e76", + "productRouteShell": "uapi/components/base/bitcode/routes/product-route-shell.tsx:1db5b3d0e67eb84327568b90", + "packsClient": "uapi/app/packs/PacksPageClient.tsx:9a225a3462967b4b8c2adc00", + "readClient": "uapi/app/read/ReadPageClient.tsx:8e75873706918b22d7ddf8ed", + "depositClient": "uapi/app/deposit/DepositPageClient.tsx:ee78319e6a48ccf12e2eb925", + "packsTest": "uapi/tests/packsPageClient.test.tsx:3d190debc869e3d2ec7c0b45", + "readTest": "uapi/tests/readPageClient.test.tsx:39abee8e499c491b5a33cbf1", + "depositTest": "uapi/tests/depositPageClient.test.tsx:b1acbca83d8f3244147217dc", + "protocolIndex": "packages/protocol/src/index.js:4f9fea5557edf88d1e1ae521", + "protocolTypes": "packages/protocol/src/index.d.ts:6a766f2d554a2558bf6ddbd3", + "protocolTest": "packages/protocol/test/v43-route-ux-product-excellence.test.js:90da888669ac62dabb2fab0d", + "generator": "scripts/generate-v43-route-ux-product-excellence.mjs:cfa27fac384b22a62c12aa54", + "checker": "scripts/check-v43-gate8-route-ux-product-excellence.mjs:0216d34433f7bd393cf8a99b" + }, + "predicateResults": [ + { + "id": "active-canon-pointer-remains-v42", + "sourcePath": "BITCODE_SPEC.txt", + "passed": true + }, + { + "id": "spec-defines-gate8", + "sourcePath": "BITCODE_SPEC_V43.md", + "passed": true + }, + { + "id": "spec-records-shared-route-shell", + "sourcePath": "BITCODE_SPEC_V43.md", + "passed": true + }, + { + "id": "delta-records-gate8", + "sourcePath": "BITCODE_SPEC_V43_DELTA.md", + "passed": true + }, + { + "id": "notes-records-gate8", + "sourcePath": "BITCODE_SPEC_V43_NOTES.md", + "passed": true + }, + { + "id": "parity-records-gate8", + "sourcePath": "BITCODE_SPEC_V43_PARITY_MATRIX.md", + "passed": true + }, + { + "id": "roadmap-records-gate8", + "sourcePath": "SPECIFICATIONS_ROADMAP.md", + "passed": true + }, + { + "id": "readme-records-gate8", + "sourcePath": "README.md", + "passed": true + }, + { + "id": "protocol-readme-records-gate8", + "sourcePath": "packages/protocol/README.md", + "passed": true + }, + { + "id": "shared-shell-implements-route-shell", + "sourcePath": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "passed": true + }, + { + "id": "shared-shell-implements-step-grid", + "sourcePath": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "passed": true + }, + { + "id": "shared-shell-implements-state-panel", + "sourcePath": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "passed": true + }, + { + "id": "shared-shell-implements-disclosure", + "sourcePath": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "passed": true + }, + { + "id": "packs-route-uses-shell", + "sourcePath": "uapi/app/packs/PacksPageClient.tsx", + "passed": true + }, + { + "id": "read-route-uses-shell-step-grid", + "sourcePath": "uapi/app/read/ReadPageClient.tsx", + "passed": true + }, + { + "id": "deposit-route-uses-shell-step-grid", + "sourcePath": "uapi/app/deposit/DepositPageClient.tsx", + "passed": true + }, + { + "id": "read-route-uses-progressive-disclosure", + "sourcePath": "uapi/app/read/ReadPageClient.tsx", + "passed": true + }, + { + "id": "deposit-route-uses-progressive-disclosure", + "sourcePath": "uapi/app/deposit/DepositPageClient.tsx", + "passed": true + }, + { + "id": "product-copy-removes-long-instructions", + "sourcePath": "uapi/components/base/bitcode/routes/product-route-shell.tsx", + "passed": true + }, + { + "id": "read-test-covers-shell-and-active-step", + "sourcePath": "uapi/tests/readPageClient.test.tsx", + "passed": true + }, + { + "id": "deposit-test-covers-shell-and-active-step", + "sourcePath": "uapi/tests/depositPageClient.test.tsx", + "passed": true + }, + { + "id": "packs-test-covers-shell", + "sourcePath": "uapi/tests/packsPageClient.test.tsx", + "passed": true + }, + { + "id": "protocol-test-covers-artifact", + "sourcePath": "packages/protocol/test/v43-route-ux-product-excellence.test.js", + "passed": true + }, + { + "id": "protocol-package-exports-gate8", + "sourcePath": "packages/protocol/src/index.js", + "passed": true + }, + { + "id": "protocol-types-export-gate8", + "sourcePath": "packages/protocol/src/index.d.ts", + "passed": true + }, + { + "id": "package-json-exposes-gate8", + "sourcePath": "package.json", + "passed": true + }, + { + "id": "gate-workflow-runs-gate8", + "sourcePath": ".github/workflows/bitcode-gate-quality.yml", + "passed": true + }, + { + "id": "canon-workflow-runs-gate8", + "sourcePath": ".github/workflows/bitcode-canon-quality.yml", + "passed": true + }, + { + "id": "generator-exists", + "sourcePath": "scripts/generate-v43-route-ux-product-excellence.mjs", + "passed": true + }, + { + "id": "checker-exists", + "sourcePath": "scripts/check-v43-gate8-route-ux-product-excellence.mjs", + "passed": true + } + ], + "coverage": { + "sharedRouteShellImplemented": true, + "sharedStepGridImplemented": true, + "keyboardCurrentStepImplemented": true, + "routeMetricsImplemented": true, + "productRouteStatePanelsImplemented": true, + "loadingEmptyErrorStatesImplemented": true, + "progressiveDisclosureImplemented": true, + "packsRouteUsesSharedShell": true, + "readRouteUsesSharedShell": true, + "depositRouteUsesSharedShell": true, + "selfReferentialProductCopyReduced": true, + "executionStreamReadbackRetained": true, + "responsiveGridPostureImplemented": true, + "sourceSafeMetadataOnly": true, + "protectedSourceVisible": false, + "rawSourceTextVisible": false, + "unpaidAssetPackSourceVisible": false, + "rawPromptVisible": false, + "interpolatedPromptVisible": false, + "rawProviderResponseVisible": false, + "walletPrivateMaterialVisible": false, + "settlementPrivatePayloadVisible": false, + "requiredPredicateCount": 30, + "passedPredicateCount": 30, + "failedPredicateIds": [] + } +} diff --git a/.bitcode/v43-route-vocabulary-inventory.json b/.bitcode/v43-route-vocabulary-inventory.json index 8e000bd7..ef47cf89 100644 --- a/.bitcode/v43-route-vocabulary-inventory.json +++ b/.bitcode/v43-route-vocabulary-inventory.json @@ -5,7 +5,7 @@ "currentTarget": "V42", "sourceSafetyVerdict": "source-safe-route-vocabulary-inventory-metadata", "generatedAt": "deterministic", - "artifactRoot": "v43-route-vocabulary-inventory:7b7ee161c29ff5abb1bd7427", + "artifactRoot": "v43-route-vocabulary-inventory:be23e8d462deba7c23f1eca7", "passed": true, "tokenIds": [ "route:/exchange", @@ -2081,7 +2081,7 @@ }, { "path": "BITCODE_SPEC_V43.md", - "pathRoot": "v43-route-vocabulary-file:9984fe8f4db39e1905d87b6b", + "pathRoot": "v43-route-vocabulary-file:7500bd3f04d8b323a7b29f83", "categories": [ "doc", "spec", @@ -2090,9 +2090,9 @@ "tokenCounts": { "route:/exchange": 5, "route:/terminal": 5, - "route:/packs": 21, - "route:/read": 18, - "route:/deposit": 15, + "route:/packs": 22, + "route:/read": 19, + "route:/deposit": 16, "symbol:Exchange": 4, "symbol:Terminal": 2, "symbol:Packs": 5, @@ -2104,14 +2104,14 @@ "word:terminal": 5, "word:self-referential": 4 }, - "totalMatches": 128, + "totalMatches": 131, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false }, { "path": "BITCODE_SPEC_V43_DELTA.md", - "pathRoot": "v43-route-vocabulary-file:82d8d77824f1a5660bd42b4e", + "pathRoot": "v43-route-vocabulary-file:dcd73f5cbbaff061529c6a90", "categories": [ "doc", "spec", @@ -2120,11 +2120,12 @@ "tokenCounts": { "route:/exchange": 4, "route:/terminal": 2, - "route:/packs": 13, - "route:/read": 8, - "route:/deposit": 10, + "route:/packs": 14, + "route:/read": 9, + "route:/deposit": 11, "symbol:Exchange": 2, "symbol:Terminal": 4, + "symbol:Packs": 1, "symbol:Reading": 6, "symbol:Depositing": 3, "symbol:PackActivity": 2, @@ -2133,14 +2134,14 @@ "word:terminal": 2, "word:self-referential": 3 }, - "totalMatches": 64, + "totalMatches": 68, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false }, { "path": "BITCODE_SPEC_V43_NOTES.md", - "pathRoot": "v43-route-vocabulary-file:52986106dbfa43471d544280", + "pathRoot": "v43-route-vocabulary-file:77472c109accfe2cd259ab8e", "categories": [ "doc", "spec", @@ -2149,28 +2150,28 @@ "tokenCounts": { "route:/exchange": 2, "route:/terminal": 1, - "route:/packs": 9, - "route:/read": 5, - "route:/deposit": 4, + "route:/packs": 10, + "route:/read": 6, + "route:/deposit": 5, "symbol:Exchange": 1, "symbol:Terminal": 1, "symbol:Packs": 1, - "symbol:Reading": 5, - "symbol:Depositing": 2, + "symbol:Reading": 6, + "symbol:Depositing": 3, "symbol:PackActivity": 2, "symbol:DepositAssetPackOption": 1, "word:exchange": 2, "word:terminal": 1, "word:self-referential": 2 }, - "totalMatches": 39, + "totalMatches": 44, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false }, { "path": "BITCODE_SPEC_V43_PARITY_MATRIX.md", - "pathRoot": "v43-route-vocabulary-file:9c29ea9ed1747259cb5cf1ae", + "pathRoot": "v43-route-vocabulary-file:f2f0241b791d67070efe3e8d", "categories": [ "doc", "spec", @@ -2179,9 +2180,9 @@ "tokenCounts": { "route:/exchange": 3, "route:/terminal": 1, - "route:/packs": 11, - "route:/read": 6, - "route:/deposit": 9, + "route:/packs": 12, + "route:/read": 7, + "route:/deposit": 10, "symbol:Packs": 1, "symbol:Reading": 1, "symbol:PackActivity": 5, @@ -2190,7 +2191,7 @@ "word:terminal": 1, "word:self-referential": 2 }, - "totalMatches": 44, + "totalMatches": 47, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false @@ -2315,7 +2316,7 @@ }, { "path": "README.md", - "pathRoot": "v43-route-vocabulary-file:2c31822c1f25522ed86613c9", + "pathRoot": "v43-route-vocabulary-file:297cc99cb56bd9fe6e989d16", "categories": [ "doc", "telemetry" @@ -2323,28 +2324,28 @@ "tokenCounts": { "route:/exchange": 5, "route:/terminal": 5, - "route:/packs": 11, - "route:/read": 8, - "route:/deposit": 7, + "route:/packs": 12, + "route:/read": 9, + "route:/deposit": 8, "symbol:Exchange": 16, "symbol:Terminal": 31, "symbol:Packs": 3, - "symbol:Reading": 30, - "symbol:Depositing": 5, + "symbol:Reading": 31, + "symbol:Depositing": 6, "symbol:PackActivity": 1, "symbol:DepositAssetPackOption": 1, "word:exchange": 17, "word:terminal": 7, "word:self-referential": 2 }, - "totalMatches": 149, + "totalMatches": 154, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false }, { "path": "SPECIFICATIONS_ROADMAP.md", - "pathRoot": "v43-route-vocabulary-file:317e1d3bf5a19dd41302913f", + "pathRoot": "v43-route-vocabulary-file:ce539868a759bd90522b0def", "categories": [ "doc", "spec", @@ -2353,9 +2354,9 @@ "tokenCounts": { "route:/exchange": 4, "route:/terminal": 3, - "route:/packs": 11, - "route:/read": 11, - "route:/deposit": 9, + "route:/packs": 12, + "route:/read": 12, + "route:/deposit": 10, "symbol:Exchange": 25, "symbol:Terminal": 42, "symbol:Reading": 59, @@ -2364,9 +2365,9 @@ "symbol:DepositAssetPackOption": 1, "word:exchange": 20, "word:terminal": 6, - "word:self-referential": 4 + "word:self-referential": 3 }, - "totalMatches": 207, + "totalMatches": 209, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false @@ -5955,7 +5956,7 @@ }, { "path": "packages/protocol/README.md", - "pathRoot": "v43-route-vocabulary-file:450e9569c135f17e69e2af65", + "pathRoot": "v43-route-vocabulary-file:275e096e2394d84312e091dc", "categories": [ "doc", "package", @@ -5964,20 +5965,20 @@ "tokenCounts": { "route:/exchange": 4, "route:/terminal": 2, - "route:/packs": 8, - "route:/read": 5, - "route:/deposit": 3, + "route:/packs": 9, + "route:/read": 6, + "route:/deposit": 4, "symbol:Exchange": 17, "symbol:Terminal": 29, "symbol:Packs": 1, - "symbol:Reading": 34, - "symbol:Depositing": 6, + "symbol:Reading": 35, + "symbol:Depositing": 7, "symbol:PackActivity": 1, "word:exchange": 16, "word:terminal": 6, "word:self-referential": 1 }, - "totalMatches": 133, + "totalMatches": 138, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false @@ -7259,6 +7260,27 @@ "rawSourceTextSerialized": false, "sourceSnippetSerialized": false }, + { + "path": "packages/protocol/src/canonical/v43-route-ux-product-excellence.js", + "pathRoot": "v43-route-vocabulary-file:c7db7ddec38e961e1af89c0d", + "categories": [ + "package", + "telemetry" + ], + "tokenCounts": { + "route:/packs": 2, + "route:/read": 2, + "route:/deposit": 2, + "symbol:Packs": 2, + "symbol:Reading": 3, + "symbol:Depositing": 3, + "word:self-referential": 2 + }, + "totalMatches": 16, + "sourceSafeMetadataOnly": true, + "rawSourceTextSerialized": false, + "sourceSnippetSerialized": false + }, { "path": "packages/protocol/src/canonical/v43-route-vocabulary-inventory.js", "pathRoot": "v43-route-vocabulary-file:157fd43a1b0d92c5e4c6d901", @@ -10085,6 +10107,23 @@ "rawSourceTextSerialized": false, "sourceSnippetSerialized": false }, + { + "path": "scripts/check-v43-gate8-route-ux-product-excellence.mjs", + "pathRoot": "v43-route-vocabulary-file:bc39e71d297fd3dadcd02abc", + "categories": [ + "script", + "telemetry" + ], + "tokenCounts": { + "route:/packs": 2, + "route:/read": 2, + "route:/deposit": 2 + }, + "totalMatches": 6, + "sourceSafeMetadataOnly": true, + "rawSourceTextSerialized": false, + "sourceSnippetSerialized": false + }, { "path": "scripts/code-review/README.md", "pathRoot": "v43-route-vocabulary-file:fef2886ffeed000a3327379c", @@ -11421,7 +11460,7 @@ }, { "path": "uapi/app/deposit/DepositPageClient.tsx", - "pathRoot": "v43-route-vocabulary-file:7ce948d8d5630a04dc7fc207", + "pathRoot": "v43-route-vocabulary-file:ed94c3944988d6918c0e7480", "categories": [ "component", "telemetry" @@ -11429,11 +11468,11 @@ "tokenCounts": { "route:/terminal": 12, "route:/packs": 1, - "symbol:Reading": 3, + "symbol:Reading": 2, "symbol:Depositing": 1, "word:terminal": 23 }, - "totalMatches": 40, + "totalMatches": 39, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false @@ -11705,17 +11744,16 @@ }, { "path": "uapi/app/packs/PacksPageClient.tsx", - "pathRoot": "v43-route-vocabulary-file:fb5cb2d34c0b644456d0f9ee", + "pathRoot": "v43-route-vocabulary-file:302a64482199b93281b6bc2d", "categories": [ "component", "telemetry" ], "tokenCounts": { "route:/packs": 1, - "symbol:Packs": 1, - "symbol:Reading": 1 + "symbol:Packs": 1 }, - "totalMatches": 3, + "totalMatches": 2, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false @@ -11754,7 +11792,7 @@ }, { "path": "uapi/app/read/ReadPageClient.tsx", - "pathRoot": "v43-route-vocabulary-file:5c1c473c8882148acde2c91d", + "pathRoot": "v43-route-vocabulary-file:1f818574d002de39986ecf9d", "categories": [ "component", "telemetry" @@ -11763,10 +11801,10 @@ "route:/terminal": 11, "route:/packs": 1, "route:/read": 1, - "symbol:Reading": 10, + "symbol:Reading": 11, "word:terminal": 24 }, - "totalMatches": 47, + "totalMatches": 48, "sourceSafeMetadataOnly": true, "rawSourceTextSerialized": false, "sourceSnippetSerialized": false @@ -15699,23 +15737,23 @@ } ], "coverage": { - "sourceFileCount": 923, + "sourceFileCount": 925, "tokenTotals": { "route:/exchange": 147, "route:/terminal": 1475, - "route:/packs": 184, - "route:/read": 295, - "route:/deposit": 167, + "route:/packs": 195, + "route:/read": 306, + "route:/deposit": 178, "symbol:Exchange": 1964, "symbol:Terminal": 3091, - "symbol:Packs": 50, - "symbol:Reading": 1334, - "symbol:Depositing": 243, + "symbol:Packs": 53, + "symbol:Reading": 1339, + "symbol:Depositing": 249, "symbol:PackActivity": 29, "symbol:DepositAssetPackOption": 33, "word:exchange": 1708, "word:terminal": 3735, - "word:self-referential": 31 + "word:self-referential": 32 }, "categoryTotals": { "route": 14, @@ -15723,10 +15761,10 @@ "test": 224, "doc": 169, "api": 43, - "telemetry": 662, + "telemetry": 664, "workflow": 12, - "script": 121, - "package": 321, + "script": 122, + "package": 322, "spec": 76 }, "routeVocabularyInventoryComplete": true, diff --git a/.github/workflows/bitcode-canon-quality.yml b/.github/workflows/bitcode-canon-quality.yml index d50ebab2..5ac9c9d8 100644 --- a/.github/workflows/bitcode-canon-quality.yml +++ b/.github/workflows/bitcode-canon-quality.yml @@ -346,6 +346,9 @@ jobs: if [ -f scripts/check-v43-gate7-deposit-option-admission.mjs ]; then node scripts/check-v43-gate7-deposit-option-admission.mjs --skip-branch-check --skip-uapi-tests --skip-package-tests fi + if [ -f scripts/check-v43-gate8-route-ux-product-excellence.mjs ]; then + node scripts/check-v43-gate8-route-ux-product-excellence.mjs --skip-branch-check --skip-uapi-tests + fi fi else echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2 diff --git a/.github/workflows/bitcode-gate-quality.yml b/.github/workflows/bitcode-gate-quality.yml index 00cb67a4..6cfb1d14 100644 --- a/.github/workflows/bitcode-gate-quality.yml +++ b/.github/workflows/bitcode-gate-quality.yml @@ -475,6 +475,9 @@ jobs: if [ -f scripts/check-v43-gate7-deposit-option-admission.mjs ]; then node scripts/check-v43-gate7-deposit-option-admission.mjs --skip-branch-check --skip-uapi-tests --skip-package-tests fi + if [ -f scripts/check-v43-gate8-route-ux-product-excellence.mjs ]; then + node scripts/check-v43-gate8-route-ux-product-excellence.mjs --skip-branch-check --skip-uapi-tests + fi fi else echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2 @@ -526,6 +529,9 @@ jobs: if [ -f scripts/check-v43-gate7-deposit-option-admission.mjs ]; then node scripts/check-v43-gate7-deposit-option-admission.mjs --skip-branch-check --skip-uapi-tests --skip-package-tests fi + if [ -f scripts/check-v43-gate8-route-ux-product-excellence.mjs ]; then + node scripts/check-v43-gate8-route-ux-product-excellence.mjs --skip-branch-check --skip-uapi-tests + fi pnpm --filter @bitcode/protocol test pnpm --filter @bitcode/btd exec jest --config jest.config.cjs --runInBand --forceExit pnpm --filter @bitcode/pipeline-asset-pack exec jest --config jest.config.cjs --passWithNoTests --forceExit diff --git a/BITCODE_SPEC_V43.md b/BITCODE_SPEC_V43.md index e72dfe93..447f60c3 100644 --- a/BITCODE_SPEC_V43.md +++ b/BITCODE_SPEC_V43.md @@ -220,6 +220,17 @@ settlement. Gate 8 must improve route layout, visual hierarchy, copy, progressive disclosure, execution stream usage, empty/error/loading states, keyboard/responsive behavior, and reusable themed components across `/packs`, `/read`, and `/deposit`. It must remove in-app self-referential explanatory copy outside public docs. +Gate 8 closes with `ProductRouteShell`, `ProductRouteStepGrid`, +`ProductRouteStatePanel`, `ProductRouteDisclosure`, and the generated +`.bitcode/v43-route-ux-product-excellence.json` proof. `/packs`, `/read`, and +`/deposit` must share a consistent themed route frame, concise route summaries, +source-safe metrics, keyboard-accessible step buttons, loading/empty/error +states, and expandable proof/source-safety detail. Product copy must be route +and status vocabulary, not explanations of the interface itself. Gate 8 must +not change route state-machine authority, disclose protected source, disclose +unpaid AssetPack source, serialize prompts/provider responses, or weaken the +settlement-gated source boundary. + ## V43 Gate 9 Cross-Route Rehearsal, Telemetry, And Repair Gate 9 must rehearse the full path across `/deposit`, `/read`, and `/packs`: synthesize deposit options, admit a deposit AssetPack, request Reading, find fits, preview, settle, deliver, compensate, and inspect activity. It must cover local/staging-testnet lanes, telemetry, database/ledger/storage synchronization, and repair states. diff --git a/BITCODE_SPEC_V43_DELTA.md b/BITCODE_SPEC_V43_DELTA.md index 83275c43..9511bcd2 100644 --- a/BITCODE_SPEC_V43_DELTA.md +++ b/BITCODE_SPEC_V43_DELTA.md @@ -8,7 +8,7 @@ - Prior canonical anchor: `BITCODE_SPEC_V42.md` - Prior generated proof appendix: `BITCODE_SPEC_V42_PROVEN.md` - Generated structured artifact inventory: `.bitcode/v43-spec-family-report.json`, `.bitcode/v43-canonical-input-report.json`, and V43 gate artifacts as introduced -- Source parity state: Gate 1 opens V43 specification and validation posture; Gate 2 adds source-safe route vocabulary inventory and migration-matrix proof +- Source parity state: Gate 1 opens V43 specification and validation posture; Gate 2 adds source-safe route vocabulary inventory and migration-matrix proof; Gates 3 through 8 now close Packs, Read, Deposit, deposit policy/admission, and shared route UX proof ## Why V43 exists @@ -123,6 +123,19 @@ and execution-stream telemetry. Gate 7 still does not mint BTD, transfer rights, or disclose unpaid AssetPack source; those boundaries stay with future Need-Fit settlement. +## Gate 8 delta closure + +Gate 8 adds `ProductRouteShell`, `ProductRouteStepGrid`, +`ProductRouteStatePanel`, `ProductRouteDisclosure`, the generated +`.bitcode/v43-route-ux-product-excellence.json` artifact, package exports, +protocol tests, workflow checks, route shell assertions, and focused +`/packs`/`/read`/`/deposit` tests. The route clients now share a themed product +frame, source-safe metrics, concise route summaries, keyboard-accessible step +buttons, compact loading/empty/error states, and expandable disclosure +boundaries. In-app route copy is reduced to workflow/status vocabulary; deeper +protocol explanation stays in docs and generated proofs. Gate 8 keeps every +existing V43 state machine and source-safety boundary intact. + ## Commit-Body Direction V43 gate commits should state the route/product surface changed, the protocol objects preserved, the proof/test commands run, and the source-safety boundaries maintained. Gate PR titles must begin with `V43 Gate N:`. diff --git a/BITCODE_SPEC_V43_NOTES.md b/BITCODE_SPEC_V43_NOTES.md index b316f29e..ead08bb7 100644 --- a/BITCODE_SPEC_V43_NOTES.md +++ b/BITCODE_SPEC_V43_NOTES.md @@ -8,7 +8,7 @@ - Prior canonical anchor: `BITCODE_SPEC_V42.md` - Prior generated proof appendix: `BITCODE_SPEC_V42_PROVEN.md` - Generated structured artifact inventory: `.bitcode/v43-spec-family-report.json`, `.bitcode/v43-canonical-input-report.json`, and future V43 gate artifacts -- Source parity state: notes define operating memory for V43 gates; implementation parity is pending gate work +- Source parity state: notes define operating memory for V43 gates; Gates 2 through 8 now have generated proof-backed implementation parity ## Notes companion rule @@ -73,6 +73,15 @@ must not enter the Depository. Admitted options still do not mint BTD, transfer rights, reveal unpaid AssetPack source, or serialize prompts, provider responses, wallet material, or private settlement payloads. +Gate 8 closes the shared product route shell polish layer. `ProductRouteShell` now frames +`/packs`, `/read`, and `/deposit`; `ProductRouteStepGrid` owns the Reading and +Depositing step controls with active `aria-current` semantics; `ProductRouteStatePanel` +normalizes loading, empty, and error states; and `ProductRouteDisclosure` +keeps proof/source-safety detail expandable. Product route copy should stay +concise: route labels, status summaries, metrics, and visible/withheld +boundaries. Longer explanation belongs in public documentation and generated +proofs, not the core product flow. + ## V43 copy boundary Outside public docs, avoid self-referential copy such as text explaining that a component is powerful or that Bitcode is doing a thing. Use clear route names, labels, status rows, measurement summaries, empty states, and expandable proof metadata. Public docs may explain the protocol; product UI should operate it. diff --git a/BITCODE_SPEC_V43_PARITY_MATRIX.md b/BITCODE_SPEC_V43_PARITY_MATRIX.md index 794de11e..e65738f0 100644 --- a/BITCODE_SPEC_V43_PARITY_MATRIX.md +++ b/BITCODE_SPEC_V43_PARITY_MATRIX.md @@ -8,7 +8,7 @@ - Prior canonical anchor: `BITCODE_SPEC_V42.md` - Prior generated proof appendix: `BITCODE_SPEC_V42_PROVEN.md` - Generated structured artifact inventory: `.bitcode/v43-spec-family-report.json`, `.bitcode/v43-canonical-input-report.json`, and future V43 gate artifacts -- Source parity state: V43 Gate 1 parity is documentation/workflow posture; V43 Gate 2 parity is source-safe inventory and migration planning; V43 Gate 3 parity is PackActivity source-safe master-detail implementation; V43 Gate 4 parity is `/read`; V43 Gate 5 parity is `/deposit` and source-safe DepositAssetPackOption synthesis; V43 Gate 6 parity is source-safe deposit policy and compensation scoring; V43 Gate 7 parity is source-safe deposit option review, admission, indexing, storage projection, telemetry, and `/packs` synchronization +- Source parity state: V43 Gate 1 parity is documentation/workflow posture; V43 Gate 2 parity is source-safe inventory and migration planning; V43 Gate 3 parity is PackActivity source-safe master-detail implementation; V43 Gate 4 parity is `/read`; V43 Gate 5 parity is `/deposit` and source-safe DepositAssetPackOption synthesis; V43 Gate 6 parity is source-safe deposit policy and compensation scoring; V43 Gate 7 parity is source-safe deposit option review, admission, indexing, storage projection, telemetry, and `/packs` synchronization; V43 Gate 8 parity is shared product route UX, concise copy, progressive disclosure, and loading/empty/error route states ## Purpose @@ -29,7 +29,7 @@ Audit V43 against `BITCODE_SPEC_V43.md`, V42 active canon, route source, package | Deposit route | `DepositRouteSession`, `/deposit`, source-safe connected-source option synthesis, source-safe option cards, route tests, package tests, generated proof, and retained deposit composer reuse | `packages/protocol/src/canonical/v43-deposit-route-options.js`, `.bitcode/v43-deposit-route-options.json`, `uapi/app/deposit`, `packages/pipelines/asset-pack/src/deposit-asset-pack-options.ts` | implemented | | Criticality/ROI policy | Source criticality, demand, ROI, BTD potential, and BTC source-to-shares compensation posture | `packages/protocol/src/canonical/v43-deposit-policy-compensation.js`, `.bitcode/v43-deposit-policy-compensation.json`, `packages/pipelines/asset-pack/src/deposit-asset-pack-option-policy.ts`, `/deposit` policy readback | implemented | | Deposit option admission | Approved, policy-eligible deposit options enter source-safe Depository projections and `/packs` activity while rejected, resynthesis, pending, and policy-blocked options stay out | `packages/protocol/src/canonical/v43-deposit-option-admission.js`, `.bitcode/v43-deposit-option-admission.json`, `packages/pipelines/asset-pack/src/deposit-asset-pack-option-admission.ts`, `/deposit` admission readback, `/packs` activity model | implemented | -| UX excellence | Self-explanatory, polished, progressive-detail UI without self-referential product copy | future Gate 8 artifact | draft-required | +| UX/UI product excellence | Self-explanatory, polished, progressive-detail UI without self-referential product copy | `packages/protocol/src/canonical/v43-route-ux-product-excellence.js`, `.bitcode/v43-route-ux-product-excellence.json`, `uapi/components/base/bitcode/routes/product-route-shell.tsx`, `/packs`, `/read`, `/deposit` route clients | implemented | | Rehearsal | Local/staging-testnet cross-route path verifies deposit, read, packs, settlement, compensation, delivery | future Gate 9 artifact | draft-required | | Promotion readiness | V43 generated proof and active V43 / draft V44 posture ready | future Gate 10 artifact | draft-required | @@ -47,7 +47,8 @@ Audit V43 against `BITCODE_SPEC_V43.md`, V42 active canon, route source, package | Gate 5 Deposit route proof | `V43DepositRouteOptions` exports, generated artifact, source-safe route model/UI tests, asset-pack option synthesis tests, workflow checks, and `check:v43-gate5` exist | implemented | | Gate 6 Deposit policy proof | `DepositAssetPackOptionPolicyReport`, generated artifact, source-safe route model/UI tests, asset-pack policy tests, workflow checks, and `check:v43-gate6` exist | implemented | | Gate 7 Deposit option admission proof | `DepositAssetPackOptionAdmissionReport`, generated artifact, source-safe route model/UI tests, asset-pack admission tests, PackActivity sync tests, workflow checks, and `check:v43-gate7` exist | implemented | -| Implementation | Route and pipeline source changes are not part of Gates 1 or 2; Gate 3 implements only `/packs` and PackActivity; Gate 4 implements `/read`; Gate 5 implements `/deposit` option synthesis; Gate 6 implements policy scoring; Gate 7 implements depositor decisions, admission receipts, index/storage projections, telemetry, and `/packs` synchronization | accepted boundary | +| Gate 8 route UX proof | `ProductRouteShell`, `ProductRouteStepGrid`, `ProductRouteStatePanel`, `ProductRouteDisclosure`, generated artifact, source-safe route shell tests, workflow checks, and `check:v43-gate8` exist | implemented | +| Implementation | Route and pipeline source changes are not part of Gates 1 or 2; Gate 3 implements only `/packs` and PackActivity; Gate 4 implements `/read`; Gate 5 implements `/deposit` option synthesis; Gate 6 implements policy scoring; Gate 7 implements depositor decisions, admission receipts, index/storage projections, telemetry, and `/packs` synchronization; Gate 8 implements shared route UX only | accepted boundary | ## V43 accepted boundaries @@ -63,6 +64,10 @@ index, store, or synchronize deposit AssetPacks into `/packs`; those remain Gate policy-eligible options, project source-safe index/storage metadata, and synchronize admitted options into `/packs`; it must not mint BTD, transfer rights, broadcast settlement, or disclose unpaid AssetPack source. +Gate 8 may refine route layout, concise copy, shared components, accessible +step controls, progressive detail, and loading/empty/error states, but it must +not move state-machine authority, change settlement law, or disclose protected +source. ## V43 completion condition diff --git a/README.md b/README.md index c9f2df0f..9b34ccf0 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,16 @@ preview continuity, execution-stream telemetry, and `/packs` options. It still does not mint BTD, transfer rights, or reveal unpaid AssetPack source. +V43 Gate 8 adds `ProductRouteShell`, `ProductRouteStepGrid`, +`ProductRouteStatePanel`, `ProductRouteDisclosure`, +`.bitcode/v43-route-ux-product-excellence.json`, +`generate:v43-route-ux-product-excellence`, +`check:v43-route-ux-product-excellence`, and `check:v43-gate8`. It refines +`/packs`, `/read`, and `/deposit` into a shared themed route frame with concise +copy, source-safe route metrics, keyboard current-step semantics, loading/ +empty/error states, and progressive disclosure boundaries while keeping every +Reading, Depositing, settlement, and source-safety invariant intact. + Exchange is inherited V36 canon: market-wide activity master-detail, buy/sell/ bid/ask/cancel/accept/settle/history flows, AssetPack range trading, rights-transfer review, pricing/liquidity/wrapper analysis, settlement diff --git a/SPECIFICATIONS_ROADMAP.md b/SPECIFICATIONS_ROADMAP.md index 8da920ef..fa012b30 100644 --- a/SPECIFICATIONS_ROADMAP.md +++ b/SPECIFICATIONS_ROADMAP.md @@ -5,8 +5,8 @@ - Current active canonical pointer: `BITCODE_SPEC.txt` -> `V42` - Current active canon: `BITCODE_SPEC_V42.md` - Current draft target: `BITCODE_SPEC_V43.md`. -- Current working gate: V43 Gate 7 Deposit Option Review, Admission, And Pack Activity Synchronization. -- Next queued work after V43 Gate 7: UX/UI product excellence across `/packs`, `/read`, and `/deposit`, including polished route layout, progressive detail, execution-stream clarity, empty/error/loading states, responsive/keyboard behavior, and removal of in-app self-referential copy. +- Current working gate: V43 Gate 8 UX/UI Product Excellence Pass. +- Next queued work after V43 Gate 8: cross-route local/staging-testnet rehearsal across `/deposit`, `/read`, and `/packs`, including telemetry/database/ledger/storage synchronization and repair readback. - Latest closed version: V42 Reliable MVP Experience, which promoted shortest-path Depositing, five-step Reading, ReadNeed review/resynthesis, ReadFitsFinding source-safe preview and quote, settlement rights transfer, repository delivery, AI-reading demonstration, local/staging MVP rehearsal, and V42 promotion readiness. - Recent V42 canonical promotion anchor: V42 canonical promotion updated `BITCODE_SPEC.txt` to `V42`, generated `BITCODE_SPEC_V42_PROVEN.md`, preserved active V42 / draft V43 runtime posture, and closed reliable MVP experience canon. - Recent V42 opening anchor: reliable MVP experience opens over promoted V41 with V42 SPEC, DELTA, NOTES, and PARITY files, `check:v42-gate1`, active V41 / draft V42 posture, and a nine-gate plan for shortest-path Depositing, five-step Reading, ReadNeed product closure, ReadFitsFinding preview and quote closure, settlement and repository delivery, AI-reading demonstration, local/staging rehearsal, and promotion readiness. @@ -24,6 +24,7 @@ - V43 Gate 5 closure anchor: route-product cleanup now owns package-backed `V43DepositRouteOptions`, deterministic `.bitcode/v43-deposit-route-options.json`, `DepositRouteSession`, `/deposit`, five-step Depositing UX, connected-source option synthesis, `DepositAssetPackOptionSynthesis`, source-safe AssetPack option cards, option measurement roots, demand signal roots, retained deposit composer reuse, route/nav/footer ownership, focused UAPI/package/protocol tests, workflow wiring, and `check:v43-gate5`. - V43 Gate 6 closure anchor: route-product cleanup now owns package-backed `DepositAssetPackOptionPolicyReport`, deterministic `.bitcode/v43-deposit-policy-compensation.json`, source criticality scoring, likely demand scoring, deterministic estimated-gross-minus-development-cost ROI, estimate-only BTD potential, future-reader BTC source-to-shares compensation route preview, critical-source pre-admission blocking, `/deposit` policy readback, source-safe route/package/protocol tests, workflow wiring, and `check:v43-gate6`. - V43 Gate 7 closure anchor: route-product cleanup now owns package-backed `DepositAssetPackOptionAdmissionReport`, deterministic `.bitcode/v43-deposit-option-admission.json`, approve/reject/resynthesis review decisions, source-safe admission receipts, approved-policy-eligible Depository admission, semantic/lexical/metadata index projection, object-storage metadata and external source pointer projection, BTC source-to-shares compensation preview continuity, execution-stream telemetry, `/packs` `depository-assetpack` synchronization, focused route/package/activity/protocol tests, workflow wiring, and `check:v43-gate7`. +- V43 Gate 8 closure anchor: route-product cleanup now owns shared `ProductRouteShell`, `ProductRouteStepGrid`, `ProductRouteStatePanel`, and `ProductRouteDisclosure` components, deterministic `.bitcode/v43-route-ux-product-excellence.json`, concise `/packs`, `/read`, and `/deposit` product route copy, keyboard current-step semantics, route loading/empty/error states, progressive source-safety disclosure, focused route/protocol tests, workflow wiring, and `check:v43-gate8`. - Recent V41 closure anchor: V41 canonical promotion updated `BITCODE_SPEC.txt` to `V41`, generated `BITCODE_SPEC_V41_PROVEN.md`, preserved active V41 / draft V42 runtime posture, and closed prompt-program excellence canon. - Recent V40 closure anchor: V40 canonical promotion updated `BITCODE_SPEC.txt` to `V40`, generated `BITCODE_SPEC_V40_PROVEN.md`, preserved active V40 / draft V41 runtime posture, and closed exhaustive commercial application testing canon. - Recent V39 closure anchor: V39 canonical promotion updated `BITCODE_SPEC.txt` to `V39`, generated `BITCODE_SPEC_V39_PROVEN.md`, preserved active V39 / draft V40 runtime posture, and closed commercial Reading readiness canon. diff --git a/package.json b/package.json index 1e81929a..e79d4feb 100644 --- a/package.json +++ b/package.json @@ -348,6 +348,9 @@ "generate:v43-deposit-option-admission": "node scripts/generate-v43-deposit-option-admission.mjs", "check:v43-deposit-option-admission": "node scripts/generate-v43-deposit-option-admission.mjs --check", "check:v43-gate7": "node scripts/check-v43-gate7-deposit-option-admission.mjs", + "generate:v43-route-ux-product-excellence": "node scripts/generate-v43-route-ux-product-excellence.mjs", + "check:v43-route-ux-product-excellence": "node scripts/generate-v43-route-ux-product-excellence.mjs --check", + "check:v43-gate8": "node scripts/check-v43-gate8-route-ux-product-excellence.mjs", "generate:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs", "check:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs --check", "check:v38-gate2": "node scripts/check-v38-gate2-inference-surface-inventory.mjs", diff --git a/packages/protocol/README.md b/packages/protocol/README.md index 81a18cef..6c3ab749 100644 --- a/packages/protocol/README.md +++ b/packages/protocol/README.md @@ -143,6 +143,18 @@ continuity, execution-stream telemetry, and `/packs` `depository-assetpack` synchronization while keeping BTD mint, rights transfer, settlement broadcast, and unpaid AssetPack source disclosure outside deposit-side admission. +V43 Gate 8 adds `V43RouteUxProductExcellence` through +`packages/protocol/src/canonical/v43-route-ux-product-excellence.js`, +`packages/protocol/test/v43-route-ux-product-excellence.test.js`, +`.bitcode/v43-route-ux-product-excellence.json`, +`generate:v43-route-ux-product-excellence`, +`check:v43-route-ux-product-excellence`, and `check:v43-gate8`. It binds the +shared product route shell, Reading/Depositing step grid, loading/empty/error +state panels, progressive disclosure, concise route copy, focused route tests, +and workflow wiring for `/packs`, `/read`, and `/deposit` without exposing +protected source, unpaid AssetPack source, prompts, provider responses, wallet +private material, or private settlement payloads. + Historical V39 promotion moved this package through the `V39` active, `V40` draft posture. V40 promotion has since advanced the current package posture to `V40` active, `V41` draft. diff --git a/packages/protocol/src/canonical/v43-deposit-policy-compensation.js b/packages/protocol/src/canonical/v43-deposit-policy-compensation.js index c7cca5f2..c6466d85 100644 --- a/packages/protocol/src/canonical/v43-deposit-policy-compensation.js +++ b/packages/protocol/src/canonical/v43-deposit-policy-compensation.js @@ -92,6 +92,15 @@ function predicateResult(id, sourcePath, passed) { return { id, sourcePath, passed: Boolean(passed) }; } +function includesWithWhitespace(source, phrase) { + const pattern = phrase + .trim() + .split(/\s+/u) + .map((part) => part.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&')) + .join('\\s+'); + return new RegExp(pattern, 'u').test(source); +} + export const V43_DEPOSIT_POLICY_COMPENSATION_CONTRACT_ROWS = Object.freeze([ { rowId: 'criticality-policy', @@ -145,7 +154,7 @@ function buildPredicateResults(repoRoot) { predicateResult('policy-model-defers-gate7-admission', SOURCE_ROOTS.policyModel, sources.policyModel.includes('future-gate7-deposit-option-review') && sources.policyModel.includes('admissionAndIndexingOwnedBy')), predicateResult('policy-model-forbids-source-leakage', SOURCE_ROOTS.policyModel, sources.policyModel.includes('rawSourceTextVisible: false') && sources.policyModel.includes('settlementPrivatePayloadVisible: false') && sources.policyModel.includes('walletPrivateMaterialVisible: false')), predicateResult('route-model-owns-policy', SOURCE_ROOTS.routeModel, sources.routeModel.includes('DepositAssetPackOptionPolicyReport') && sources.routeModel.includes('sourceCriticalityDemandRoiPolicyOwnedByGate6')), - predicateResult('deposit-client-renders-policy', SOURCE_ROOTS.client, sources.client.includes('DepositAssetPackOptionPolicy') && sources.client.includes('BTC source-to-shares preview')), + predicateResult('deposit-client-renders-policy', SOURCE_ROOTS.client, sources.client.includes('DepositAssetPackOptionPolicy') && includesWithWhitespace(sources.client, 'BTC source-to-shares preview')), predicateResult('asset-pack-package-exports-policy', SOURCE_ROOTS.packageIndex, sources.packageIndex.includes("export * from './deposit-asset-pack-option-policy'")), predicateResult('asset-pack-manifest-exports-policy', SOURCE_ROOTS.packageManifest, sources.packageManifest.includes('"./deposit-asset-pack-option-policy"')), predicateResult('policy-test-covers-report', SOURCE_ROOTS.policyModelTest, sources.policyModelTest.includes('buildDepositAssetPackOptionPolicyReport') && sources.policyModelTest.includes('blocked-before-admission')), diff --git a/packages/protocol/src/canonical/v43-deposit-route-options.js b/packages/protocol/src/canonical/v43-deposit-route-options.js index f70259a8..42b34944 100644 --- a/packages/protocol/src/canonical/v43-deposit-route-options.js +++ b/packages/protocol/src/canonical/v43-deposit-route-options.js @@ -162,7 +162,13 @@ function buildPredicateResults(repoRoot) { predicateResult('route-model-defines-pipeline-ownership', SOURCE_ROOTS.routeModel, sources.routeModel.includes('DepositAssetPackOptionSynthesis') && sources.routeModel.includes('sourceCriticalityDemandRoiPolicyDeferredToGate6')), predicateResult('route-model-forbids-source-leakage', SOURCE_ROOTS.routeModel, sources.routeModel.includes('protectedSourceVisible: false') && sources.routeModel.includes('rawSourceTextVisible: false') && sources.routeModel.includes('unpaidAssetPackSourceVisible: false')), predicateResult('deposit-page-canonical-route', SOURCE_ROOTS.page, sources.page.includes("canonical: '/deposit'") && sources.page.includes('DepositPageClient')), - predicateResult('deposit-client-renders-five-step-route', SOURCE_ROOTS.client, sources.client.includes('data-testid={`deposit-route-step-${step.id}`}') && sources.client.includes('Deposit steps')), + predicateResult( + 'deposit-client-renders-five-step-route', + SOURCE_ROOTS.client, + (sources.client.includes('data-testid={`deposit-route-step-${step.id}`}') || + (sources.client.includes('ProductRouteStepGrid') && sources.client.includes('testIdPrefix="deposit-route-step"'))) && + sources.client.includes('Deposit steps'), + ), predicateResult('deposit-client-renders-options', SOURCE_ROOTS.client, sources.client.includes('DepositAssetPackOptionSynthesis') && sources.client.includes('Source-safe AssetPack proposals')), predicateResult('deposit-client-reuses-terminal-primitives', SOURCE_ROOTS.client, sources.client.includes('TerminalRepositoryContextPanel') && sources.client.includes('TerminalSupplySelectionPanel') && sources.client.includes('TerminalDepositComposer')), predicateResult('option-model-defines-request', SOURCE_ROOTS.optionModel, sources.optionModel.includes('DepositOptionSynthesisRequest') && sources.optionModel.includes('depositoryDemandSignals') && sources.optionModel.includes('readingDemandSignals')), diff --git a/packages/protocol/src/canonical/v43-read-route-five-step-ux.js b/packages/protocol/src/canonical/v43-read-route-five-step-ux.js index 3c8ca73e..cdd11005 100644 --- a/packages/protocol/src/canonical/v43-read-route-five-step-ux.js +++ b/packages/protocol/src/canonical/v43-read-route-five-step-ux.js @@ -169,7 +169,13 @@ function buildPredicateResults(repoRoot) { predicateResult('route-model-defines-pipeline-ownership', SOURCE_ROOTS.routeModel, sources.routeModel.includes('ReadNeedComprehensionSynthesis') && sources.routeModel.includes('ReadFitsFindingSynthesis')), predicateResult('route-model-forbids-source-leakage', SOURCE_ROOTS.routeModel, sources.routeModel.includes('protectedSourceVisible: false') && sources.routeModel.includes('unpaidAssetPackSourceVisible: false')), predicateResult('read-page-canonical-route', SOURCE_ROOTS.page, sources.page.includes("canonical: '/read'") && sources.page.includes('ReadPageClient')), - predicateResult('read-client-renders-five-step-route', SOURCE_ROOTS.client, sources.client.includes('data-testid={`read-route-step-${step.id}`}') && sources.client.includes('Reading steps')), + predicateResult( + 'read-client-renders-five-step-route', + SOURCE_ROOTS.client, + (sources.client.includes('data-testid={`read-route-step-${step.id}`}') || + (sources.client.includes('ProductRouteStepGrid') && sources.client.includes('testIdPrefix="read-route-step"'))) && + sources.client.includes('Reading steps'), + ), predicateResult('read-client-reuses-live-workbench', SOURCE_ROOTS.client, sources.client.includes('TerminalDepositReadWorkbench') && sources.client.includes('showDemonstrationWorkbench={false}')), predicateResult('read-client-renders-source-safe-session', SOURCE_ROOTS.client, sources.client.includes('Source-safe read state') && sources.client.includes('Disclosure boundary')), predicateResult('read-client-records-activity', SOURCE_ROOTS.client, sources.client.includes('/api/executions/history') && sources.client.includes('buildTerminalExecutionHistoryRequest')), diff --git a/packages/protocol/src/canonical/v43-route-ux-product-excellence.js b/packages/protocol/src/canonical/v43-route-ux-product-excellence.js new file mode 100644 index 00000000..2a79d850 --- /dev/null +++ b/packages/protocol/src/canonical/v43-route-ux-product-excellence.js @@ -0,0 +1,248 @@ +// @ts-check + +import crypto from 'node:crypto'; +import { existsSync, readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const DEFAULT_REPO_ROOT = path.resolve(__dirname, '..', '..', '..', '..'); + +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH = '.bitcode/v43-route-ux-product-excellence.json'; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_SCHEMA_ID = 'bitcode.v43.routeUxProductExcellence.v1'; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_VERSION = 'V43'; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_CURRENT_TARGET = 'V42'; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_SAFETY_VERDICT = + 'source-safe-product-route-ux-metadata'; + +export const V43_ROUTE_UX_OBJECT_IDS = Object.freeze([ + 'ProductRouteShell', + 'ProductRouteStepGrid', + 'ProductRouteStatePanel', + 'ProductRouteDisclosure', + '/packs product route', + '/read product route', + '/deposit product route', +]); + +export const V43_ROUTE_UX_FIELD_IDS = Object.freeze([ + 'routeLabel', + 'routeTitle', + 'routeSummary', + 'metric', + 'step', + 'statePanel', + 'progressiveDisclosure', + 'sourceSafeBoundary', +]); + +export const V43_ROUTE_UX_FORBIDDEN_PAYLOAD_IDS = Object.freeze([ + 'protected_source_payload', + 'raw_source_text', + 'unpaid_assetpack_source', + 'raw_protected_prompt', + 'interpolated_prompt', + 'raw_provider_response', + 'wallet_private_material', + 'settlement_private_payload', +]); + +const SOURCE_ROOTS = Object.freeze({ + activePointer: 'BITCODE_SPEC.txt', + spec: 'BITCODE_SPEC_V43.md', + delta: 'BITCODE_SPEC_V43_DELTA.md', + notes: 'BITCODE_SPEC_V43_NOTES.md', + parity: 'BITCODE_SPEC_V43_PARITY_MATRIX.md', + roadmap: 'SPECIFICATIONS_ROADMAP.md', + readme: 'README.md', + protocolReadme: 'packages/protocol/README.md', + packageJson: 'package.json', + gateWorkflow: '.github/workflows/bitcode-gate-quality.yml', + canonWorkflow: '.github/workflows/bitcode-canon-quality.yml', + productRouteShell: 'uapi/components/base/bitcode/routes/product-route-shell.tsx', + packsClient: 'uapi/app/packs/PacksPageClient.tsx', + readClient: 'uapi/app/read/ReadPageClient.tsx', + depositClient: 'uapi/app/deposit/DepositPageClient.tsx', + packsTest: 'uapi/tests/packsPageClient.test.tsx', + readTest: 'uapi/tests/readPageClient.test.tsx', + depositTest: 'uapi/tests/depositPageClient.test.tsx', + protocolIndex: 'packages/protocol/src/index.js', + protocolTypes: 'packages/protocol/src/index.d.ts', + protocolTest: 'packages/protocol/test/v43-route-ux-product-excellence.test.js', + generator: 'scripts/generate-v43-route-ux-product-excellence.mjs', + checker: 'scripts/check-v43-gate8-route-ux-product-excellence.mjs', +}); + +function digest(value) { + return crypto.createHash('sha256').update(value).digest('hex').slice(0, 24); +} + +function readSource(repoRoot, sourcePath) { + const absolutePath = path.join(repoRoot, sourcePath); + return existsSync(absolutePath) ? readFileSync(absolutePath, 'utf8') : ''; +} + +function predicateResult(id, sourcePath, passed) { + return { id, sourcePath, passed: Boolean(passed) }; +} + +export const V43_ROUTE_UX_CONTRACT_ROWS = Object.freeze([ + { + rowId: 'shared-product-route-shell', + owner: SOURCE_ROOTS.productRouteShell, + contract: + 'Packs, Reading, and Depositing render through a shared themed product shell with route label, title, concise summary, and source-safe route metrics.', + requiredFields: ['ProductRouteShell', 'route-shell-packs', 'route-shell-read', 'route-shell-deposit'], + }, + { + rowId: 'keyboard-five-step-navigation', + owner: SOURCE_ROOTS.productRouteShell, + contract: + 'Reading and Depositing use a shared button-based step grid with visible active state, aria-current step semantics, and stable data attributes for route state tests.', + requiredFields: ['ProductRouteStepGrid', 'aria-current', 'data-reading-step-state', 'data-deposit-step-state'], + }, + { + rowId: 'state-panels-empty-error-loading', + owner: SOURCE_ROOTS.productRouteShell, + contract: + 'Packs, Reading, and Depositing share compact loading, empty, and error state panels without leaking source-bearing payloads.', + requiredFields: ['ProductRouteStatePanel', 'loading', 'empty', 'error'], + }, + { + rowId: 'progressive-source-safe-detail', + owner: SOURCE_ROOTS.productRouteShell, + contract: + 'Read and Deposit route proof detail remains expandable by default, with visible metadata and withheld protected-source boundaries stated as route state.', + requiredFields: ['ProductRouteDisclosure', 'Disclosure boundary', 'Withheld'], + }, + { + rowId: 'product-copy-reduced', + owner: SOURCE_ROOTS.spec, + contract: + 'In-app product copy is concise route/status vocabulary rather than self-referential instructions, while deeper protocol explanation stays in public documentation and proof artifacts.', + requiredFields: ['self-referential product copy', 'route structure', 'progressive proof detail'], + }, +]); + +function buildPredicateResults(repoRoot) { + const sources = Object.fromEntries( + Object.entries(SOURCE_ROOTS).map(([key, sourcePath]) => [key, readSource(repoRoot, sourcePath)]), + ); + const productCopy = [sources.packsClient, sources.readClient, sources.depositClient].join('\n'); + + return [ + predicateResult('active-canon-pointer-remains-v42', SOURCE_ROOTS.activePointer, sources.activePointer.trim() === 'V42'), + predicateResult('spec-defines-gate8', SOURCE_ROOTS.spec, sources.spec.includes('V43 Gate 8 UX/UI Product Excellence Pass')), + predicateResult('spec-records-shared-route-shell', SOURCE_ROOTS.spec, sources.spec.includes('ProductRouteShell') && sources.spec.includes('ProductRouteStepGrid')), + predicateResult('delta-records-gate8', SOURCE_ROOTS.delta, sources.delta.includes('Gate 8') && sources.delta.includes('v43-route-ux-product-excellence')), + predicateResult('notes-records-gate8', SOURCE_ROOTS.notes, sources.notes.includes('Gate 8') && sources.notes.includes('product route shell')), + predicateResult('parity-records-gate8', SOURCE_ROOTS.parity, sources.parity.includes('UX/UI product excellence') && sources.parity.includes('v43-route-ux-product-excellence')), + predicateResult('roadmap-records-gate8', SOURCE_ROOTS.roadmap, sources.roadmap.includes('V43 Gate 8 closure anchor')), + predicateResult('readme-records-gate8', SOURCE_ROOTS.readme, sources.readme.includes('V43 Gate 8')), + predicateResult('protocol-readme-records-gate8', SOURCE_ROOTS.protocolReadme, sources.protocolReadme.includes('V43 Gate 8')), + predicateResult('shared-shell-implements-route-shell', SOURCE_ROOTS.productRouteShell, sources.productRouteShell.includes('ProductRouteShell') && sources.productRouteShell.includes('ProductRouteMetric')), + predicateResult('shared-shell-implements-step-grid', SOURCE_ROOTS.productRouteShell, sources.productRouteShell.includes('ProductRouteStepGrid') && sources.productRouteShell.includes('aria-current')), + predicateResult( + 'shared-shell-implements-state-panel', + SOURCE_ROOTS.productRouteShell, + sources.productRouteShell.includes('ProductRouteStatePanel') && + sources.productRouteShell.includes('variant:') && + sources.productRouteShell.includes('"loading" | "empty" | "error"'), + ), + predicateResult('shared-shell-implements-disclosure', SOURCE_ROOTS.productRouteShell, sources.productRouteShell.includes('ProductRouteDisclosure') && sources.productRouteShell.includes(' !predicate.passed) + .map((predicate) => predicate.id); + const sourceRoots = Object.fromEntries( + Object.entries(SOURCE_ROOTS).map(([key, sourcePath]) => [key, `${sourcePath}:${digest(readSource(repoRoot, sourcePath))}`]), + ); + const artifactRoot = `v43-route-ux-product-excellence:${digest(JSON.stringify({ + objectIds: V43_ROUTE_UX_OBJECT_IDS, + fieldIds: V43_ROUTE_UX_FIELD_IDS, + forbiddenPayloadIds: V43_ROUTE_UX_FORBIDDEN_PAYLOAD_IDS, + contractRows: V43_ROUTE_UX_CONTRACT_ROWS.map((row) => row.rowId), + sourceRoots, + failedPredicateIds, + }))}`; + + return { + artifactId: 'v43-route-ux-product-excellence', + schemaId: V43_ROUTE_UX_PRODUCT_EXCELLENCE_SCHEMA_ID, + version: V43_ROUTE_UX_PRODUCT_EXCELLENCE_VERSION, + currentTarget: V43_ROUTE_UX_PRODUCT_EXCELLENCE_CURRENT_TARGET, + sourceSafetyVerdict: V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_SAFETY_VERDICT, + generatedAt: 'deterministic', + artifactRoot, + passed: failedPredicateIds.length === 0, + objectIds: [...V43_ROUTE_UX_OBJECT_IDS], + fieldIds: [...V43_ROUTE_UX_FIELD_IDS], + forbiddenPayloadIds: [...V43_ROUTE_UX_FORBIDDEN_PAYLOAD_IDS], + contractRows: V43_ROUTE_UX_CONTRACT_ROWS.map((row) => ({ + ...row, + rowRoot: `v43-route-ux-contract:${digest(row.rowId)}`, + sourceSafeMetadataOnly: true, + protectedSourceVisible: false, + unpaidAssetPackSourceVisible: false, + })), + sourceRoots, + predicateResults, + coverage: { + sharedRouteShellImplemented: true, + sharedStepGridImplemented: true, + keyboardCurrentStepImplemented: true, + routeMetricsImplemented: true, + productRouteStatePanelsImplemented: true, + loadingEmptyErrorStatesImplemented: true, + progressiveDisclosureImplemented: true, + packsRouteUsesSharedShell: true, + readRouteUsesSharedShell: true, + depositRouteUsesSharedShell: true, + selfReferentialProductCopyReduced: true, + executionStreamReadbackRetained: true, + responsiveGridPostureImplemented: true, + sourceSafeMetadataOnly: true, + protectedSourceVisible: false, + rawSourceTextVisible: false, + unpaidAssetPackSourceVisible: false, + rawPromptVisible: false, + interpolatedPromptVisible: false, + rawProviderResponseVisible: false, + walletPrivateMaterialVisible: false, + settlementPrivatePayloadVisible: false, + requiredPredicateCount: predicateResults.length, + passedPredicateCount: predicateResults.length - failedPredicateIds.length, + failedPredicateIds, + }, + }; +} + +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_ROOTS = Object.freeze( + Object.fromEntries(Object.entries(SOURCE_ROOTS).map(([key, sourcePath]) => [key, sourcePath])), +); diff --git a/packages/protocol/src/index.d.ts b/packages/protocol/src/index.d.ts index 032ae1f5..9b1a3814 100644 --- a/packages/protocol/src/index.d.ts +++ b/packages/protocol/src/index.d.ts @@ -652,6 +652,17 @@ export const V43_DEPOSIT_OPTION_ADMISSION_FIELD_IDS: readonly string[]; export const V43_DEPOSIT_OPTION_ADMISSION_FORBIDDEN_PAYLOAD_IDS: readonly string[]; export const V43_DEPOSIT_OPTION_ADMISSION_CONTRACT_ROWS: readonly Record[]; export function buildV43DepositOptionAdmission(input?: Record): BitcodeProtocolReport; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH: string; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_CURRENT_TARGET: string; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_SCHEMA_ID: string; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_VERSION: string; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_SAFETY_VERDICT: string; +export const V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_ROOTS: Readonly>; +export const V43_ROUTE_UX_OBJECT_IDS: readonly string[]; +export const V43_ROUTE_UX_FIELD_IDS: readonly string[]; +export const V43_ROUTE_UX_FORBIDDEN_PAYLOAD_IDS: readonly string[]; +export const V43_ROUTE_UX_CONTRACT_ROWS: readonly Record[]; +export function buildV43RouteUxProductExcellence(input?: Record): BitcodeProtocolReport; export const EXCHANGE_INTENT_ORDER_CONTRACTS_ARTIFACT_PATH: string; export const EXCHANGE_INTENT_ORDER_CONTRACTS_CURRENT_TARGET: string; export const EXCHANGE_INTENT_ORDER_CONTRACTS_SCHEMA_ID: string; diff --git a/packages/protocol/src/index.js b/packages/protocol/src/index.js index e88288d6..ba96233f 100644 --- a/packages/protocol/src/index.js +++ b/packages/protocol/src/index.js @@ -738,6 +738,19 @@ export { V43_DEPOSIT_OPTION_ADMISSION_VERSION, buildV43DepositOptionAdmission } from './canonical/v43-deposit-option-admission.js'; +export { + V43_ROUTE_UX_CONTRACT_ROWS, + V43_ROUTE_UX_FIELD_IDS, + V43_ROUTE_UX_FORBIDDEN_PAYLOAD_IDS, + V43_ROUTE_UX_OBJECT_IDS, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_CURRENT_TARGET, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_SCHEMA_ID, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_ROOTS, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_SAFETY_VERDICT, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_VERSION, + buildV43RouteUxProductExcellence +} from './canonical/v43-route-ux-product-excellence.js'; export { EXCHANGE_INTENT_ACTION_KINDS, EXCHANGE_INTENT_ORDER_CONTRACTS_ARTIFACT_PATH, diff --git a/packages/protocol/test/v43-route-ux-product-excellence.test.js b/packages/protocol/test/v43-route-ux-product-excellence.test.js new file mode 100644 index 00000000..f554f5a1 --- /dev/null +++ b/packages/protocol/test/v43-route-ux-product-excellence.test.js @@ -0,0 +1,44 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { + V43_ROUTE_UX_FIELD_IDS, + V43_ROUTE_UX_FORBIDDEN_PAYLOAD_IDS, + V43_ROUTE_UX_OBJECT_IDS, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_SCHEMA_ID, + V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_SAFETY_VERDICT, + buildV43RouteUxProductExcellence, +} from '../src/canonical/v43-route-ux-product-excellence.js'; + +test('V43 route UX product excellence artifact binds shared route polish contracts', () => { + const report = buildV43RouteUxProductExcellence(); + + assert.equal(V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH, '.bitcode/v43-route-ux-product-excellence.json'); + assert.equal(report.artifactId, 'v43-route-ux-product-excellence'); + assert.equal(report.schemaId, V43_ROUTE_UX_PRODUCT_EXCELLENCE_SCHEMA_ID); + assert.equal(report.version, 'V43'); + assert.equal(report.currentTarget, 'V42'); + assert.equal(report.sourceSafetyVerdict, V43_ROUTE_UX_PRODUCT_EXCELLENCE_SOURCE_SAFETY_VERDICT); + assert.ok(report.artifactRoot.startsWith('v43-route-ux-product-excellence:')); + assert.deepEqual(report.objectIds, [...V43_ROUTE_UX_OBJECT_IDS]); + assert.deepEqual(report.fieldIds, [...V43_ROUTE_UX_FIELD_IDS]); + assert.deepEqual(report.forbiddenPayloadIds, [...V43_ROUTE_UX_FORBIDDEN_PAYLOAD_IDS]); + assert.equal(report.contractRows.length, 5); + assert.equal(report.coverage.sharedRouteShellImplemented, true); + assert.equal(report.coverage.sharedStepGridImplemented, true); + assert.equal(report.coverage.keyboardCurrentStepImplemented, true); + assert.equal(report.coverage.productRouteStatePanelsImplemented, true); + assert.equal(report.coverage.loadingEmptyErrorStatesImplemented, true); + assert.equal(report.coverage.progressiveDisclosureImplemented, true); + assert.equal(report.coverage.packsRouteUsesSharedShell, true); + assert.equal(report.coverage.readRouteUsesSharedShell, true); + assert.equal(report.coverage.depositRouteUsesSharedShell, true); + assert.equal(report.coverage.selfReferentialProductCopyReduced, true); + assert.equal(report.coverage.sourceSafeMetadataOnly, true); + assert.equal(report.coverage.protectedSourceVisible, false); + assert.equal(report.coverage.rawSourceTextVisible, false); + assert.equal(report.coverage.unpaidAssetPackSourceVisible, false); + assert.equal(report.coverage.rawProviderResponseVisible, false); + assert.equal(report.coverage.walletPrivateMaterialVisible, false); + assert.equal(report.coverage.settlementPrivatePayloadVisible, false); +}); diff --git a/scripts/check-v43-gate8-route-ux-product-excellence.mjs b/scripts/check-v43-gate8-route-ux-product-excellence.mjs new file mode 100644 index 00000000..39c3bea2 --- /dev/null +++ b/scripts/check-v43-gate8-route-ux-product-excellence.mjs @@ -0,0 +1,171 @@ +#!/usr/bin/env node + +import { execFileSync } from 'node:child_process'; +import { existsSync, readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { + V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH, + buildV43RouteUxProductExcellence, +} from '../packages/protocol/src/canonical/v43-route-ux-product-excellence.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const defaultRepoRoot = path.resolve(__dirname, '..'); + +function read(root, relativePath) { + return readFileSync(path.join(root, relativePath), 'utf8'); +} + +function exists(root, relativePath) { + return existsSync(path.join(root, relativePath)); +} + +function git(root, args) { + return execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim(); +} + +function assertCheck(failures, condition, message) { + if (!condition) failures.push(message); +} + +function parseArgs(argv) { + const args = { repoRoot: defaultRepoRoot, skipBranchCheck: false, skipUapiTests: false }; + for (let index = 0; index < argv.length; index += 1) { + const arg = argv[index]; + if (arg === '--repo-root') args.repoRoot = path.resolve(argv[++index]); + else if (arg === '--skip-branch-check') args.skipBranchCheck = true; + else if (arg === '--skip-uapi-tests') args.skipUapiTests = true; + else if (arg === '--help' || arg === '-h') args.help = true; + else throw new Error(`Unknown argument ${arg}`); + } + return args; +} + +function printHelp() { + process.stdout.write( + [ + 'Usage: node scripts/check-v43-gate8-route-ux-product-excellence.mjs [--skip-branch-check] [--skip-uapi-tests] [--repo-root ]', + '', + 'Checks V43 Gate 8 shared route shell, product route copy, progressive disclosure, loading/empty/error states, route tests, generated artifact, docs, and workflow wiring.', + ].join('\n'), + ); + process.stdout.write('\n'); +} + +function run(root, command, args) { + execFileSync(command, args, { cwd: root, stdio: 'pipe', encoding: 'utf8' }); +} + +function main() { + const args = parseArgs(process.argv.slice(2)); + if (args.help) { + printHelp(); + return; + } + + const root = args.repoRoot; + const failures = []; + const pointer = read(root, 'BITCODE_SPEC.txt').trim(); + + assertCheck(failures, pointer === 'V42', `BITCODE_SPEC.txt must remain V42 during V43 gate work. Observed ${pointer || 'empty'}.`); + + if (!args.skipBranchCheck) { + const branch = git(root, ['branch', '--show-current']); + assertCheck( + failures, + branch === 'version/v43' || /^v43\/gate-\d+-[a-z0-9][a-z0-9-]*$/u.test(branch), + `V43 work must occur on version/v43 or v43/gate-N-* branches. Observed ${branch || 'detached HEAD'}.`, + ); + } + + for (const relativePath of [ + V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH, + 'uapi/components/base/bitcode/routes/product-route-shell.tsx', + 'uapi/app/packs/PacksPageClient.tsx', + 'uapi/app/read/ReadPageClient.tsx', + 'uapi/app/deposit/DepositPageClient.tsx', + 'uapi/tests/packsPageClient.test.tsx', + 'uapi/tests/readPageClient.test.tsx', + 'uapi/tests/depositPageClient.test.tsx', + 'packages/protocol/src/canonical/v43-route-ux-product-excellence.js', + 'packages/protocol/test/v43-route-ux-product-excellence.test.js', + 'scripts/generate-v43-route-ux-product-excellence.mjs', + 'scripts/check-v43-gate8-route-ux-product-excellence.mjs', + 'BITCODE_SPEC_V43.md', + 'BITCODE_SPEC_V43_DELTA.md', + 'BITCODE_SPEC_V43_NOTES.md', + 'BITCODE_SPEC_V43_PARITY_MATRIX.md', + 'SPECIFICATIONS_ROADMAP.md', + 'README.md', + 'packages/protocol/README.md', + '.github/workflows/bitcode-gate-quality.yml', + '.github/workflows/bitcode-canon-quality.yml', + 'package.json', + ]) { + assertCheck(failures, exists(root, relativePath), `Missing required V43 Gate 8 file: ${relativePath}`); + } + + const artifact = buildV43RouteUxProductExcellence({ repoRoot: root }); + assertCheck(failures, artifact.passed, `V43 route UX product excellence predicates failed: ${artifact.coverage.failedPredicateIds.join(', ')}`); + assertCheck(failures, artifact.coverage.sharedRouteShellImplemented === true, 'Shared route shell must be implemented.'); + assertCheck(failures, artifact.coverage.sharedStepGridImplemented === true, 'Shared route step grid must be implemented.'); + assertCheck(failures, artifact.coverage.keyboardCurrentStepImplemented === true, 'Keyboard current-step semantics must be implemented.'); + assertCheck(failures, artifact.coverage.productRouteStatePanelsImplemented === true, 'Product route state panels must be implemented.'); + assertCheck(failures, artifact.coverage.loadingEmptyErrorStatesImplemented === true, 'Loading, empty, and error states must be implemented.'); + assertCheck(failures, artifact.coverage.progressiveDisclosureImplemented === true, 'Progressive disclosure must be implemented.'); + assertCheck(failures, artifact.coverage.packsRouteUsesSharedShell === true, '/packs must use shared route shell.'); + assertCheck(failures, artifact.coverage.readRouteUsesSharedShell === true, '/read must use shared route shell.'); + assertCheck(failures, artifact.coverage.depositRouteUsesSharedShell === true, '/deposit must use shared route shell.'); + assertCheck(failures, artifact.coverage.selfReferentialProductCopyReduced === true, 'Product copy must be reduced to route/status vocabulary.'); + assertCheck(failures, artifact.coverage.executionStreamReadbackRetained === true, 'Execution stream readback posture must remain retained.'); + assertCheck(failures, artifact.coverage.sourceSafeMetadataOnly === true, 'Artifact must be source-safe metadata only.'); + assertCheck(failures, artifact.coverage.protectedSourceVisible === false, 'Artifact must not expose protected source.'); + assertCheck(failures, artifact.coverage.rawSourceTextVisible === false, 'Artifact must not expose raw source text.'); + assertCheck(failures, artifact.coverage.unpaidAssetPackSourceVisible === false, 'Artifact must not expose unpaid AssetPack source.'); + assertCheck(failures, artifact.coverage.rawProviderResponseVisible === false, 'Artifact must not expose raw provider responses.'); + assertCheck(failures, artifact.coverage.walletPrivateMaterialVisible === false, 'Artifact must not expose wallet private material.'); + assertCheck(failures, artifact.coverage.settlementPrivatePayloadVisible === false, 'Artifact must not expose settlement private payload.'); + + const serialized = `${JSON.stringify(artifact, null, 2)}\n`; + assertCheck( + failures, + exists(root, V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH) && + read(root, V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH) === serialized, + `${V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH} must be generated and current.`, + ); + + const packageJson = read(root, 'package.json'); + const gateWorkflow = read(root, '.github/workflows/bitcode-gate-quality.yml'); + const canonWorkflow = read(root, '.github/workflows/bitcode-canon-quality.yml'); + assertCheck(failures, packageJson.includes('"generate:v43-route-ux-product-excellence"'), 'package.json must expose generate:v43-route-ux-product-excellence.'); + assertCheck(failures, packageJson.includes('"check:v43-route-ux-product-excellence"'), 'package.json must expose check:v43-route-ux-product-excellence.'); + assertCheck(failures, packageJson.includes('"check:v43-gate8"'), 'package.json must expose check:v43-gate8.'); + assertCheck(failures, gateWorkflow.includes('check-v43-gate8-route-ux-product-excellence.mjs'), 'Gate workflow must run V43 Gate 8 checker.'); + assertCheck(failures, canonWorkflow.includes('check-v43-gate8-route-ux-product-excellence.mjs'), 'Canon workflow must run V43 Gate 8 checker.'); + + if (!args.skipUapiTests) { + try { + run(root, 'pnpm', ['--dir', 'uapi', 'exec', 'jest', '--runTestsByPath', 'tests/packsPageClient.test.tsx', 'tests/readPageClient.test.tsx', 'tests/depositPageClient.test.tsx', '--runInBand']); + } catch { + failures.push('uapi packsPageClient.test.tsx, readPageClient.test.tsx, and depositPageClient.test.tsx must pass.'); + } + } + + if (failures.length > 0) { + process.stderr.write('V43 Gate 8 route UX product excellence check failed:\n'); + for (const failure of failures.filter(Boolean)) process.stderr.write(`- ${failure}\n`); + process.exitCode = 1; + return; + } + + process.stdout.write('V43 Gate 8 route UX product excellence check passed.\n'); +} + +try { + main(); +} catch (error) { + const detail = error instanceof Error ? error.message : String(error); + process.stderr.write(`${detail}\n`); + process.exitCode = 1; +} diff --git a/scripts/generate-v43-route-ux-product-excellence.mjs b/scripts/generate-v43-route-ux-product-excellence.mjs new file mode 100644 index 00000000..d8c0ce1a --- /dev/null +++ b/scripts/generate-v43-route-ux-product-excellence.mjs @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { + V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH, + buildV43RouteUxProductExcellence, +} from '../packages/protocol/src/canonical/v43-route-ux-product-excellence.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '..'); +const check = process.argv.includes('--check'); +const artifact = buildV43RouteUxProductExcellence({ repoRoot }); +const serialized = `${JSON.stringify(artifact, null, 2)}\n`; +const artifactPath = path.join(repoRoot, V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH); + +if (check) { + if (!existsSync(artifactPath) || readFileSync(artifactPath, 'utf8') !== serialized) { + process.stderr.write( + `${V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH} is stale. Run pnpm run generate:v43-route-ux-product-excellence.\n`, + ); + process.exitCode = 1; + } +} else { + mkdirSync(path.dirname(artifactPath), { recursive: true }); + writeFileSync(artifactPath, serialized); + process.stdout.write(`wrote ${V43_ROUTE_UX_PRODUCT_EXCELLENCE_ARTIFACT_PATH}\n`); +} diff --git a/uapi/app/deposit/DepositPageClient.tsx b/uapi/app/deposit/DepositPageClient.tsx index 945697ad..3e75b83a 100644 --- a/uapi/app/deposit/DepositPageClient.tsx +++ b/uapi/app/deposit/DepositPageClient.tsx @@ -1,69 +1,89 @@ -'use client'; +"use client"; -import Link from 'next/link'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { Boxes, GitBranch, GitCommitHorizontal, RefreshCw, ShieldCheck, Sparkles } from 'lucide-react'; -import { useRouter, useSearchParams } from 'next/navigation'; +import Link from "next/link"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; +import { + Boxes, + GitBranch, + GitCommitHorizontal, + RefreshCw, + ShieldCheck, + Sparkles, +} from "lucide-react"; +import { useRouter, useSearchParams } from "next/navigation"; -import { useAuth } from '@/components/base/bitcode/auth/AuthProvider'; -import { useUserData } from '@/hooks/useUserData'; -import { fetchPipelineExecutionHistory } from '@/networking/api-client'; -import type { PipelineExecution } from '@/types/api'; +import { useAuth } from "@/components/base/bitcode/auth/AuthProvider"; +import { + ProductRouteDisclosure, + ProductRouteShell, + ProductRouteStatePanel, + ProductRouteStepGrid, +} from "@/components/base/bitcode/routes/product-route-shell"; +import { useUserData } from "@/hooks/useUserData"; +import { fetchPipelineExecutionHistory } from "@/networking/api-client"; +import type { PipelineExecution } from "@/types/api"; -import TerminalDepositComposer from '@/app/terminal/TerminalDepositComposer'; -import TerminalRepositoryContextPanel from '@/app/terminal/TerminalRepositoryContextPanel'; -import TerminalSupplySelectionPanel from '@/app/terminal/TerminalSupplySelectionPanel'; +import TerminalDepositComposer from "@/app/terminal/TerminalDepositComposer"; +import TerminalRepositoryContextPanel from "@/app/terminal/TerminalRepositoryContextPanel"; +import TerminalSupplySelectionPanel from "@/app/terminal/TerminalSupplySelectionPanel"; import { buildTerminalExecutionHistoryRequest, mapExecutionHistoryRunToWorkspaceRun, readTerminalRouteError, type TerminalActivityRecordDraft, upsertWorkspaceRun, -} from '@/app/terminal/terminal-activity-history'; -import type { TerminalRepositoryContextState } from '@/app/terminal/terminal-repository-context'; +} from "@/app/terminal/terminal-activity-history"; +import type { TerminalRepositoryContextState } from "@/app/terminal/terminal-repository-context"; import { readTerminalTransactionId, writeTerminalTransactionId, -} from '@/app/terminal/terminal-transaction-query'; -import { shouldRecoverTerminalTransactionRoute } from '@/app/terminal/terminal-transaction-query'; -import type { WorkspaceRun } from '@/app/terminal/terminal-run-data'; -import { buildDepositHref, DEPOSIT_ROUTE } from '@/app/terminal/terminal-routes'; -import { TerminalShellBridgeProvider } from '@/app/terminal/terminal-shell-bridge'; -import { deriveTerminalTransactionReadiness } from '@/app/terminal/terminal-transaction-readiness-source'; - -import { buildDepositRouteSession, readDepositRouteStage, writeDepositRouteStage } from './deposit-route-model'; +} from "@/app/terminal/terminal-transaction-query"; +import { shouldRecoverTerminalTransactionRoute } from "@/app/terminal/terminal-transaction-query"; +import type { WorkspaceRun } from "@/app/terminal/terminal-run-data"; +import { + buildDepositHref, + DEPOSIT_ROUTE, +} from "@/app/terminal/terminal-routes"; +import { TerminalShellBridgeProvider } from "@/app/terminal/terminal-shell-bridge"; +import { deriveTerminalTransactionReadiness } from "@/app/terminal/terminal-transaction-readiness-source"; + +import { + buildDepositRouteSession, + readDepositRouteStage, + writeDepositRouteStage, +} from "./deposit-route-model"; import type { DepositOptionReviewDecision, DepositOptionReviewDecisionState, -} from '@bitcode/pipeline-asset-pack/deposit-asset-pack-option-admission'; +} from "@bitcode/pipeline-asset-pack/deposit-asset-pack-option-admission"; -const DEPOSIT_OPTION_PIPELINE_ID = 'DepositAssetPackOptionSynthesis'; -const DEPOSIT_OPTION_POLICY_ID = 'DepositAssetPackOptionPolicy'; -const DEPOSIT_OPTION_ADMISSION_ID = 'DepositAssetPackOptionAdmissionReport'; +const DEPOSIT_OPTION_PIPELINE_ID = "DepositAssetPackOptionSynthesis"; +const DEPOSIT_OPTION_POLICY_ID = "DepositAssetPackOptionPolicy"; +const DEPOSIT_OPTION_ADMISSION_ID = "DepositAssetPackOptionAdmissionReport"; function shortIdentifier(value: string | null | undefined) { - if (!value) return 'pending'; + if (!value) return "pending"; return value.length > 18 ? `${value.slice(0, 12)}...` : value; } function formatDate(value: string | null | undefined) { - if (!value) return 'pending'; + if (!value) return "pending"; const date = new Date(value); if (Number.isNaN(date.getTime())) return value; return date.toLocaleString(undefined, { - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit', + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", }); } function readStringField(source: unknown, ...keys: string[]) { - if (!source || typeof source !== 'object') return null; + if (!source || typeof source !== "object") return null; const record = source as Record; for (const key of keys) { const value = record[key]; - if (typeof value === 'string' && value.trim()) return value.trim(); + if (typeof value === "string" && value.trim()) return value.trim(); } return null; } @@ -81,28 +101,41 @@ export default function DepositPageClient() { hasStoredVerifiedWalletConnection, walletConnectionStatus, } = useUserData(); - const routeSearchParams = useMemo(() => new URLSearchParams(searchParams.toString()), [searchParams]); - const selectedTransactionId = useMemo(() => readTerminalTransactionId(routeSearchParams), [routeSearchParams]); - const routeDepositStage = useMemo(() => readDepositRouteStage(routeSearchParams), [routeSearchParams]); + const routeSearchParams = useMemo( + () => new URLSearchParams(searchParams.toString()), + [searchParams], + ); + const selectedTransactionId = useMemo( + () => readTerminalTransactionId(routeSearchParams), + [routeSearchParams], + ); + const routeDepositStage = useMemo( + () => readDepositRouteStage(routeSearchParams), + [routeSearchParams], + ); const [liveRuns, setLiveRuns] = useState([]); const [isLoadingRuns, setIsLoadingRuns] = useState(true); const [runsLoadError, setRunsLoadError] = useState(null); - const [repositoryContext, setRepositoryContext] = useState(null); + const [repositoryContext, setRepositoryContext] = + useState(null); const [depositorInstructions, setDepositorInstructions] = useState( - 'Propose source-safe AssetPack options that are sub-critical to expose after settlement and likely useful for future Reading demand.', + "Propose source-safe AssetPack options that are sub-critical to expose after settlement and likely useful for future Reading demand.", ); const [sourcePathHintsText, setSourcePathHintsText] = useState( [ - 'uapi/app/terminal/TerminalDepositComposer.tsx', - 'packages/pipelines/asset-pack/src/depository-supply-index.ts', - ].join('\n'), + "uapi/app/terminal/TerminalDepositComposer.tsx", + "packages/pipelines/asset-pack/src/depository-supply-index.ts", + ].join("\n"), ); const [optionsRequested, setOptionsRequested] = useState(false); - const [optionReviewDecisions, setOptionReviewDecisions] = useState>({}); + const [optionReviewDecisions, setOptionReviewDecisions] = useState< + Record + >({}); const readCurrentSearchParams = useCallback( () => - typeof window !== 'undefined' && window.location.pathname === DEPOSIT_ROUTE + typeof window !== "undefined" && + window.location.pathname === DEPOSIT_ROUTE ? new URLSearchParams(window.location.search) : new URLSearchParams(searchParams.toString()), [searchParams], @@ -118,7 +151,9 @@ export default function DepositPageClient() { const replaceDepositRouteTransaction = useCallback( (transactionId: string) => { - replaceDepositSearchParams(writeTerminalTransactionId(readCurrentSearchParams(), transactionId)); + replaceDepositSearchParams( + writeTerminalTransactionId(readCurrentSearchParams(), transactionId), + ); }, [readCurrentSearchParams, replaceDepositSearchParams], ); @@ -134,7 +169,11 @@ export default function DepositPageClient() { return nextRuns; } catch (error) { setLiveRuns([]); - setRunsLoadError(error instanceof Error ? error.message : 'Unable to load recent Deposit activity.'); + setRunsLoadError( + error instanceof Error + ? error.message + : "Unable to load recent Deposit activity.", + ); return []; } finally { setIsLoadingRuns(false); @@ -158,28 +197,42 @@ export default function DepositPageClient() { }, [liveRuns, replaceDepositRouteTransaction, selectedTransactionId]); const selectedRun = useMemo( - () => liveRuns.find((run) => run.id === selectedTransactionId) || liveRuns[0] || null, + () => + liveRuns.find((run) => run.id === selectedTransactionId) || + liveRuns[0] || + null, [liveRuns, selectedTransactionId], ); const profileRecord = - userData?.profile && typeof userData.profile === 'object' + userData?.profile && typeof userData.profile === "object" ? (userData.profile as Record) : null; const walletBinding = - profileRecord?.wallet_binding && typeof profileRecord.wallet_binding === 'object' + profileRecord?.wallet_binding && + typeof profileRecord.wallet_binding === "object" ? (profileRecord.wallet_binding as Record) : null; const preferredSignerAddress = useMemo(() => { - const profileAuthAddress = readStringField(profileRecord, 'auth_address'); - const profileWalletAddress = readStringField(profileRecord, 'wallet_address'); - const walletAuthAddress = walletConnectionStatus?.metadata?.authAddress?.trim() || ''; - const walletAddress = walletConnectionStatus?.address?.trim() || ''; - return walletAuthAddress || walletAddress || profileAuthAddress || profileWalletAddress || null; + const profileAuthAddress = readStringField(profileRecord, "auth_address"); + const profileWalletAddress = readStringField( + profileRecord, + "wallet_address", + ); + const walletAuthAddress = + walletConnectionStatus?.metadata?.authAddress?.trim() || ""; + const walletAddress = walletConnectionStatus?.address?.trim() || ""; + return ( + walletAuthAddress || + walletAddress || + profileAuthAddress || + profileWalletAddress || + null + ); }, [profileRecord, walletConnectionStatus]); const preferredSignerLabel = walletConnectionStatus?.provider ? `${walletConnectionStatus.provider} wallet` - : 'connected wallet'; + : "connected wallet"; const transactionReadiness = useMemo( () => deriveTerminalTransactionReadiness({ @@ -190,7 +243,10 @@ export default function DepositPageClient() { hasValidRepositoryProviderAttachment: hasValidGitHubConnection, hasWalletBinding: hasWalletConnection || - Boolean(readStringField(profileRecord, 'wallet_address') || readStringField(walletBinding, 'address')), + Boolean( + readStringField(profileRecord, "wallet_address") || + readStringField(walletBinding, "address"), + ), hasVerifiedWalletBinding: hasVerifiedWalletConnection, hasStoredVerifiedWalletBinding: hasStoredVerifiedWalletConnection, }).readiness, @@ -208,23 +264,31 @@ export default function DepositPageClient() { ); const sourcePathHints = useMemo( - () => sourcePathHintsText.split(/\r?\n|,/u).map((entry) => entry.trim()).filter(Boolean), + () => + sourcePathHintsText + .split(/\r?\n|,/u) + .map((entry) => entry.trim()) + .filter(Boolean), [sourcePathHintsText], ); const sourceCriticalitySignals = useMemo( () => [ { - id: 'depositor-sub-critical-intent', - label: 'Depositor intends this option set to avoid critical source exposure.', - severity: 'sub-critical' as const, + id: "depositor-sub-critical-intent", + label: + "Depositor intends this option set to avoid critical source exposure.", + severity: "sub-critical" as const, weight: 0.74, }, - ...(sourcePathHints.some((path) => /secret|credential|wallet|auth|key|payment|settlement/iu.test(path)) + ...(sourcePathHints.some((path) => + /secret|credential|wallet|auth|key|payment|settlement/iu.test(path), + ) ? [ { - id: 'source-path-sensitive-scope-warning', - label: 'Source path hints include sensitive operational terms requiring review.', - severity: 'warning' as const, + id: "source-path-sensitive-scope-warning", + label: + "Source path hints include sensitive operational terms requiring review.", + severity: "warning" as const, weight: 0.64, }, ] @@ -235,10 +299,13 @@ export default function DepositPageClient() { const hasSubmittedDeposit = useMemo(() => { const selectedRepository = repositoryContext?.selectedRepository || null; if (!selectedRepository) return false; - const selectedBranch = repositoryContext?.selectedBranch || selectedRepository.defaultBranch || 'main'; + const selectedBranch = + repositoryContext?.selectedBranch || + selectedRepository.defaultBranch || + "main"; return liveRuns.some( (run) => - run.contextSource === 'terminal-deposit-composer' && + run.contextSource === "terminal-deposit-composer" && run.repository === selectedRepository.fullName && run.branch === selectedBranch && Boolean(run.candidateAssetId), @@ -248,8 +315,12 @@ export default function DepositPageClient() { () => liveRuns.some( (run) => - run.contextSource === 'terminal-deposit-composer' && - Boolean(run.depositorySearchDocumentRoot || run.vectorDocumentRoot || run.compensationPreviewRoot), + run.contextSource === "terminal-deposit-composer" && + Boolean( + run.depositorySearchDocumentRoot || + run.vectorDocumentRoot || + run.compensationPreviewRoot, + ), ), [liveRuns], ); @@ -266,36 +337,45 @@ export default function DepositPageClient() { () => ({ transactionId: selectedTransactionId || selectedRun?.id || null, depositStage: routeDepositStage, - repositoryFullName: repositoryContext?.selectedRepository?.fullName || null, + repositoryFullName: + repositoryContext?.selectedRepository?.fullName || null, sourceBranch: repositoryContext?.selectedBranch || null, sourceCommit: repositoryContext?.selectedCommit || null, depositorInstructions, sourcePathHints, depositoryDemandSignals: [ { - id: 'depository-gap-source-safe-pack-options', - label: 'Depository benefits from reviewable source-safe AssetPack supply options.', + id: "depository-gap-source-safe-pack-options", + label: + "Depository benefits from reviewable source-safe AssetPack supply options.", weight: 0.72, }, ], readingDemandSignals: [ { - id: 'reading-demand-fit-ready-source-supply', - label: 'Reading demand needs searchable, proof-bearing source supply for Finding Fits.', + id: "reading-demand-fit-ready-source-supply", + label: + "Reading demand needs searchable, proof-bearing source supply for Finding Fits.", weight: 0.8, }, ], existingDepositorySignals: [ { - id: 'existing-supply-compensation-route', - label: 'Existing supply expects proof roots, vector projections, and compensation previews.', + id: "existing-supply-compensation-route", + label: + "Existing supply expects proof roots, vector projections, and compensation previews.", weight: 0.58, }, ], sourceCriticalitySignals, developmentCostSats: Math.max(1600, 1200 + sourcePathHints.length * 240), - expectedSettlementSats: Math.max(4200, 3600 + sourcePathHints.length * 360 + liveRuns.length * 90), - depositorWalletId: preferredSignerAddress ? 'connected-depositor-wallet' : null, + expectedSettlementSats: Math.max( + 4200, + 3600 + sourcePathHints.length * 360 + liveRuns.length * 90, + ), + depositorWalletId: preferredSignerAddress + ? "connected-depositor-wallet" + : null, reviewerId: user?.id || preferredSignerAddress || null, hasRepositorySource: Boolean(repositoryContext?.selectedRepository), optionsRequested, @@ -330,32 +410,59 @@ export default function DepositPageClient() { ); const sessionRows = [ - { label: 'Repository', value: depositRouteSession.routeState.repositoryFullName || 'select repository' }, - { label: 'Branch', value: depositRouteSession.routeState.sourceBranch || 'pending' }, - { label: 'Commit', value: shortIdentifier(depositRouteSession.routeState.sourceCommit) }, - { label: 'Transaction', value: shortIdentifier(depositRouteSession.routeState.transactionId) }, - { label: 'Pipeline', value: DEPOSIT_OPTION_PIPELINE_ID }, - { label: 'Policy', value: DEPOSIT_OPTION_POLICY_ID }, - { label: 'Admission', value: DEPOSIT_OPTION_ADMISSION_ID }, - { label: 'Option roots', value: String(depositRouteSession.synthesis.roots.optionRoots.length) }, - { label: 'Positive ROI options', value: String(depositRouteSession.policy.reviewablePositiveRoiCount) }, - { label: 'Admitted options', value: String(depositRouteSession.admission.admittedCount) }, + { + label: "Repository", + value: + depositRouteSession.routeState.repositoryFullName || + "select repository", + }, + { + label: "Branch", + value: depositRouteSession.routeState.sourceBranch || "pending", + }, + { + label: "Commit", + value: shortIdentifier(depositRouteSession.routeState.sourceCommit), + }, + { + label: "Transaction", + value: shortIdentifier(depositRouteSession.routeState.transactionId), + }, + { label: "Pipeline", value: DEPOSIT_OPTION_PIPELINE_ID }, + { label: "Policy", value: DEPOSIT_OPTION_POLICY_ID }, + { label: "Admission", value: DEPOSIT_OPTION_ADMISSION_ID }, + { + label: "Option roots", + value: String(depositRouteSession.synthesis.roots.optionRoots.length), + }, + { + label: "Positive ROI options", + value: String(depositRouteSession.policy.reviewablePositiveRoiCount), + }, + { + label: "Admitted options", + value: String(depositRouteSession.admission.admittedCount), + }, ]; const recentDepositRuns = useMemo( () => liveRuns - .filter((run) => run.contextSource === 'terminal-deposit-composer' || run.transactionLens === 'deposit') + .filter( + (run) => + run.contextSource === "terminal-deposit-composer" || + run.transactionLens === "deposit", + ) .slice(0, 6), [liveRuns], ); const handleRecordActivity = useCallback( async (draft: TerminalActivityRecordDraft) => { - const response = await fetch('/api/executions/history', { - method: 'POST', + const response = await fetch("/api/executions/history", { + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify( buildTerminalExecutionHistoryRequest(draft, { @@ -366,19 +473,35 @@ export default function DepositPageClient() { }); if (!response.ok) { - throw new Error(await readTerminalRouteError(response, 'Unable to record Deposit activity.')); + throw new Error( + await readTerminalRouteError( + response, + "Unable to record Deposit activity.", + ), + ); } - const payload = (await response.json()) as { execution?: PipelineExecution }; - if (!payload.execution) throw new Error('Deposit activity response did not include an execution row.'); + const payload = (await response.json()) as { + execution?: PipelineExecution; + }; + if (!payload.execution) + throw new Error( + "Deposit activity response did not include an execution row.", + ); const nextRun = mapExecutionHistoryRunToWorkspaceRun(payload.execution); setLiveRuns((currentRuns) => upsertWorkspaceRun(currentRuns, nextRun)); - if (draft.selectAfterRecord !== false) replaceDepositRouteTransaction(nextRun.id); + if (draft.selectAfterRecord !== false) + replaceDepositRouteTransaction(nextRun.id); void refreshLiveRuns(); return nextRun; }, - [refreshLiveRuns, replaceDepositRouteTransaction, repositoryContext, selectedRun], + [ + refreshLiveRuns, + replaceDepositRouteTransaction, + repositoryContext, + selectedRun, + ], ); const handleOptionReviewDecision = useCallback( @@ -390,32 +513,41 @@ export default function DepositPageClient() { setOptionsRequested(true); setOptionReviewDecisions(nextDecisions); - const nextDecisionRecords = Object.entries(nextDecisions).map(([entryOptionId, entryDecision]) => ({ - optionId: entryOptionId, - decision: entryDecision, - reviewerId: user?.id || preferredSignerAddress || null, - })); + const nextDecisionRecords = Object.entries(nextDecisions).map( + ([entryOptionId, entryDecision]) => ({ + optionId: entryOptionId, + decision: entryDecision, + reviewerId: user?.id || preferredSignerAddress || null, + }), + ); const nextSession = buildDepositRouteSession({ ...depositRouteInput, optionsRequested: true, hasReviewedOption: true, optionReviewDecisions: nextDecisionRecords, }); - const receipt = nextSession.admission.receipts.find((entry) => entry.optionId === optionId); - const admitted = receipt?.admission.state === 'admitted-to-depository'; + const receipt = nextSession.admission.receipts.find( + (entry) => entry.optionId === optionId, + ); + const admitted = receipt?.admission.state === "admitted-to-depository"; replaceDepositSearchParams( - writeDepositRouteStage(readCurrentSearchParams(), admitted ? 'read-depository-state' : 'review-options'), + writeDepositRouteStage( + readCurrentSearchParams(), + admitted ? "read-depository-state" : "review-options", + ), ); if (!receipt) return; try { await handleRecordActivity({ - type: admitted ? 'pipeline:deposit-option-admission' : 'pipeline:deposit-option-review', - status: 'completed', + type: admitted + ? "pipeline:deposit-option-admission" + : "pipeline:deposit-option-review", + status: "completed", summary: admitted ? `Admitted ${receipt.title} to the Depository.` - : `Recorded ${decision.replace(/-/g, ' ')} for ${receipt.title}.`, + : `Recorded ${decision.replace(/-/g, " ")} for ${receipt.title}.`, selectAfterRecord: admitted, output: { assetPackTitle: receipt.title, @@ -427,8 +559,8 @@ export default function DepositPageClient() { packsActivityRoot: receipt.packsActivitySync.activityRoot, }, context: { - source: 'deposit-option-review-admission', - workbench: 'deposit-option-review', + source: "deposit-option-review-admission", + workbench: "deposit-option-review", optionId, reviewDecision: decision, admissionState: receipt.admission.state, @@ -440,7 +572,11 @@ export default function DepositPageClient() { }, }); } catch (error) { - setRunsLoadError(error instanceof Error ? error.message : 'Unable to record deposit option review.'); + setRunsLoadError( + error instanceof Error + ? error.message + : "Unable to record deposit option review.", + ); } }, [ @@ -457,12 +593,14 @@ export default function DepositPageClient() { const handleRepositorySourceBranchChange = useCallback( (branch: string) => { const nextParams = readCurrentSearchParams(); - if (repositoryContext?.provider) nextParams.set('provider', repositoryContext.provider); - if (repositoryContext?.selectedRepository?.fullName) nextParams.set('repo', repositoryContext.selectedRepository.fullName); - nextParams.set('sourceBranch', branch); - nextParams.delete('sourceCommit'); - nextParams.delete('branch'); - nextParams.delete('commit'); + if (repositoryContext?.provider) + nextParams.set("provider", repositoryContext.provider); + if (repositoryContext?.selectedRepository?.fullName) + nextParams.set("repo", repositoryContext.selectedRepository.fullName); + nextParams.set("sourceBranch", branch); + nextParams.delete("sourceCommit"); + nextParams.delete("branch"); + nextParams.delete("commit"); replaceDepositSearchParams(nextParams); }, [readCurrentSearchParams, replaceDepositSearchParams, repositoryContext], @@ -471,12 +609,15 @@ export default function DepositPageClient() { const handleRepositorySourceCommitChange = useCallback( (commit: string) => { const nextParams = readCurrentSearchParams(); - if (repositoryContext?.provider) nextParams.set('provider', repositoryContext.provider); - if (repositoryContext?.selectedRepository?.fullName) nextParams.set('repo', repositoryContext.selectedRepository.fullName); - if (repositoryContext?.selectedBranch) nextParams.set('sourceBranch', repositoryContext.selectedBranch); - nextParams.set('sourceCommit', commit); - nextParams.delete('branch'); - nextParams.delete('commit'); + if (repositoryContext?.provider) + nextParams.set("provider", repositoryContext.provider); + if (repositoryContext?.selectedRepository?.fullName) + nextParams.set("repo", repositoryContext.selectedRepository.fullName); + if (repositoryContext?.selectedBranch) + nextParams.set("sourceBranch", repositoryContext.selectedBranch); + nextParams.set("sourceCommit", commit); + nextParams.delete("branch"); + nextParams.delete("commit"); replaceDepositSearchParams(nextParams); }, [readCurrentSearchParams, replaceDepositSearchParams, repositoryContext], @@ -484,369 +625,502 @@ export default function DepositPageClient() { return ( -
-
-
-
-

-

-

- Depositing -

-

- Connect source, synthesize reviewable AssetPack options, inspect source-safe measurements, then submit supply for depository indexing. -

-
-
-
-
Stage
-
{depositRouteSession.activeStepId.replace(/-/g, ' ')}
-
-
-
Options
-
{depositRouteSession.synthesis.optionCount}
-
-
-
Boundary
-
source-safe
-
-
-
- -
- {depositRouteSession.steps.map((step) => { - const active = step.id === depositRouteSession.activeStepId; - return ( - - ); - })} -
- -
-
-
- -
-
-
-

Option synthesis

-

Depositor instruction

-
-
-