@starci/hfs 4.0.8 → 4.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +21 -0
- package/README.md +81 -39
- package/emit/contracts.mjs +56 -9
- package/emit/db-types.mjs +169 -0
- package/emit/events.mjs +41 -0
- package/emit/operations-worker.mjs +1 -1
- package/emit/operations.mjs +2 -2
- package/emit/schema-worker.mjs +1 -1
- package/lint/bound-sys.cjs +50 -0
- package/lint/run.mjs +131 -24
- package/package.json +16 -10
- package/report/sonar.mjs +8 -8
- package/runtime/engine/admission.mjs +308 -0
- package/runtime/engine/canonical-json.mjs +10 -0
- package/runtime/engine/config.mjs +486 -0
- package/runtime/engine/db/blob.mjs +315 -0
- package/runtime/engine/db/ledger-paths.mjs +83 -0
- package/runtime/engine/db/ledger.mjs +1118 -0
- package/runtime/engine/db/machine-connection.mjs +135 -0
- package/runtime/engine/db/machine-schema.mjs +84 -0
- package/runtime/engine/db/machine.mjs +1367 -0
- package/runtime/engine/db/migrations/machine/0001-init.sql +924 -0
- package/runtime/engine/db/migrations/runtime/0001-init.sql +1108 -0
- package/runtime/engine/db/provider-reservations.mjs +101 -0
- package/runtime/engine/digest.mjs +16 -0
- package/runtime/engine/invalid-config.mjs +15 -0
- package/runtime/engine/orca-config.mjs +27 -0
- package/runtime/engine/refuse.mjs +11 -0
- package/runtime/engine/secrets.mjs +130 -0
- package/runtime/knowledge/hfs/canon-pins.yaml +162 -31
- package/runtime/knowledge/hfs/peer-integrations.yaml +2 -2
- package/runtime/knowledge/hfs/rules.yaml +2059 -0
- package/runtime/knowledge/hfs/slots.yaml +912 -120
- package/runtime/knowledge/patterns/be/api.yaml +369 -0
- package/runtime/knowledge/patterns/be/cli.yaml +297 -0
- package/runtime/knowledge/patterns/be/domain.yaml +113 -0
- package/runtime/knowledge/patterns/be/event-bus.yaml +285 -0
- package/runtime/knowledge/patterns/be/jobs.yaml +261 -0
- package/runtime/knowledge/patterns/be/projections.yaml +178 -0
- package/runtime/knowledge/patterns/be/queues.yaml +236 -0
- package/runtime/knowledge/patterns/be/reactors.yaml +140 -0
- package/runtime/knowledge/patterns/be/realtime.yaml +222 -0
- package/runtime/knowledge/patterns/be/saga.yaml +248 -0
- package/runtime/knowledge/patterns/be/webhooks.yaml +221 -0
- package/runtime/knowledge/patterns/fe/folder.yaml +131 -25
- package/runtime/knowledge/sonar-gate.yaml +52 -18
- package/runtime/modules/kernel/failure-codes.yaml +611 -51
- package/runtime/modules/models/registry.yaml +553 -0
- package/runtime/modules/models/runtimes.yaml +695 -0
- package/runtime/modules/ops/_labels.yaml +53 -0
- package/runtime/scripts/api/fs/forbidden-root.mjs +51 -0
- package/runtime/scripts/api/fs/is-link-like.mjs +25 -0
- package/runtime/scripts/api/fs/lib.mjs +16 -2
- package/runtime/scripts/api/fs/safe-remove.mjs +12 -132
- package/runtime/scripts/api/git/config-get.mjs +10 -0
- package/runtime/scripts/api/git/diff.mjs +5 -0
- package/runtime/scripts/api/git/lib.mjs +18 -26
- package/runtime/scripts/api/git/log.mjs +5 -0
- package/runtime/scripts/api/git/ls-files.mjs +6 -0
- package/runtime/scripts/api/git/ls-tree.mjs +5 -0
- package/runtime/scripts/api/git/merge-base.mjs +9 -0
- package/runtime/scripts/api/git/remote.mjs +5 -0
- package/runtime/scripts/api/git/rev-parse-query.mjs +5 -0
- package/runtime/scripts/api/git/show.mjs +6 -0
- package/runtime/scripts/api/node/lib.mjs +14 -0
- package/runtime/scripts/api/node/spawn-node.mjs +6 -0
- package/runtime/scripts/api/process/lib.mjs +111 -0
- package/runtime/scripts/api/process/owned-process.mjs +78 -0
- package/runtime/scripts/api/process/resolve-real-tool.mjs +46 -0
- package/runtime/scripts/api/process/run-program.mjs +7 -0
- package/runtime/scripts/api/process/stop-owned-process.mjs +9 -0
- package/runtime/scripts/api/sops/decrypt.mjs +9 -12
- package/runtime/scripts/api/sops/lib.mjs +255 -0
- package/runtime/scripts/api/sops/seal.mjs +22 -0
- package/runtime/scripts/connectors/lib.mjs +488 -0
- package/runtime/scripts/hfs/architecture/ast-walks.mjs +220 -0
- package/runtime/scripts/hfs/architecture/backend.mjs +16 -23
- package/runtime/scripts/hfs/architecture/background-unowned.mjs +16 -34
- package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +3 -1
- package/runtime/scripts/hfs/architecture/clones.mjs +4 -4
- package/runtime/scripts/hfs/architecture/config.mjs +9 -6
- package/runtime/scripts/hfs/architecture/connection-map.mjs +20 -8
- package/runtime/scripts/hfs/architecture/context-coupling.mjs +88 -0
- package/runtime/scripts/hfs/architecture/context-map.mjs +237 -0
- package/runtime/scripts/hfs/architecture/context-owner.mjs +82 -0
- package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -0
- package/runtime/scripts/hfs/architecture/context-transaction.mjs +60 -0
- package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +4 -10
- package/runtime/scripts/hfs/architecture/contracts.mjs +33 -162
- package/runtime/scripts/hfs/architecture/dead-exports.mjs +58 -29
- package/runtime/scripts/hfs/architecture/doc-language.mjs +1 -1
- package/runtime/scripts/hfs/architecture/entrypoint.mjs +2 -1
- package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +2 -2
- package/runtime/scripts/hfs/architecture/feature-shape.mjs +5 -2
- package/runtime/scripts/hfs/architecture/framework-pinned.mjs +1 -1
- package/runtime/scripts/hfs/architecture/frontend.mjs +17 -43
- package/runtime/scripts/hfs/architecture/hfs.mjs +24 -39
- package/runtime/scripts/hfs/architecture/i18n-keys.mjs +1 -1
- package/runtime/scripts/hfs/architecture/index.mjs +17 -4
- package/runtime/scripts/hfs/architecture/machine-ast.mjs +44 -11
- package/runtime/scripts/hfs/architecture/managed-scripts.mjs +27 -0
- package/runtime/scripts/hfs/architecture/module-per-transport.mjs +30 -6
- package/runtime/scripts/hfs/architecture/next-data.mjs +22 -63
- package/runtime/scripts/hfs/architecture/owners.mjs +35 -15
- package/runtime/scripts/hfs/architecture/register-once.mjs +2 -1
- package/runtime/scripts/hfs/architecture/registration.mjs +23 -81
- package/runtime/scripts/hfs/architecture/required-files.mjs +20 -12
- package/runtime/scripts/hfs/architecture/schema-owner.mjs +17 -114
- package/runtime/scripts/hfs/architecture/server-action.mjs +24 -0
- package/runtime/scripts/hfs/architecture/side-boundary.mjs +16 -0
- package/runtime/scripts/hfs/architecture/source-names.mjs +27 -147
- package/runtime/scripts/hfs/architecture/sql-owner.mjs +59 -18
- package/runtime/scripts/hfs/architecture/sql-returning.mjs +64 -0
- package/runtime/scripts/hfs/architecture/supabase-ast.mjs +111 -0
- package/runtime/scripts/hfs/architecture/supabase-be.mjs +131 -0
- package/runtime/scripts/hfs/architecture/supabase-tables.mjs +42 -0
- package/runtime/scripts/hfs/architecture/supabase.mjs +434 -0
- package/runtime/scripts/hfs/architecture/surface.mjs +9 -3
- package/runtime/scripts/hfs/architecture/test-world-files.mjs +9 -19
- package/runtime/scripts/hfs/architecture/tiers.mjs +47 -5
- package/runtime/scripts/hfs/architecture/transport-owner.mjs +3 -3
- package/runtime/scripts/hfs/architecture/typescript.mjs +12 -26
- package/runtime/scripts/hfs/architecture.mjs +4 -4
- package/runtime/scripts/hfs/check.mjs +75 -72
- package/runtime/scripts/hfs/coverage-scope.mjs +162 -0
- package/runtime/scripts/hfs/declaration-shape.mjs +62 -0
- package/runtime/scripts/hfs/declaration-slots.mjs +75 -0
- package/runtime/scripts/hfs/edition-slots.mjs +66 -0
- package/runtime/scripts/hfs/manifest-shape.mjs +109 -32
- package/runtime/scripts/hfs/param-names.mjs +18 -0
- package/runtime/scripts/hfs/path-findings.mjs +1 -1
- package/runtime/scripts/hfs/repo-identity.mjs +9 -6
- package/runtime/scripts/hfs/rule-params-shape.mjs +50 -0
- package/runtime/scripts/hfs/rules/app-root.mjs +51 -0
- package/runtime/scripts/hfs/rules/cli.mjs +37 -0
- package/runtime/scripts/hfs/rules/contract-compat.mjs +71 -0
- package/runtime/scripts/hfs/rules/contract.mjs +10 -9
- package/runtime/scripts/hfs/rules/database-config.mjs +102 -0
- package/runtime/scripts/hfs/rules/database-constants.mjs +13 -0
- package/runtime/scripts/hfs/rules/database-migrations.mjs +111 -0
- package/runtime/scripts/hfs/rules/database-plpgsql.mjs +233 -0
- package/runtime/scripts/hfs/rules/database-sql.mjs +336 -0
- package/runtime/scripts/hfs/rules/database.mjs +68 -0
- package/runtime/scripts/hfs/rules/deps.mjs +1 -1
- package/runtime/scripts/hfs/rules/docker.mjs +259 -0
- package/runtime/scripts/hfs/rules/edition.mjs +111 -0
- package/runtime/scripts/hfs/rules/event-bus.mjs +153 -0
- package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -1
- package/runtime/scripts/hfs/rules/fe-no-tests.mjs +6 -5
- package/runtime/scripts/hfs/rules/frontend-tree.mjs +9 -9
- package/runtime/scripts/hfs/rules/integration-specs.mjs +3 -6
- package/runtime/scripts/hfs/rules/kinds.mjs +84 -0
- package/runtime/scripts/hfs/rules/lint-suppression.mjs +1 -1
- package/runtime/scripts/hfs/rules/monorepo.mjs +179 -0
- package/runtime/scripts/hfs/rules/peer-integrations.mjs +3 -3
- package/runtime/scripts/hfs/rules/pipeline.mjs +11 -21
- package/runtime/scripts/hfs/rules/proof-commands.mjs +2 -2
- package/runtime/scripts/hfs/rules/read.mjs +1 -1
- package/runtime/scripts/hfs/rules/repo-local-checks.mjs +2 -2
- package/runtime/scripts/hfs/rules/saga.mjs +170 -0
- package/runtime/scripts/hfs/rules/secrets.mjs +3 -3
- package/runtime/scripts/hfs/rules/services.mjs +220 -0
- package/runtime/scripts/hfs/rules/spec-placement.mjs +1 -1
- package/runtime/scripts/hfs/rules/stacks.mjs +3 -3
- package/runtime/scripts/hfs/rules/supabase-secrets.mjs +89 -0
- package/runtime/scripts/hfs/rules/test-topology.mjs +2 -2
- package/runtime/scripts/hfs/secret.mjs +209 -0
- package/runtime/scripts/hfs/slots.mjs +78 -108
- package/runtime/scripts/hfs/sql/pg-parse.mjs +46 -0
- package/runtime/scripts/hfs/test-world-slot.mjs +6 -0
- package/runtime/scripts/hfs/tree.mjs +5 -4
- package/runtime/scripts/hfs/typescript-programs.mjs +0 -5
- package/runtime/scripts/hfs/view.mjs +3 -2
- package/runtime/scripts/lib/clip.mjs +19 -0
- package/runtime/scripts/lib/display-names.mjs +259 -0
- package/runtime/scripts/lib/dockerfile.mjs +124 -0
- package/runtime/scripts/lib/env.mjs +10 -0
- package/runtime/scripts/lib/event-contract.mjs +103 -0
- package/runtime/scripts/lib/example-refs.mjs +158 -0
- package/runtime/scripts/lib/fs-kind.mjs +14 -4
- package/runtime/scripts/lib/git.mjs +36 -0
- package/runtime/scripts/lib/graphql-contract.mjs +1 -1
- package/runtime/scripts/lib/i18n.mjs +86 -0
- package/runtime/scripts/lib/json-schema.mjs +52 -0
- package/runtime/scripts/lib/json.mjs +13 -3
- package/runtime/scripts/lib/language.mjs +24 -5
- package/runtime/scripts/lib/list.mjs +20 -0
- package/runtime/scripts/lib/mutation-fence.mjs +15 -0
- package/runtime/scripts/lib/package-at.mjs +37 -0
- package/runtime/scripts/lib/path-key.mjs +57 -2
- package/runtime/scripts/lib/process-identity.mjs +6 -0
- package/runtime/scripts/lib/read-text.mjs +34 -0
- package/runtime/scripts/lib/read-yaml.mjs +18 -0
- package/runtime/scripts/lib/redact.mjs +161 -0
- package/runtime/scripts/lib/regex.mjs +4 -0
- package/runtime/scripts/lib/same-text.mjs +5 -0
- package/runtime/scripts/lib/secret-patterns.mjs +4 -3
- package/runtime/scripts/lib/sleep-sync.mjs +2 -1
- package/runtime/scripts/lib/sleep.mjs +7 -0
- package/runtime/scripts/lib/sops-envelope.mjs +112 -0
- package/runtime/scripts/lib/source-phrases.mjs +34 -0
- package/runtime/scripts/lib/sqlite.mjs +21 -0
- package/runtime/scripts/lib/stack-services.mjs +7 -31
- package/runtime/scripts/lib/ts-ast.mjs +35 -0
- package/runtime/scripts/lib/walk.mjs +4 -3
- package/scaffold/add-app.mjs +174 -0
- package/scaffold/add-cli-lite.mjs +257 -0
- package/scaffold/add-inbox-lite.mjs +314 -0
- package/scaffold/add-table.mjs +344 -0
- package/scaffold/add.mjs +299 -0
- package/scaffold/app.mjs +358 -69
- package/scaffold/edition-gate.mjs +25 -0
- package/scaffold/image.mjs +19 -0
- package/scaffold/lite-exports.mjs +186 -0
- package/scaffold/service.mjs +32 -26
- package/scaffold/supabase-ports.mjs +26 -0
- package/src/main.mjs +327 -0
- package/sync/cli.mjs +6 -9
- package/sync/format.mjs +1 -1
- package/sync/hygiene.mjs +10 -10
- package/sync/index.mjs +167 -104
- package/sync/managed.mjs +19 -11
- package/sync/sonar-key.mjs +5 -0
- package/templates/app/ci-workflows/github/workflows/ci.yml +14 -14
- package/templates/app/ci-workflows/github/workflows/images.yml +37 -0
- package/templates/app/ci-workflows/sonar-steps.yml +9 -0
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +66 -0
- package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +31 -0
- package/templates/app/ci-workflows-lite/github/workflows/images.yml +37 -0
- package/templates/app/codegen-lite/scripts/codegen.mjs +32 -0
- package/templates/app/docker-ignore/dockerignore +50 -0
- package/templates/app/gitignore-lite +35 -0
- package/templates/app/hooks/husky/pre-commit +3 -8
- package/templates/app/hooks/husky/pre-push +45 -6
- package/templates/app/package-scripts/core.json +8 -0
- package/templates/app/package-scripts/package.json +3 -10
- package/templates/app/package-scripts-lite/package.json +15 -0
- package/templates/app/quality-config/codecov.yml +15 -3
- package/templates/app/quality-config/sonar-base.properties +4 -0
- package/templates/app/quality-config/sonar-project.properties +1 -4
- package/templates/app/quality-config-lite/sonar-project.properties +5 -0
- package/templates/app/skeleton/.starcistacks/dev/seeds/primary-notes.sql +5 -0
- package/templates/app/skeleton/.starciwork/features/system-health/index.yaml +4 -0
- package/templates/app/skeleton/.starciwork/{features/index.yaml → index.yaml} +2 -2
- package/templates/app/skeleton/README.md +7 -5
- package/templates/app/skeleton-lite/.sops.yaml +3 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +5 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/secrets/.gitkeep +1 -0
- package/templates/app/skeleton-lite/.starciwork/shell/index.yaml +55 -0
- package/templates/app/skeleton-lite/README.md +40 -0
- package/templates/app/skeleton-lite/supabase/config.toml +41 -0
- package/templates/app/skeleton-lite/supabase/migrations/__timestamp___baseline.sql +56 -0
- package/templates/app/skeleton-lite/supabase/seed.sql +0 -0
- package/templates/app/task-graph/turbo.json +23 -0
- package/templates/app/tool-config-lite/prettierignore +2 -0
- package/templates/app/tool-config-lite/prettierrc +1 -0
- package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +38 -0
- package/templates/app/upgrade-full/.starcistacks/dev/README.md +10 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +13 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +3 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +12 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +7 -0
- package/templates/be/common/main-listen.ts.partial +14 -0
- package/templates/be/common/sql-ident.ts.partial +7 -0
- package/templates/be/common/sql-tag.ts.partial +5 -0
- package/templates/be/image/api/Dockerfile +38 -0
- package/templates/be/image/cli/Dockerfile +38 -0
- package/templates/be/image/worker/Dockerfile +36 -0
- package/templates/be/inbox/database-client.ts.tpl +50 -0
- package/templates/be/inbox/index.ts.tpl +2 -0
- package/templates/be/inbox/migration.sql.tpl +29 -0
- package/templates/be/inbox/module-definition.ts.tpl +6 -0
- package/templates/be/inbox/module.ts.tpl +14 -0
- package/templates/be/inbox/options.ts.tpl +2 -0
- package/templates/be/inbox/service.ts.tpl +33 -0
- package/templates/be/inbox/sql.ts.tpl +16 -0
- package/templates/be/inbox/webhook-door.ts.tpl +36 -0
- package/templates/be/patterns/api/application.command.http.ts.tpl +10 -0
- package/templates/be/patterns/api/application.command.ts.tpl +10 -0
- package/templates/be/patterns/api/application.contracts.ts.tpl +11 -0
- package/templates/be/patterns/api/application.handler.http.ts.tpl +22 -0
- package/templates/be/patterns/api/application.handler.ts.tpl +22 -0
- package/templates/be/patterns/api/feature.index.http.ts.tpl +1 -0
- package/templates/be/patterns/api/feature.index.ts.tpl +1 -0
- package/templates/be/patterns/api/feature.module.ts.tpl +6 -0
- package/templates/be/patterns/api/graphql.input.ts.tpl +13 -0
- package/templates/be/patterns/api/graphql.mapper.ts.tpl +9 -0
- package/templates/be/patterns/api/graphql.module.ts.tpl +7 -0
- package/templates/be/patterns/api/graphql.resolver.ts.tpl +27 -0
- package/templates/be/patterns/api/graphql.type.ts.tpl +9 -0
- package/templates/be/patterns/api/http.controller.ts.tpl +27 -0
- package/templates/be/patterns/api/http.mapper.ts.tpl +9 -0
- package/templates/be/patterns/api/http.module.ts.tpl +7 -0
- package/templates/be/patterns/api/http.request.ts.tpl +10 -0
- package/templates/be/patterns/api/http.response.ts.tpl +5 -0
- package/templates/be/patterns/cli/group.cli.spec.ts.tpl +15 -0
- package/templates/be/patterns/cli/group.cli.ts.tpl +11 -0
- package/templates/be/patterns/cli/group.module.ts.tpl +7 -0
- package/templates/be/patterns/cli/sub.run.cli.spec.ts.tpl +17 -0
- package/templates/be/patterns/cli/sub.run.cli.ts.tpl +15 -0
- package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +22 -0
- package/templates/be/patterns/event-bus/platform/event-bus.config.ts.tpl +19 -0
- package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +58 -0
- package/templates/be/patterns/event-bus/platform/event-bus.decorators.ts.tpl +46 -0
- package/templates/be/patterns/event-bus/platform/event-bus.log-events.ts.tpl +12 -0
- package/templates/be/patterns/event-bus/platform/event-bus.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/event-bus/platform/event-bus.module.ts.tpl +52 -0
- package/templates/be/patterns/event-bus/platform/event-bus.options.ts.tpl +19 -0
- package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +28 -0
- package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +165 -0
- package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +93 -0
- package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +90 -0
- package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +58 -0
- package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +136 -0
- package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +56 -0
- package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +272 -0
- package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +128 -0
- package/templates/be/patterns/event-bus/platform/event-transport.port.ts.tpl +180 -0
- package/templates/be/patterns/event-bus/platform/event.policy.spec.ts.tpl +67 -0
- package/templates/be/patterns/event-bus/platform/event.policy.ts.tpl +38 -0
- package/templates/be/patterns/event-bus/platform/index.ts.tpl +11 -0
- package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.spec.ts.tpl +348 -0
- package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.ts.tpl +241 -0
- package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +15 -0
- package/templates/be/patterns/event-bus/platform/persistence/connection.ts.tpl +8 -0
- package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +37 -0
- package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +11 -0
- package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +12 -0
- package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +26 -0
- package/templates/be/patterns/jobs/job.index.ts.tpl +1 -0
- package/templates/be/patterns/jobs/job.module.ts.tpl +6 -0
- package/templates/be/patterns/jobs/job.processor.ts.tpl +20 -0
- package/templates/be/patterns/jobs/job.queue.module.ts.tpl +20 -0
- package/templates/be/patterns/jobs/job.step.ts.tpl +19 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +31 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.ts.tpl +13 -0
- package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +150 -0
- package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +100 -0
- package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +138 -0
- package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +69 -0
- package/templates/be/patterns/jobs/platform/jobs.config.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +62 -0
- package/templates/be/patterns/jobs/platform/jobs.decorators.ts.tpl +31 -0
- package/templates/be/patterns/jobs/platform/jobs.error.ts.tpl +22 -0
- package/templates/be/patterns/jobs/platform/jobs.index.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.log-events.ts.tpl +9 -0
- package/templates/be/patterns/jobs/platform/jobs.messages.ts.tpl +15 -0
- package/templates/be/patterns/jobs/platform/jobs.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/jobs/platform/jobs.module.ts.tpl +32 -0
- package/templates/be/patterns/jobs/platform/jobs.options.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.port.ts.tpl +36 -0
- package/templates/be/patterns/jobs/platform/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/jobs/platform/persistence.job.entity.ts.tpl +53 -0
- package/templates/be/patterns/jobs/platform/persistence.jobs.rows.ts.tpl +13 -0
- package/templates/be/patterns/jobs/platform/persistence.jobs.sql.ts.tpl +33 -0
- package/templates/be/patterns/jobs/platform/persistence.migration.ts.tpl +29 -0
- package/templates/be/patterns/outbox/platform/index.ts.tpl +2 -0
- package/templates/be/patterns/outbox/platform/outbox-relay.policy.spec.ts.tpl +96 -0
- package/templates/be/patterns/outbox/platform/outbox-relay.policy.ts.tpl +78 -0
- package/templates/be/patterns/outbox/platform/outbox.log-events.ts.tpl +5 -0
- package/templates/be/patterns/projections/migration.ts.tpl +18 -0
- package/templates/be/patterns/projections/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/projections/projection.entity.ts.tpl +9 -0
- package/templates/be/patterns/projections/projection.index.ts.tpl +3 -0
- package/templates/be/patterns/projections/projection.module-definition.ts.tpl +7 -0
- package/templates/be/patterns/projections/projection.module.ts.tpl +18 -0
- package/templates/be/patterns/projections/projection.options.ts.tpl +2 -0
- package/templates/be/patterns/projections/projection.projection.spec.ts.tpl +55 -0
- package/templates/be/patterns/projections/projection.projection.ts.tpl +21 -0
- package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +142 -0
- package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +81 -0
- package/templates/be/patterns/queues/platform/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +25 -0
- package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +25 -0
- package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +9 -0
- package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +12 -0
- package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +48 -0
- package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +17 -0
- package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +128 -0
- package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +48 -0
- package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +115 -0
- package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +91 -0
- package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +45 -0
- package/templates/be/patterns/queues/platform/queue.config.ts.tpl +15 -0
- package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +31 -0
- package/templates/be/patterns/queues/platform/queue.decorators.ts.tpl +45 -0
- package/templates/be/patterns/queues/platform/queue.index.ts.tpl +7 -0
- package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +5 -0
- package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/queues/platform/queue.module.ts.tpl +62 -0
- package/templates/be/patterns/queues/platform/queue.options.ts.tpl +22 -0
- package/templates/be/patterns/queues/platform/queue.policy.spec.ts.tpl +19 -0
- package/templates/be/patterns/queues/platform/queue.policy.ts.tpl +11 -0
- package/templates/be/patterns/queues/platform/queue.port.ts.tpl +14 -0
- package/templates/be/patterns/queues/queue.index.ts.tpl +3 -0
- package/templates/be/patterns/queues/queue.module.ts.tpl +6 -0
- package/templates/be/patterns/queues/queue.queue.ts.tpl +23 -0
- package/templates/be/patterns/reactors/application.command.ts.tpl +10 -0
- package/templates/be/patterns/reactors/application.contracts.ts.tpl +12 -0
- package/templates/be/patterns/reactors/application.handler.ts.tpl +22 -0
- package/templates/be/patterns/reactors/consumer.ts.tpl +19 -0
- package/templates/be/patterns/reactors/message.module.ts.tpl +20 -0
- package/templates/be/patterns/reactors/reactor.index.ts.tpl +1 -0
- package/templates/be/patterns/reactors/reactor.module.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.graphql.module.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.index.ts.tpl +1 -0
- package/templates/be/patterns/realtime/channel.input.ts.tpl +12 -0
- package/templates/be/patterns/realtime/channel.subscription.spec.ts.tpl +51 -0
- package/templates/be/patterns/realtime/channel.subscription.ts.tpl +32 -0
- package/templates/be/patterns/realtime/channel.type.ts.tpl +9 -0
- package/templates/be/patterns/saga/saga.compensate.command.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.compensate.contracts.ts.tpl +7 -0
- package/templates/be/patterns/saga/saga.compensate.handler.ts.tpl +22 -0
- package/templates/be/patterns/saga/saga.compensation.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.complete.command.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.complete.contracts.ts.tpl +7 -0
- package/templates/be/patterns/saga/saga.complete.handler.ts.tpl +22 -0
- package/templates/be/patterns/saga/saga.done.consumer.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.failed.consumer.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.index.ts.tpl +1 -0
- package/templates/be/patterns/saga/saga.message.module.ts.tpl +23 -0
- package/templates/be/patterns/saga/saga.module.ts.tpl +20 -0
- package/templates/be/patterns/saga/saga.service.spec.ts.tpl +70 -0
- package/templates/be/patterns/saga/saga.service.ts.tpl +44 -0
- package/templates/be/patterns/saga/saga.state.ts.tpl +14 -0
- package/templates/be/patterns/saga/saga.step.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.undo.command.ts.tpl +10 -0
- package/templates/be/patterns/saga/saga.undo.contracts.ts.tpl +5 -0
- package/templates/be/patterns/saga/saga.undo.handler.ts.tpl +21 -0
- package/templates/be/patterns/webhooks/webhook.door.spec.ts.tpl +72 -0
- package/templates/be/patterns/webhooks/webhook.door.ts.tpl +36 -0
- package/templates/be/patterns/webhooks/webhook.http.module.ts.tpl +6 -0
- package/templates/be/patterns/webhooks/webhook.index.ts.tpl +1 -0
- package/templates/be/patterns/webhooks/webhook.request.ts.tpl +9 -0
- package/templates/be/skeleton/apps/__app__/src/__app__.options.ts +3 -0
- package/templates/be/skeleton/apps/__app__/src/app.module.ts +15 -2
- package/templates/be/skeleton/apps/__app__/src/main.ts +7 -15
- package/templates/be/skeleton/apps/cli/src/app.module.ts +30 -0
- package/templates/be/skeleton/apps/cli/src/cli.options.ts +22 -0
- package/templates/be/skeleton/apps/cli/src/main.ts +24 -0
- package/templates/be/skeleton/src/features/cli/cli.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/index.ts +1 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.ts +15 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.ts +18 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.cli.ts +15 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.spec.ts +33 -0
- package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.ts +34 -0
- package/templates/be/skeleton/src/modules/domain/identity/admission.policy.spec.ts +13 -0
- package/templates/be/skeleton/src/modules/domain/identity/auth.guard.spec.ts +40 -0
- package/templates/be/skeleton/src/modules/domain/identity/messages/identity.messages.ts +1 -1
- package/templates/be/skeleton/src/modules/domain/note/errors/note.error.ts +16 -0
- package/templates/be/skeleton/src/modules/domain/note/index.ts +3 -0
- package/templates/be/skeleton/src/modules/domain/note/note.contracts.ts +19 -0
- package/templates/be/skeleton/src/modules/domain/note/note.decorators.ts +9 -0
- package/templates/be/skeleton/src/modules/domain/note/note.module-definition.ts +7 -0
- package/templates/be/skeleton/src/modules/domain/note/note.module.ts +19 -0
- package/templates/be/skeleton/src/modules/domain/note/note.options.ts +2 -0
- package/templates/be/skeleton/src/modules/domain/note/note.service.spec.ts +76 -0
- package/templates/be/skeleton/src/modules/domain/note/note.service.ts +37 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/connection.ts +8 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/entities/note.entity.ts +17 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/migrations/1790000000000-init-note.ts +22 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/note.rows.ts +17 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/note.sql.ts +4 -0
- package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +20 -0
- package/templates/be/skeleton/src/modules/platform/config/index.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/cqrs/cqrs.contracts.ts +18 -0
- package/templates/be/skeleton/src/modules/platform/database/connection-source.client.spec.ts +41 -0
- package/templates/be/skeleton/src/modules/platform/database/connection-source.client.ts +17 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module-definition.ts +13 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module.ts +77 -0
- package/templates/be/skeleton/src/modules/platform/database/database.options.ts +30 -0
- package/templates/be/skeleton/src/modules/platform/database/database.port.ts +65 -0
- package/templates/be/skeleton/src/modules/platform/database/database.sql.ts +47 -0
- package/templates/be/skeleton/src/modules/platform/database/errors/database.error.ts +16 -0
- package/templates/be/skeleton/src/modules/platform/database/index.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/database/migrate-connections.client.ts +30 -0
- package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.spec.ts +84 -0
- package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.ts +23 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.config.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.connection.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.decorators.ts +10 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.spec.ts +108 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.ts +75 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.spec.ts +88 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.ts +29 -0
- package/templates/be/skeleton/src/modules/platform/errors/errors.filter.spec.ts +48 -0
- package/templates/be/skeleton/src/modules/platform/errors/messages/errors.messages.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/http-security/errors/http-security.error.ts +12 -0
- package/templates/be/skeleton/src/modules/platform/http-security/execution-request.mapper.spec.ts +16 -0
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.config.ts +8 -1
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.decorators.ts +8 -0
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.module.ts +14 -1
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.options.ts +12 -0
- package/templates/be/skeleton/src/modules/platform/http-security/messages/http-security.messages.ts +10 -2
- package/templates/be/skeleton/src/modules/platform/http-security/origin.guard.spec.ts +63 -0
- package/templates/be/skeleton/src/modules/platform/http-security/rate-limit.guard.spec.ts +108 -0
- package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.spec.ts +39 -0
- package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.ts +25 -0
- package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.spec.ts +172 -0
- package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.ts +66 -0
- package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +3 -1
- package/templates/be/skeleton/src/modules/platform/primitives/outcome.mapper.spec.ts +52 -0
- package/templates/be/skeleton-lite/apps/api/Dockerfile +37 -0
- package/templates/be/skeleton-lite/apps/api/src/api.options.ts +16 -0
- package/templates/be/skeleton-lite/apps/api/src/app.module.ts +81 -0
- package/templates/be/skeleton-lite/apps/api/src/main.ts +34 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.ts +14 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +50 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +26 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +19 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +26 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +7 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +6 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +19 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/index.ts +10 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.ts +24 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.config.ts +8 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.decorators.ts +17 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.jwks.ts +32 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.options.ts +24 -0
- package/templates/be/skeleton-lite/src/modules/platform/cqrs/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +54 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.options.ts +23 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.port.ts +10 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.sql.ts +49 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/migration-runner.service.ts +21 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/primary.config.ts +11 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/seed-runner.service.ts +28 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/http-security.module.ts +25 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +9 -0
- package/templates/be/skeleton-lite/src/modules/platform/i18n/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +5 -0
- package/templates/be/table/error.ts.tpl +16 -0
- package/templates/be/table/index.ts.tpl +2 -0
- package/templates/be/table/migration.sql.tpl +51 -0
- package/templates/be/table/module-definition.ts.tpl +7 -0
- package/templates/be/table/module.ts.tpl +14 -0
- package/templates/be/table/options.ts.tpl +2 -0
- package/templates/be/table/rows.ts.tpl +4 -0
- package/templates/be/table/service.ts.tpl +23 -0
- package/templates/be/table/sql.ts.tpl +4 -0
- package/templates/be/tool-config/jest.config.js +3 -1
- package/templates/be/upgrade-full/apps/cli/src/app.module.ts +14 -0
- package/templates/be/upgrade-full/apps/cli/src/main.ts +26 -0
- package/templates/be/upgrade-full/src/features/cli/cli.module.ts +6 -0
- package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +23 -0
- package/templates/common/gitignore.base +1 -2
- package/templates/fe/app/package.json.tpl +1 -0
- package/templates/fe/app/tsconfig.json +12 -0
- package/templates/fe/common/app-layout.tsx.partial +8 -0
- package/templates/fe/common/site-shell.tsx.partial +9 -0
- package/templates/fe/image/next/Dockerfile +42 -0
- package/templates/fe/skeleton/apps/app/next.config.ts +23 -0
- package/templates/fe/skeleton/apps/app/postcss.config.mjs +7 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/error.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/[locale]/layout.tsx +22 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/loading.tsx +2 -2
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/not-found.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/global-error.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/globals.css +10 -0
- package/templates/fe/skeleton/apps/app/src/features/layouts/AppLayout/index.tsx +18 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/component.tsx +19 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/index.tsx +11 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppGlobalErrorPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/component.tsx +10 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/index.tsx +15 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/index.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/vi.json +28 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/request.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/modules/routes/index.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/proxy.ts +1 -0
- package/templates/fe/skeleton/apps/{__app__ → landing}/next.config.ts +4 -2
- package/templates/fe/skeleton/apps/landing/postcss.config.mjs +7 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/error.tsx +10 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/layout.tsx +22 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/loading.tsx +6 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/not-found.tsx +6 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton/apps/landing/src/app/global-error.tsx +10 -0
- package/templates/fe/skeleton/apps/landing/src/app/globals.css +10 -0
- package/templates/fe/skeleton/apps/landing/src/features/layouts/LandingLayout/index.tsx +24 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/component.tsx +18 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/index.tsx +11 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingGlobalErrorPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/component.tsx +24 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/landing/src/modules/config/index.ts +12 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/index.ts +7 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/messages/vi.json +31 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/request.ts +4 -0
- package/templates/fe/skeleton/apps/landing/src/modules/routes/index.ts +4 -0
- package/templates/fe/skeleton/apps/landing/src/proxy.ts +1 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/index.ts +49 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/proxy.ts +24 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +20 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/branches/Providers/index.tsx +23 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/ErrorNotice/index.tsx +14 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/GlobalErrorNotice/index.tsx +25 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/LoadingNotice/index.tsx +9 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/LocaleShell/index.tsx +21 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/NotFoundNotice/index.tsx +19 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/classNames.ts +4 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/index.tsx +19 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/index.ts +6 -0
- package/templates/fe/skeleton-lite/apps/web/next.config.ts +22 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/error.tsx +10 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/layout.tsx +37 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/loading.tsx +6 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/not-found.tsx +6 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/providers.tsx +26 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/auth/callback/route.ts +24 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/global-error.tsx +10 -0
- package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/src/app/globals.css +1 -1
- package/templates/fe/skeleton-lite/apps/web/src/app/health/live/route.ts +5 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/component.tsx +29 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/index.tsx +41 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/component.tsx +17 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/index.tsx +38 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/ErrorNotice/index.tsx +13 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/GlobalErrorNotice/index.tsx +24 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/LoadingNotice/index.tsx +7 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/NotFoundNotice/index.tsx +18 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/classNames.ts +4 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/index.tsx +13 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/layouts/AppLayout/index.tsx +31 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/component.tsx +12 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/index.tsx +10 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppGlobalErrorPage/index.tsx +15 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/component.tsx +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +30 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/brand/brand.css +20 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/brand/index.ts +2 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/config/index.ts +20 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/read-session.ts +25 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-in.ts +25 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-out.ts +17 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/browser.ts +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/index.ts +3 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/outcome.ts +59 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/principal.ts +29 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/server.ts +70 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/validation/validation.mapper.ts +50 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/index.ts +8 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +48 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/request.ts +16 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/routes/index.ts +7 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/routes/safe-next-path.ts +26 -0
- package/templates/fe/skeleton-lite/apps/web/src/proxy.ts +43 -0
- package/templates/fe/table/read.ts.tpl +16 -0
- package/templates/fe/table/write.ts.tpl +16 -0
- package/upgrade/check.mjs +137 -0
- package/upgrade/index.mjs +524 -0
- package/bin/hfs.mjs +0 -233
- package/runtime/scripts/api/fs/rmdir-link.mjs +0 -12
- package/runtime/scripts/lib/test-secrets.mjs +0 -116
- package/templates/fe/skeleton/apps/__app__/src/app/[locale]/layout.tsx +0 -20
- package/templates/fe/skeleton/apps/__app__/src/app/[locale]/page.tsx +0 -9
- package/templates/fe/skeleton/apps/__app__/src/components/composites/FailureScreen/index.tsx +0 -28
- package/templates/fe/skeleton/apps/__app__/src/features/layouts/LocaleShell/index.tsx +0 -35
- package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/component.tsx +0 -19
- package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/index.tsx +0 -11
- package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/component.tsx +0 -24
- package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/index.tsx +0 -14
- package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/component.tsx +0 -21
- package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/index.tsx +0 -15
- package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/component.tsx +0 -23
- package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/index.tsx +0 -8
- package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/component.tsx +0 -28
- package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/index.tsx +0 -8
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/config.ts +0 -8
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/index.ts +0 -2
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/messages/vi.json +0 -25
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/request.ts +0 -19
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/routing.ts +0 -9
- package/templates/fe/skeleton/apps/__app__/src/modules/routes/index.ts +0 -4
- package/templates/fe/skeleton/apps/__app__/src/proxy.ts +0 -10
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.contracts.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.handler.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.query.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/index.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/system-health.module.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/live.controller.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/system-health-http.module.ts +0 -0
- /package/templates/fe/skeleton/apps/{__app__ → app}/src/app/health/live/route.ts +0 -0
- /package/templates/fe/skeleton/apps/{__app__ → app}/src/modules/config/index.ts +0 -0
- /package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/postcss.config.mjs +0 -0
|
@@ -0,0 +1,924 @@
|
|
|
1
|
+
-- ############################################################################################################
|
|
2
|
+
-- machine.sqlite (one per machine) - this file is the single schema step of the database.
|
|
3
|
+
-- Tables: machine_meta/schema_migrations - identity and migration journal; ui_states/ui_state_map - display
|
|
4
|
+
-- vocabulary; blob_ref_columns - blob-referencing columns; ledgers/repositories - registered projects;
|
|
5
|
+
-- agents/models - agent and model catalog; blobs/archives/gc_marks - content store and GC; sup_* - Supervisor;
|
|
6
|
+
-- process_runs/engine_*/schedules/sla_episodes/invariant_violations - reconciler; services/seats/deliveries/
|
|
7
|
+
-- seat_turns/terminals/host_locks/claims/agent_sessions - machine objects; throttle_*/
|
|
8
|
+
-- host_samples/provider_*/pool_backoff/quotas/guard_*/host_*/budgets - capacity and spend; gc_*/lanes/land_*/
|
|
9
|
+
-- pushes/worktrees/env_servers/uat_slots/connectors/ask_requests - worker operations; machine_logs/
|
|
10
|
+
-- metrics_snapshots/notifications - observability; v_* - durable views.
|
|
11
|
+
-- ############################################################################################################
|
|
12
|
+
|
|
13
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
14
|
+
-- B0. Identity, vocabulary, registry, catalog, archive
|
|
15
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
16
|
+
-- machine_meta: host_id, schema='starci/machine@1', created_at, blob_root, runtime_rev, sqlite_version, node_version.
|
|
17
|
+
CREATE TABLE IF NOT EXISTS machine_meta(key TEXT PRIMARY KEY, value TEXT NOT NULL) STRICT;
|
|
18
|
+
CREATE TABLE IF NOT EXISTS schema_migrations(
|
|
19
|
+
version INTEGER PRIMARY KEY, name TEXT NOT NULL, runtime_rev TEXT, sql_sha256 TEXT NOT NULL,
|
|
20
|
+
backup_path TEXT, backup_sha256 TEXT, started_at INTEGER NOT NULL, finished_at INTEGER,
|
|
21
|
+
status TEXT NOT NULL CHECK(status IN ('running','done','failed'))) STRICT;
|
|
22
|
+
|
|
23
|
+
CREATE TABLE IF NOT EXISTS ui_states(
|
|
24
|
+
ui TEXT PRIMARY KEY CHECK(ui IN ('bad','warn','running','waiting','ok','done','unknown')),
|
|
25
|
+
rank INTEGER NOT NULL) STRICT;
|
|
26
|
+
INSERT OR IGNORE INTO ui_states VALUES
|
|
27
|
+
('bad',0),('warn',1),('running',2),('waiting',3),('ok',4),('done',5),('unknown',6);
|
|
28
|
+
CREATE TABLE IF NOT EXISTS ui_state_map(
|
|
29
|
+
entity TEXT NOT NULL, native TEXT NOT NULL, ui TEXT NOT NULL REFERENCES ui_states(ui), PRIMARY KEY(entity,native)) STRICT;
|
|
30
|
+
INSERT OR IGNORE INTO ui_state_map VALUES
|
|
31
|
+
('service','healthy','ok'),('service','ok','ok'),('service','live','ok'),('service','down','bad'),('service','dead','bad'),
|
|
32
|
+
('service','quarantined','bad'),('service','stale','bad'),('service','restarting','warn'),('service','booting','running'),
|
|
33
|
+
('seat','empty','waiting'),('seat','parked','done'),('seat','booting','running'),('seat','live','ok'),('seat','busy','running'),
|
|
34
|
+
('seat','stale','bad'),('seat','dead','bad'),('seat','replacing','warn'),('seat','quarantined','bad'),('service','degraded','warn'),
|
|
35
|
+
('engine-action','fenced','warn'),('push','failed','bad'),
|
|
36
|
+
('sla','running','waiting'),('sla','violated','warn'),('sla','violated-critical','bad'),('sla','cleared','done'),
|
|
37
|
+
('engine-action','intent','running'),('engine-action','running','running'),('engine-action','done','done'),
|
|
38
|
+
('engine-action','failed','bad'),('engine-action','unknown','bad'),
|
|
39
|
+
('land','queued','waiting'),('land','running','running'),('land','passed','done'),('land','failed','bad'),
|
|
40
|
+
('land','conflict','bad'),('land','refused','bad'),('land','cancelled','done'),
|
|
41
|
+
('push','pushed','done'),('push','skipped','waiting'),('push','refused','bad'),
|
|
42
|
+
('lane','open','running'),('lane','landing','running'),('lane','landed','done'),('lane','abandoned','done'),('lane','removed','done'),
|
|
43
|
+
('provider','healthy','ok'),('provider','recovered','ok'),('provider','striking','warn'),('provider','unavailable','bad'),
|
|
44
|
+
('throttle','normal','ok'),('throttle','heavy','warn'),('throttle','critical','bad'),
|
|
45
|
+
('sup-job','queued','waiting'),('sup-job','spawning','running'),('sup-job','running','running'),('sup-job','reported','running'),
|
|
46
|
+
('sup-job','landing','running'),('sup-job','succeeded','done'),('sup-job','failed','bad'),('sup-job','cancelled','done'),
|
|
47
|
+
('decision','open','waiting'),('decision','claimed','running'),('decision','escalated','warn'),('decision','expired','warn'),
|
|
48
|
+
('decision','resolved','done'),('decision','superseded','done'),
|
|
49
|
+
('owed','open','waiting'),('owed','acked','running'),('owed','closed','done'),
|
|
50
|
+
('gc-run','running','running'),('gc-run','done','done'),('gc-run','errors','warn'),
|
|
51
|
+
('env-server','starting','running'),('env-server','ready','ok'),('env-server','failed','bad'),('env-server','stopped','done'),
|
|
52
|
+
('ask','open','waiting'),('ask','answered','done'),('ask','retired','done'),('ask','expired','warn');
|
|
53
|
+
|
|
54
|
+
CREATE TABLE IF NOT EXISTS blob_ref_columns(
|
|
55
|
+
table_name TEXT NOT NULL, column_name TEXT NOT NULL, PRIMARY KEY(table_name,column_name)) STRICT;
|
|
56
|
+
INSERT OR IGNORE INTO blob_ref_columns VALUES
|
|
57
|
+
('lanes','report_sha'),('land_runs','stdout_sha'),('land_runs','stderr_sha'),
|
|
58
|
+
('engine_actions','result_sha'),('engine_actions','stdout_sha'),('engine_actions','stderr_sha'),
|
|
59
|
+
('metrics_snapshots','data_sha'),('sup_reports','report_sha'),('sup_attempts','prompt_sha'),('sup_attempts','transcript_sha'),
|
|
60
|
+
('env_servers','log_sha'),('notifications','media_sha'),('agent_sessions','transcript_sha'),('sup_events','payload_sha'),
|
|
61
|
+
('seat_transcript_snapshots','sha256'),('pushes','stdout_sha'),('pushes','stderr_sha'),('gc_runs','report_sha');
|
|
62
|
+
|
|
63
|
+
-- ledgers: the ONLY registry of every runtime.sqlite (reconciler, GC, harness read it here; replaces config.yaml supervisor.repos).
|
|
64
|
+
CREATE TABLE IF NOT EXISTS ledgers(
|
|
65
|
+
ledger_id TEXT PRIMARY KEY, -- = meta.ledger_id inside the file (UUID)
|
|
66
|
+
name TEXT NOT NULL UNIQUE, -- 'acme-backend'
|
|
67
|
+
product TEXT,
|
|
68
|
+
repo_root TEXT NOT NULL,
|
|
69
|
+
file TEXT NOT NULL,
|
|
70
|
+
state TEXT NOT NULL DEFAULT 'active' CHECK(state IN ('active','idle','retired')),
|
|
71
|
+
schema_version INTEGER,
|
|
72
|
+
registered_at INTEGER NOT NULL,
|
|
73
|
+
seen_at INTEGER NOT NULL, -- most recent time the engine opened it (G16)
|
|
74
|
+
retired_at INTEGER, retired_reason TEXT,
|
|
75
|
+
CHECK(state<>'retired' OR retired_at IS NOT NULL)) STRICT;
|
|
76
|
+
|
|
77
|
+
CREATE TABLE IF NOT EXISTS repositories(
|
|
78
|
+
repo_root TEXT PRIMARY KEY,
|
|
79
|
+
name TEXT NOT NULL,
|
|
80
|
+
role TEXT NOT NULL CHECK(role IN ('backend','frontend','service','runtime')),
|
|
81
|
+
ledger_id TEXT REFERENCES ledgers(ledger_id),
|
|
82
|
+
default_branch TEXT, remote TEXT,
|
|
83
|
+
seen_at INTEGER NOT NULL) STRICT;
|
|
84
|
+
|
|
85
|
+
-- agents / models: PROJECTION of modules/models/*.yaml (YAML stays the contract), rewritten on each engine boot.
|
|
86
|
+
CREATE TABLE IF NOT EXISTS agents(
|
|
87
|
+
agent TEXT PRIMARY KEY CHECK(agent IN ('devin','codex','claude')),
|
|
88
|
+
provider TEXT, spawn_card TEXT, cli_name TEXT,
|
|
89
|
+
source_rev TEXT NOT NULL, loaded_at INTEGER NOT NULL) STRICT;
|
|
90
|
+
CREATE TABLE IF NOT EXISTS models(
|
|
91
|
+
profile TEXT PRIMARY KEY,
|
|
92
|
+
agent TEXT REFERENCES agents(agent),
|
|
93
|
+
model TEXT, pool TEXT, max_parallel INTEGER, share_pct REAL,
|
|
94
|
+
roles_json TEXT CHECK(roles_json IS NULL OR json_valid(roles_json)),
|
|
95
|
+
cost_json TEXT CHECK(cost_json IS NULL OR json_valid(cost_json)),
|
|
96
|
+
source_rev TEXT NOT NULL, loaded_at INTEGER NOT NULL) STRICT;
|
|
97
|
+
|
|
98
|
+
CREATE TABLE IF NOT EXISTS blobs(
|
|
99
|
+
sha256 TEXT PRIMARY KEY CHECK(length(sha256)=64), bytes INTEGER NOT NULL CHECK(bytes>=0), media_type TEXT NOT NULL,
|
|
100
|
+
encoding TEXT CHECK(encoding IS NULL OR encoding='gzip'), redaction TEXT CHECK(redaction IS NULL OR redaction IN ('v1','binary')),
|
|
101
|
+
file_uri TEXT NOT NULL, http_path TEXT GENERATED ALWAYS AS ('/api/blob/' || sha256) VIRTUAL,
|
|
102
|
+
created_at INTEGER NOT NULL, pinned INTEGER NOT NULL DEFAULT 0 CHECK(pinned IN (0,1)),
|
|
103
|
+
archived_at INTEGER, archive_ref TEXT) STRICT;
|
|
104
|
+
|
|
105
|
+
-- archives: every verified zip/copy in the starci-archive store (purge, DB backup, blob retention, lane logs).
|
|
106
|
+
CREATE TABLE IF NOT EXISTS archives(
|
|
107
|
+
archive_path TEXT PRIMARY KEY,
|
|
108
|
+
kind TEXT NOT NULL CHECK(kind IN ('workflow-purge','db-backup','blob-retention','lane-logs','agent-sessions')),
|
|
109
|
+
subject TEXT,
|
|
110
|
+
bytes INTEGER NOT NULL, sha256 TEXT NOT NULL, manifest_sha256 TEXT, entries INTEGER,
|
|
111
|
+
integrity TEXT, -- 'ok' from integrity_check (db-backup) / 'sha-verified' (zip)
|
|
112
|
+
created_at INTEGER NOT NULL, verified_at INTEGER, expires_at INTEGER) STRICT;
|
|
113
|
+
|
|
114
|
+
-- gc_marks: the set of live sha values; GC marks PER ledger (opens each read-only in turn, reads that ledger's
|
|
115
|
+
-- blob_ref_columns) then machine; sweep deletes a file only when: absent from the run's gc_marks, pinned=0 in
|
|
116
|
+
-- every DB, archived_at IS NOT NULL, created_at < now-24h. No ATTACH-UNION (10-DB limit).
|
|
117
|
+
CREATE TABLE IF NOT EXISTS gc_marks(
|
|
118
|
+
run_id INTEGER NOT NULL REFERENCES gc_runs(run_id) ON DELETE CASCADE,
|
|
119
|
+
sha256 TEXT NOT NULL,
|
|
120
|
+
source TEXT NOT NULL, -- ledger name | 'machine'
|
|
121
|
+
pinned INTEGER NOT NULL DEFAULT 0 CHECK(pinned IN (0,1)),
|
|
122
|
+
PRIMARY KEY(run_id,sha256,source)) STRICT, WITHOUT ROWID;
|
|
123
|
+
|
|
124
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
125
|
+
-- B1. Supervisor (own tables prefixed sup_; seats in `seats`, log in `machine_logs`, cost in `llm_usage`)
|
|
126
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
127
|
+
CREATE TABLE IF NOT EXISTS sup_jobs(
|
|
128
|
+
job_id TEXT PRIMARY KEY,
|
|
129
|
+
trace_id TEXT NOT NULL CHECK(length(trace_id)=32),
|
|
130
|
+
kind TEXT NOT NULL, -- runtime.fix | runtime.review | ...
|
|
131
|
+
role TEXT NOT NULL CHECK(role IN ('worker','supervisor')),
|
|
132
|
+
cluster TEXT,
|
|
133
|
+
title TEXT NOT NULL,
|
|
134
|
+
status TEXT NOT NULL CHECK(status IN ('queued','spawning','running','reported','landing','succeeded','failed','cancelled')),
|
|
135
|
+
lane TEXT,
|
|
136
|
+
files_json TEXT CHECK(files_json IS NULL OR json_valid(files_json)), -- .claude paths the job may edit
|
|
137
|
+
brief TEXT,
|
|
138
|
+
payload_json TEXT CHECK(payload_json IS NULL OR json_valid(payload_json)),
|
|
139
|
+
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL) STRICT;
|
|
140
|
+
CREATE INDEX IF NOT EXISTS ix_sup_jobs_status ON sup_jobs(status,created_at);
|
|
141
|
+
|
|
142
|
+
CREATE TABLE IF NOT EXISTS sup_leases(
|
|
143
|
+
path TEXT PRIMARY KEY,
|
|
144
|
+
job_id TEXT NOT NULL REFERENCES sup_jobs(job_id) ON DELETE CASCADE,
|
|
145
|
+
acquired_at INTEGER NOT NULL, expires_at INTEGER NOT NULL) STRICT;
|
|
146
|
+
|
|
147
|
+
-- sup_attempts: same column groups as op_attempts (who, where, when, outcome, replay) so they do not drift apart.
|
|
148
|
+
CREATE TABLE IF NOT EXISTS sup_attempts(
|
|
149
|
+
attempt_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
150
|
+
job_id TEXT NOT NULL REFERENCES sup_jobs(job_id) ON DELETE CASCADE,
|
|
151
|
+
dispatch_seq INTEGER NOT NULL DEFAULT 1,
|
|
152
|
+
span_id TEXT NOT NULL CHECK(length(span_id)=16), parent_span_id TEXT,
|
|
153
|
+
agent TEXT CHECK(agent IS NULL OR agent IN ('devin','codex','claude')),
|
|
154
|
+
provider TEXT, model TEXT, effort TEXT, terminal_handle TEXT, worker_pid INTEGER,
|
|
155
|
+
runtime_rev TEXT, cli_name TEXT, cli_version TEXT,
|
|
156
|
+
prompt_sha TEXT REFERENCES blobs(sha256), transcript_sha TEXT REFERENCES blobs(sha256),
|
|
157
|
+
worktree_path TEXT, branch TEXT, base_sha TEXT, head_sha TEXT, landed_sha TEXT,
|
|
158
|
+
spawned_at INTEGER, reported_at INTEGER, acked_at INTEGER, landed_at INTEGER, cancelled_at INTEGER, closed_at INTEGER,
|
|
159
|
+
report_outcome TEXT, verdict TEXT, failure_class TEXT,
|
|
160
|
+
tokens_in INTEGER, tokens_out INTEGER, cost_usd REAL,
|
|
161
|
+
UNIQUE(job_id,dispatch_seq)) STRICT;
|
|
162
|
+
|
|
163
|
+
CREATE TABLE IF NOT EXISTS sup_reports(
|
|
164
|
+
report_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
165
|
+
attempt_id INTEGER NOT NULL UNIQUE REFERENCES sup_attempts(attempt_id) ON DELETE CASCADE,
|
|
166
|
+
job_id TEXT NOT NULL,
|
|
167
|
+
outcome TEXT NOT NULL,
|
|
168
|
+
report_json TEXT NOT NULL CHECK(json_valid(report_json)),
|
|
169
|
+
summary TEXT GENERATED ALWAYS AS (json_extract(report_json,'$.summary')) VIRTUAL,
|
|
170
|
+
report_sha TEXT REFERENCES blobs(sha256), -- <lane>.REPORT.md
|
|
171
|
+
consumed_at INTEGER, created_at INTEGER NOT NULL) STRICT;
|
|
172
|
+
|
|
173
|
+
-- sup_events: Supervisor audit journal; digest computed in the JS writer like events.
|
|
174
|
+
CREATE TABLE IF NOT EXISTS sup_events(
|
|
175
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
176
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
177
|
+
entity_type TEXT NOT NULL, entity_id TEXT NOT NULL, kind TEXT NOT NULL, span_id TEXT,
|
|
178
|
+
payload_json TEXT CHECK(payload_json IS NULL OR (json_valid(payload_json) AND length(payload_json)<=16384)),
|
|
179
|
+
payload_sha TEXT REFERENCES blobs(sha256),
|
|
180
|
+
prev_digest TEXT, digest TEXT NOT NULL CHECK(length(digest)=64), created_at INTEGER NOT NULL) STRICT;
|
|
181
|
+
CREATE INDEX IF NOT EXISTS ix_sup_events_kind ON sup_events(kind,seq);
|
|
182
|
+
CREATE INDEX IF NOT EXISTS ix_sup_events_entity ON sup_events(entity_type,entity_id,seq);
|
|
183
|
+
CREATE TRIGGER IF NOT EXISTS sup_events_append_only BEFORE UPDATE ON sup_events BEGIN
|
|
184
|
+
SELECT RAISE(ABORT,'sup_events are append-only');
|
|
185
|
+
END;
|
|
186
|
+
|
|
187
|
+
CREATE TABLE IF NOT EXISTS sup_decision_items(
|
|
188
|
+
di_id TEXT PRIMARY KEY,
|
|
189
|
+
-- MB-07: '<kind>:<entity>:<error signature>:<head>' - no empty part (a head-less push-refused merged 73 times into an old DI).
|
|
190
|
+
idempotency_key TEXT NOT NULL UNIQUE CHECK(idempotency_key NOT LIKE '%::%' AND idempotency_key NOT LIKE '%:'
|
|
191
|
+
AND idempotency_key NOT LIKE ':%' AND length(idempotency_key)>=5),
|
|
192
|
+
key_parts_json TEXT NOT NULL CHECK(json_valid(key_parts_json) AND json_type(key_parts_json)='object'),
|
|
193
|
+
superseded_by TEXT REFERENCES sup_decision_items(di_id),
|
|
194
|
+
delivered_at INTEGER, -- MB-02: whether it reached the Supervisor seat yet (detail in deliveries)
|
|
195
|
+
ledger_id TEXT REFERENCES ledgers(ledger_id),
|
|
196
|
+
workflow_id TEXT,
|
|
197
|
+
kind TEXT NOT NULL, -- cap-starved | quota-exhausted | runtime-defect | cross-workflow | deadlock | ...
|
|
198
|
+
decider TEXT NOT NULL CHECK(decider IN ('supervisor','owner')),
|
|
199
|
+
entity_type TEXT, entity_id TEXT,
|
|
200
|
+
summary TEXT NOT NULL,
|
|
201
|
+
status TEXT NOT NULL CHECK(status IN ('open','claimed','resolved','escalated','expired','superseded')),
|
|
202
|
+
opened_by TEXT NOT NULL, opened_at INTEGER NOT NULL, due_at INTEGER,
|
|
203
|
+
escalate_to TEXT, escalations INTEGER NOT NULL DEFAULT 0,
|
|
204
|
+
claim_by TEXT, claim_at INTEGER, claim_ttl_ms INTEGER,
|
|
205
|
+
resolved_by TEXT, resolved_at INTEGER, resolution_verb TEXT, decision_id TEXT,
|
|
206
|
+
evidence_json TEXT CHECK(evidence_json IS NULL OR json_valid(evidence_json)),
|
|
207
|
+
options_json TEXT CHECK(options_json IS NULL OR json_valid(options_json)),
|
|
208
|
+
allowed_verbs_json TEXT CHECK(allowed_verbs_json IS NULL OR json_valid(allowed_verbs_json)),
|
|
209
|
+
payload_json TEXT NOT NULL CHECK(json_valid(payload_json))) STRICT;
|
|
210
|
+
CREATE INDEX IF NOT EXISTS ix_sup_di_open ON sup_decision_items(status,due_at);
|
|
211
|
+
|
|
212
|
+
CREATE TABLE IF NOT EXISTS sup_decisions(
|
|
213
|
+
decision_id TEXT PRIMARY KEY, di_id TEXT REFERENCES sup_decision_items(di_id), decider TEXT NOT NULL,
|
|
214
|
+
span_id TEXT NOT NULL CHECK(length(span_id)=16), parent_span_id TEXT,
|
|
215
|
+
ledger_id TEXT, workflow_id TEXT, subject_type TEXT, subject_id TEXT,
|
|
216
|
+
choice TEXT NOT NULL, rationale TEXT, result_json TEXT CHECK(result_json IS NULL OR json_valid(result_json)),
|
|
217
|
+
decided_at INTEGER NOT NULL) STRICT;
|
|
218
|
+
|
|
219
|
+
CREATE TABLE IF NOT EXISTS sup_owed(
|
|
220
|
+
owed_id TEXT PRIMARY KEY,
|
|
221
|
+
kind TEXT NOT NULL, subject TEXT NOT NULL, cluster TEXT,
|
|
222
|
+
state TEXT NOT NULL CHECK(state IN ('open','acked','closed')),
|
|
223
|
+
opened_at INTEGER NOT NULL, due_at INTEGER, acked_at INTEGER, acked_by TEXT, closed_at INTEGER,
|
|
224
|
+
detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json))) STRICT;
|
|
225
|
+
CREATE INDEX IF NOT EXISTS ix_sup_owed_open ON sup_owed(state,due_at);
|
|
226
|
+
|
|
227
|
+
CREATE TABLE IF NOT EXISTS sup_learning(
|
|
228
|
+
item_id TEXT PRIMARY KEY,
|
|
229
|
+
kind TEXT NOT NULL CHECK(kind IN ('lesson','hypothesis','experiment','experiment-result','proposal','owner-feedback','leftover')),
|
|
230
|
+
parent_id TEXT REFERENCES sup_learning(item_id),
|
|
231
|
+
title TEXT NOT NULL, state TEXT, source_ref TEXT, lane TEXT, landed_sha TEXT,
|
|
232
|
+
detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json)),
|
|
233
|
+
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL) STRICT;
|
|
234
|
+
|
|
235
|
+
CREATE TABLE IF NOT EXISTS sup_owner_rulings(
|
|
236
|
+
ruling_id TEXT PRIMARY KEY, said_at INTEGER NOT NULL, channel TEXT, verbatim TEXT NOT NULL, paraphrase TEXT,
|
|
237
|
+
applies_to TEXT, contract_ref TEXT, recorded_by TEXT, created_at INTEGER NOT NULL) STRICT;
|
|
238
|
+
|
|
239
|
+
CREATE TABLE IF NOT EXISTS sup_bridges(
|
|
240
|
+
bridge_id TEXT PRIMARY KEY, ledger_id TEXT REFERENCES ledgers(ledger_id),
|
|
241
|
+
action TEXT NOT NULL CHECK(action IN ('bridge','transfer','rewire')),
|
|
242
|
+
state TEXT NOT NULL, approved_by TEXT, detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json)),
|
|
243
|
+
created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL) STRICT;
|
|
244
|
+
|
|
245
|
+
CREATE TABLE IF NOT EXISTS sup_messages(
|
|
246
|
+
msg_id TEXT PRIMARY KEY,
|
|
247
|
+
direction TEXT NOT NULL CHECK(direction IN ('in','out')),
|
|
248
|
+
channel TEXT NOT NULL CHECK(channel IN ('telegram','tell','ask-gateway')),
|
|
249
|
+
chat_id TEXT, message_id TEXT, from_ref TEXT, to_ref TEXT, via TEXT,
|
|
250
|
+
text TEXT NOT NULL,
|
|
251
|
+
ok INTEGER CHECK(ok IS NULL OR ok IN (0,1)),
|
|
252
|
+
read_at INTEGER, at INTEGER NOT NULL) STRICT;
|
|
253
|
+
CREATE INDEX IF NOT EXISTS ix_sup_messages_unread ON sup_messages(direction,read_at,at);
|
|
254
|
+
|
|
255
|
+
CREATE TABLE IF NOT EXISTS sup_signals(
|
|
256
|
+
scope TEXT NOT NULL CHECK(scope IN ('supervisor-enabled','supervisor-busy','core-debug-enabled','core-debug-diagnostics')), key TEXT NOT NULL,
|
|
257
|
+
holder_pid INTEGER, token TEXT, value_json TEXT CHECK(value_json IS NULL OR json_valid(value_json)),
|
|
258
|
+
at INTEGER NOT NULL, expires_at INTEGER, PRIMARY KEY(scope,key)) STRICT;
|
|
259
|
+
|
|
260
|
+
-- llm_usage (machine): cost of Supervisor and [Worker].
|
|
261
|
+
CREATE TABLE IF NOT EXISTS llm_usage(
|
|
262
|
+
usage_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
263
|
+
subject_type TEXT NOT NULL CHECK(subject_type IN ('supervisor-turn','worker-attempt')),
|
|
264
|
+
sup_attempt_id INTEGER REFERENCES sup_attempts(attempt_id) ON DELETE CASCADE,
|
|
265
|
+
turn_ref TEXT, span_id TEXT,
|
|
266
|
+
provider TEXT NOT NULL, request_model TEXT, response_model TEXT,
|
|
267
|
+
input_tokens INTEGER, output_tokens INTEGER, cache_read_tokens INTEGER, cache_write_tokens INTEGER, reasoning_tokens INTEGER,
|
|
268
|
+
cost_usd REAL, turns INTEGER, tool_calls INTEGER, tool_errors INTEGER,
|
|
269
|
+
source TEXT NOT NULL CHECK(source IN ('cli-transcript','provider-report')),
|
|
270
|
+
at INTEGER NOT NULL,
|
|
271
|
+
CHECK((subject_type='worker-attempt' AND sup_attempt_id IS NOT NULL) OR (subject_type='supervisor-turn' AND turn_ref IS NOT NULL))) STRICT;
|
|
272
|
+
CREATE INDEX IF NOT EXISTS ix_musage ON llm_usage(subject_type,at);
|
|
273
|
+
|
|
274
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
275
|
+
-- B2. Reconciler engine (replaces reconciler.sqlite, reconciler-starts.json, reconciler.heartbeat)
|
|
276
|
+
-- Principle (LOG-AUDIT-MACHINE sec. 5): everything with a duration is APPEND-ONLY history; "current state" is a view
|
|
277
|
+
-- or one thin row. No DELETE, no rewriting history. Every action has an id; every consequence references that id.
|
|
278
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
279
|
+
-- process_runs (G1, MB-04): EVERY long-lived runtime process (engine, harness, gateway, tunnel, telegram-bridge,
|
|
280
|
+
-- settler, push-mains, land) one row: why it spawned, why it died, who killed it, last heartbeat before death.
|
|
281
|
+
CREATE TABLE IF NOT EXISTS process_runs(
|
|
282
|
+
run_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
283
|
+
role TEXT NOT NULL CHECK(role IN ('engine','harness','gateway','tunnel','telegram-bridge','settler','push','land','boot','other')),
|
|
284
|
+
pid INTEGER NOT NULL, host TEXT, rev TEXT, epoch INTEGER,
|
|
285
|
+
parent_action_id TEXT, -- engine_actions.id that spawned it (if any)
|
|
286
|
+
start_reason TEXT NOT NULL CHECK(start_reason IN ('boot','ensure-stale-heartbeat','self-reload','crash-restart','manual','scheduled','action')),
|
|
287
|
+
started_at INTEGER NOT NULL,
|
|
288
|
+
last_heartbeat_at INTEGER,
|
|
289
|
+
draining_since INTEGER, -- MB-04: handing over; ensure must NOT kill a draining process
|
|
290
|
+
ended_at INTEGER,
|
|
291
|
+
exit_code INTEGER,
|
|
292
|
+
exit_reason TEXT CHECK(exit_reason IS NULL OR exit_reason IN ('clean','reload-handover','crash','killed','lost-lease','stopped','unknown')),
|
|
293
|
+
killed_by TEXT, -- 'boot-ensure' | 'supervisor' | 'owner' | pid:<n>
|
|
294
|
+
heartbeat_age_at_end_ms INTEGER,
|
|
295
|
+
CHECK(ended_at IS NULL OR exit_reason IS NOT NULL)) STRICT;
|
|
296
|
+
CREATE INDEX IF NOT EXISTS ix_process_runs ON process_runs(role,started_at);
|
|
297
|
+
-- End fields may be filled only once (append-only in meaning).
|
|
298
|
+
CREATE TRIGGER IF NOT EXISTS process_runs_end_once BEFORE UPDATE OF ended_at, exit_reason, killed_by ON process_runs
|
|
299
|
+
WHEN OLD.ended_at IS NOT NULL BEGIN
|
|
300
|
+
SELECT RAISE(ABORT,'process run already ended');
|
|
301
|
+
END;
|
|
302
|
+
CREATE TRIGGER IF NOT EXISTS process_runs_no_delete BEFORE DELETE ON process_runs
|
|
303
|
+
WHEN OLD.started_at > CAST(unixepoch('subsec')*1000 AS INTEGER) - 7776000000 BEGIN -- only GC deletes rows older than 90 days
|
|
304
|
+
SELECT RAISE(ABORT,'process_runs are append-only (90-day retention)');
|
|
305
|
+
END;
|
|
306
|
+
-- UI-API compatibility (/api/reconciler starts24h): engine starts = view.
|
|
307
|
+
CREATE VIEW IF NOT EXISTS v_engine_starts AS
|
|
308
|
+
SELECT run_id, started_at AS at, pid, rev, epoch, start_reason AS reason, ended_at, exit_reason, killed_by
|
|
309
|
+
FROM process_runs WHERE role='engine';
|
|
310
|
+
|
|
311
|
+
-- engine_leader: one current row (fence). History in leader_history.
|
|
312
|
+
CREATE TABLE IF NOT EXISTS engine_leader(
|
|
313
|
+
name TEXT PRIMARY KEY, holder TEXT NOT NULL, pid INTEGER NOT NULL, epoch INTEGER NOT NULL,
|
|
314
|
+
process_run_id INTEGER REFERENCES process_runs(run_id),
|
|
315
|
+
heartbeat_at INTEGER NOT NULL, expires_at INTEGER NOT NULL, rev TEXT,
|
|
316
|
+
draining INTEGER NOT NULL DEFAULT 0 CHECK(draining IN (0,1)), -- MB-04: the lease still renews on its own timer while draining
|
|
317
|
+
passes INTEGER, last_pass_ms INTEGER, last_error TEXT) STRICT;
|
|
318
|
+
-- leader_history (G2): one row per epoch; how long the lead was held, why released.
|
|
319
|
+
CREATE TABLE IF NOT EXISTS leader_history(
|
|
320
|
+
epoch INTEGER PRIMARY KEY,
|
|
321
|
+
holder TEXT NOT NULL, pid INTEGER NOT NULL, process_run_id INTEGER REFERENCES process_runs(run_id), rev TEXT,
|
|
322
|
+
acquired_at INTEGER NOT NULL,
|
|
323
|
+
acquired_how TEXT NOT NULL CHECK(acquired_how IN ('fresh','takeover-stale','handover')),
|
|
324
|
+
released_at INTEGER,
|
|
325
|
+
release_reason TEXT CHECK(release_reason IS NULL OR release_reason IN ('reload','lost','killed','stop','crash'))) STRICT;
|
|
326
|
+
CREATE TRIGGER IF NOT EXISTS leader_history_release_once BEFORE UPDATE ON leader_history
|
|
327
|
+
WHEN OLD.released_at IS NOT NULL OR NEW.epoch<>OLD.epoch OR NEW.acquired_at<>OLD.acquired_at BEGIN
|
|
328
|
+
SELECT RAISE(ABORT,'leader_history is append-only');
|
|
329
|
+
END;
|
|
330
|
+
CREATE TRIGGER IF NOT EXISTS leader_history_no_delete BEFORE DELETE ON leader_history BEGIN
|
|
331
|
+
SELECT RAISE(ABORT,'leader_history is append-only');
|
|
332
|
+
END;
|
|
333
|
+
|
|
334
|
+
CREATE TABLE IF NOT EXISTS engine_cursors(
|
|
335
|
+
ledger_id TEXT PRIMARY KEY REFERENCES ledgers(ledger_id), last_seq INTEGER NOT NULL, updated_at INTEGER NOT NULL) STRICT;
|
|
336
|
+
CREATE TABLE IF NOT EXISTS engine_queue(
|
|
337
|
+
controller TEXT NOT NULL, key TEXT NOT NULL, due_at INTEGER, reason TEXT, tries INTEGER NOT NULL DEFAULT 0,
|
|
338
|
+
last_error TEXT, PRIMARY KEY(controller,key)) STRICT;
|
|
339
|
+
|
|
340
|
+
-- schedules (MB-01): the timetable of every periodic duty lives in the DB, NOT in RAM - a fresh engine rereads it,
|
|
341
|
+
-- no repeated "first run" (housekeeping once/day once ran 32 times in 3.5 hours).
|
|
342
|
+
CREATE TABLE IF NOT EXISTS schedules(
|
|
343
|
+
controller TEXT NOT NULL CHECK(controller IN ('job','workflow','resource','host','gc','workers','learning','sla')),
|
|
344
|
+
duty TEXT NOT NULL, -- housekeeping, sweep, push, digest, backup, blob-sweep, transcripts, boot ...
|
|
345
|
+
interval_ms INTEGER NOT NULL CHECK(interval_ms>0),
|
|
346
|
+
last_started_at INTEGER, last_finished_at INTEGER,
|
|
347
|
+
last_result TEXT CHECK(last_result IS NULL OR last_result IN ('done','failed','unknown','skipped')),
|
|
348
|
+
last_action_id TEXT, -- engine_actions.id
|
|
349
|
+
last_result_digest TEXT,
|
|
350
|
+
next_due_at INTEGER NOT NULL,
|
|
351
|
+
running_pid INTEGER, -- a run currently in flight (no overlap)
|
|
352
|
+
PRIMARY KEY(controller,duty)) STRICT;
|
|
353
|
+
|
|
354
|
+
-- engine_actions (MB-03): result is NOT truncated at 4000 chars - result_json is only a small structured summary;
|
|
355
|
+
-- the full result, stdout and stderr of the child verb are blobs. id is DETERMINISTIC = sha(controller, key, verb, epoch, observed_generation).
|
|
356
|
+
CREATE TABLE IF NOT EXISTS engine_actions(
|
|
357
|
+
id TEXT PRIMARY KEY,
|
|
358
|
+
controller TEXT NOT NULL CHECK(controller IN ('job','workflow','resource','host','gc','workers','learning','sla')),
|
|
359
|
+
duty TEXT, -- schedules.duty when the action is a periodic run
|
|
360
|
+
key TEXT, verb TEXT, argv_digest TEXT, epoch INTEGER, observed_generation INTEGER,
|
|
361
|
+
span_id TEXT CHECK(span_id IS NULL OR length(span_id)=16), trace_id TEXT,
|
|
362
|
+
state TEXT NOT NULL CHECK(state IN ('intent','running','done','failed','unknown','fenced')),
|
|
363
|
+
mode TEXT CHECK(mode IS NULL OR mode IN ('shadow','active')),
|
|
364
|
+
ledger_id TEXT, workflow_id TEXT, job_id TEXT, attempt_id INTEGER,
|
|
365
|
+
request_id TEXT, -- api_requests.request_id of the child verb
|
|
366
|
+
child_run_id INTEGER REFERENCES process_runs(run_id),
|
|
367
|
+
started_at INTEGER, finished_at INTEGER, exit_code INTEGER,
|
|
368
|
+
result_json TEXT CHECK(result_json IS NULL OR (json_valid(result_json) AND length(result_json)<=8192)),
|
|
369
|
+
result_sha TEXT REFERENCES blobs(sha256), -- full result
|
|
370
|
+
stdout_sha TEXT REFERENCES blobs(sha256),
|
|
371
|
+
stderr_sha TEXT REFERENCES blobs(sha256), -- FULL stderr (today it is cut to 6 lines)
|
|
372
|
+
error_signature TEXT) STRICT; -- stable error signature (no HEAD) for grouping/recurrence
|
|
373
|
+
CREATE INDEX IF NOT EXISTS ix_engine_actions_ctl ON engine_actions(controller,started_at);
|
|
374
|
+
CREATE INDEX IF NOT EXISTS ix_engine_actions_entity ON engine_actions(ledger_id,workflow_id,job_id);
|
|
375
|
+
CREATE INDEX IF NOT EXISTS ix_engine_actions_sig ON engine_actions(controller,error_signature);
|
|
376
|
+
-- action_steps (G13): a step inside a long action.
|
|
377
|
+
CREATE TABLE IF NOT EXISTS action_steps(
|
|
378
|
+
action_id TEXT NOT NULL REFERENCES engine_actions(id) ON DELETE CASCADE,
|
|
379
|
+
step_no INTEGER NOT NULL, step TEXT NOT NULL, started_at INTEGER NOT NULL, ms INTEGER,
|
|
380
|
+
ok INTEGER CHECK(ok IS NULL OR ok IN (0,1)), detail TEXT,
|
|
381
|
+
PRIMARY KEY(action_id,step_no)) STRICT;
|
|
382
|
+
|
|
383
|
+
-- controller_modes: current mode; mode_changes (G6): append-only history, who changed it and why.
|
|
384
|
+
CREATE TABLE IF NOT EXISTS controller_modes(
|
|
385
|
+
controller TEXT PRIMARY KEY CHECK(controller IN ('job','workflow','resource','host','gc','workers','learning')),
|
|
386
|
+
mode TEXT NOT NULL CHECK(mode IN ('off','shadow','active')), set_at INTEGER, set_by TEXT) STRICT;
|
|
387
|
+
CREATE TABLE IF NOT EXISTS mode_changes(
|
|
388
|
+
change_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
389
|
+
controller TEXT NOT NULL, from_mode TEXT, to_mode TEXT NOT NULL CHECK(to_mode IN ('off','shadow','active')),
|
|
390
|
+
by TEXT NOT NULL, reason TEXT NOT NULL, at INTEGER NOT NULL) STRICT;
|
|
391
|
+
CREATE TRIGGER IF NOT EXISTS mode_changes_append_only BEFORE UPDATE ON mode_changes BEGIN
|
|
392
|
+
SELECT RAISE(ABORT,'mode_changes are append-only');
|
|
393
|
+
END;
|
|
394
|
+
CREATE TRIGGER IF NOT EXISTS controller_modes_recorded BEFORE UPDATE OF mode ON controller_modes
|
|
395
|
+
WHEN NEW.mode<>OLD.mode AND NOT EXISTS(SELECT 1 FROM mode_changes c WHERE c.controller=NEW.controller AND c.to_mode=NEW.mode
|
|
396
|
+
AND c.change_id=(SELECT max(change_id) FROM mode_changes WHERE controller=NEW.controller)) BEGIN
|
|
397
|
+
SELECT RAISE(ABORT,'mode change must be recorded in mode_changes first');
|
|
398
|
+
END;
|
|
399
|
+
|
|
400
|
+
-- sla_episodes (G3): EVERY SLA clock episode one row, APPEND-ONLY. No DELETE, no overwrite: violated_at,
|
|
401
|
+
-- reported_at, cleared_at (+ clear_reason) are each filled exactly once. Open clocks = v_sla_open.
|
|
402
|
+
CREATE TABLE IF NOT EXISTS sla_episodes(
|
|
403
|
+
episode_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
404
|
+
entity TEXT NOT NULL, state TEXT NOT NULL, code TEXT NOT NULL, -- READY_UNDISPATCHED, WORKER_SILENT, SEAT_DEAF, TRANSCRIPT_MISSING ...
|
|
405
|
+
severity TEXT NOT NULL CHECK(severity IN ('warn','critical')),
|
|
406
|
+
ledger_id TEXT, workflow_id TEXT,
|
|
407
|
+
entered_at INTEGER NOT NULL, sla_ms INTEGER NOT NULL,
|
|
408
|
+
violated_at INTEGER, reported_at INTEGER, di_id TEXT,
|
|
409
|
+
cleared_at INTEGER,
|
|
410
|
+
clear_reason TEXT CHECK(clear_reason IS NULL OR clear_reason IN ('resolved','superseded','entity-gone','workflow-stopped')),
|
|
411
|
+
CHECK(cleared_at IS NULL OR clear_reason IS NOT NULL)) STRICT;
|
|
412
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ux_sla_open ON sla_episodes(entity,state) WHERE cleared_at IS NULL; -- one open episode per (entity,state)
|
|
413
|
+
CREATE INDEX IF NOT EXISTS ix_sla_code ON sla_episodes(code,entered_at);
|
|
414
|
+
CREATE TRIGGER IF NOT EXISTS sla_episodes_fill_once BEFORE UPDATE ON sla_episodes
|
|
415
|
+
WHEN NEW.entity<>OLD.entity OR NEW.state<>OLD.state OR NEW.code<>OLD.code OR NEW.entered_at<>OLD.entered_at
|
|
416
|
+
OR (OLD.violated_at IS NOT NULL AND NEW.violated_at IS NOT OLD.violated_at)
|
|
417
|
+
OR (OLD.reported_at IS NOT NULL AND NEW.reported_at IS NOT OLD.reported_at)
|
|
418
|
+
OR (OLD.cleared_at IS NOT NULL AND NEW.cleared_at IS NOT OLD.cleared_at) BEGIN
|
|
419
|
+
SELECT RAISE(ABORT,'sla_episodes are append-only: fields fill once');
|
|
420
|
+
END;
|
|
421
|
+
CREATE TRIGGER IF NOT EXISTS sla_episodes_no_delete BEFORE DELETE ON sla_episodes BEGIN
|
|
422
|
+
SELECT RAISE(ABORT,'sla_episodes are append-only');
|
|
423
|
+
END;
|
|
424
|
+
|
|
425
|
+
CREATE TABLE IF NOT EXISTS invariant_violations(
|
|
426
|
+
violation_id INTEGER PRIMARY KEY AUTOINCREMENT, code TEXT NOT NULL,
|
|
427
|
+
severity TEXT NOT NULL CHECK(severity IN ('warn','critical')),
|
|
428
|
+
entity TEXT NOT NULL, ledger_id TEXT, workflow_id TEXT, episode_id INTEGER REFERENCES sla_episodes(episode_id),
|
|
429
|
+
violated_at INTEGER NOT NULL, cleared_at INTEGER, di_id TEXT, lesson_id TEXT,
|
|
430
|
+
detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json))) STRICT;
|
|
431
|
+
CREATE INDEX IF NOT EXISTS ix_inv_open ON invariant_violations(cleared_at,code);
|
|
432
|
+
|
|
433
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
434
|
+
-- B3. Machine: services, seats, terminals, deliveries, turns, locks, claims, agent sessions
|
|
435
|
+
-- Ownership rule (no cross-DB transaction): machine resources (terminals, worktrees, locks) are owned by machine;
|
|
436
|
+
-- op_attempts only POINTS to them (terminal_handle, worktree_path). Resource ctrl/GC reconcile drift both ways.
|
|
437
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
438
|
+
CREATE TABLE IF NOT EXISTS services(
|
|
439
|
+
name TEXT PRIMARY KEY,
|
|
440
|
+
kind TEXT NOT NULL CHECK(kind IN ('host-app','http','tunnel','connector','scheduled-task','ledger')),
|
|
441
|
+
state TEXT NOT NULL CHECK(state IN ('healthy','ok','degraded','down','quarantined','restarting','booting','stale')),
|
|
442
|
+
since INTEGER, pid INTEGER, port INTEGER, url TEXT,
|
|
443
|
+
last_probe_json TEXT CHECK(last_probe_json IS NULL OR json_valid(last_probe_json)),
|
|
444
|
+
quarantined_until INTEGER) STRICT;
|
|
445
|
+
CREATE TABLE IF NOT EXISTS service_probes(
|
|
446
|
+
probe_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL REFERENCES services(name) ON DELETE CASCADE,
|
|
447
|
+
at INTEGER NOT NULL, ok INTEGER NOT NULL CHECK(ok IN (0,1)), latency_ms INTEGER,
|
|
448
|
+
detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json))) STRICT; -- kept 14 days
|
|
449
|
+
CREATE INDEX IF NOT EXISTS ix_probes ON service_probes(name,at);
|
|
450
|
+
-- service_events (G5): every state change and every restart, append-only (replaces the windowed services.restarts_json).
|
|
451
|
+
CREATE TABLE IF NOT EXISTS service_events(
|
|
452
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL REFERENCES services(name) ON DELETE CASCADE,
|
|
453
|
+
at INTEGER NOT NULL, from_state TEXT, to_state TEXT NOT NULL,
|
|
454
|
+
probe_ms INTEGER, probe_error TEXT,
|
|
455
|
+
action TEXT CHECK(action IS NULL OR action IN ('restart','quarantine','release','none')), action_id TEXT) STRICT;
|
|
456
|
+
CREATE INDEX IF NOT EXISTS ix_service_events ON service_events(name,at);
|
|
457
|
+
CREATE TRIGGER IF NOT EXISTS service_events_append_only BEFORE UPDATE ON service_events BEGIN
|
|
458
|
+
SELECT RAISE(ABORT,'service_events are append-only');
|
|
459
|
+
END;
|
|
460
|
+
|
|
461
|
+
-- seats: long-lived LLM seats - ONE place. 'parked' = deliberately no Kernel (workflow paused/stopped): the
|
|
462
|
+
-- controller does NOT "fix" a parked seat (MB-08). Consecutive input failures counted per seat (MB-05); replace
|
|
463
|
+
-- the seat after K failures in T minutes (SLA SEAT_DEAF).
|
|
464
|
+
CREATE TABLE IF NOT EXISTS seats(
|
|
465
|
+
seat_id TEXT PRIMARY KEY, -- 'kernel:<ledger name>:<wf>' | 'supervisor'
|
|
466
|
+
role TEXT NOT NULL CHECK(role IN ('kernel','supervisor')),
|
|
467
|
+
ledger_id TEXT REFERENCES ledgers(ledger_id), workflow_id TEXT,
|
|
468
|
+
state TEXT NOT NULL CHECK(state IN ('empty','parked','booting','live','busy','stale','dead','replacing','quarantined')),
|
|
469
|
+
parked_reason TEXT,
|
|
470
|
+
terminal_handle TEXT, agent TEXT, model TEXT, routed_by TEXT, pid INTEGER,
|
|
471
|
+
kernel_rev TEXT, acked_rev TEXT,
|
|
472
|
+
booted_at INTEGER, last_seen_at INTEGER, replaced_count INTEGER NOT NULL DEFAULT 0,
|
|
473
|
+
input_failures_consecutive INTEGER NOT NULL DEFAULT 0, -- consecutive unwritable/exited/unavailable
|
|
474
|
+
input_failures_total INTEGER NOT NULL DEFAULT 0,
|
|
475
|
+
last_input_failure_at INTEGER, last_input_ok_at INTEGER,
|
|
476
|
+
detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json)),
|
|
477
|
+
CHECK(state<>'parked' OR parked_reason IS NOT NULL)) STRICT;
|
|
478
|
+
|
|
479
|
+
-- deliveries (G11, MB-02): EVERY message delivery to a seat (DI, inbox, doorbell, wake, telegram) and its outcome.
|
|
480
|
+
CREATE TABLE IF NOT EXISTS deliveries(
|
|
481
|
+
delivery_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
482
|
+
message_kind TEXT NOT NULL CHECK(message_kind IN ('decision','inbox','doorbell','wake','telegram','notice')),
|
|
483
|
+
message_ref TEXT NOT NULL, -- di_id | inbox_id | msg_id
|
|
484
|
+
ledger_id TEXT, seat_id TEXT REFERENCES seats(seat_id), terminal_handle TEXT,
|
|
485
|
+
channel TEXT NOT NULL,
|
|
486
|
+
attempted_at INTEGER NOT NULL,
|
|
487
|
+
outcome TEXT NOT NULL CHECK(outcome IN ('delivered','busy-deferred','unwritable','exited','unavailable','failed')),
|
|
488
|
+
turn_id INTEGER, -- seat_turns.turn_id the message opened
|
|
489
|
+
detail TEXT) STRICT;
|
|
490
|
+
CREATE INDEX IF NOT EXISTS ix_deliveries_seat ON deliveries(seat_id,attempted_at);
|
|
491
|
+
CREATE INDEX IF NOT EXISTS ix_deliveries_msg ON deliveries(message_kind,message_ref);
|
|
492
|
+
-- Per-seat input-failure counters live in the DB, maintained automatically on each delivery.
|
|
493
|
+
CREATE TRIGGER IF NOT EXISTS deliveries_count_seat_failures AFTER INSERT ON deliveries WHEN NEW.seat_id IS NOT NULL BEGIN
|
|
494
|
+
UPDATE seats SET
|
|
495
|
+
input_failures_consecutive = CASE WHEN NEW.outcome IN ('unwritable','exited','unavailable','failed')
|
|
496
|
+
THEN input_failures_consecutive+1 ELSE 0 END,
|
|
497
|
+
input_failures_total = input_failures_total + (NEW.outcome IN ('unwritable','exited','unavailable','failed')),
|
|
498
|
+
last_input_failure_at = CASE WHEN NEW.outcome IN ('unwritable','exited','unavailable','failed') THEN NEW.attempted_at ELSE last_input_failure_at END,
|
|
499
|
+
last_input_ok_at = CASE WHEN NEW.outcome='delivered' THEN NEW.attempted_at ELSE last_input_ok_at END
|
|
500
|
+
WHERE seat_id=NEW.seat_id;
|
|
501
|
+
END;
|
|
502
|
+
CREATE TRIGGER IF NOT EXISTS deliveries_append_only BEFORE UPDATE OF outcome, attempted_at, message_ref ON deliveries BEGIN
|
|
503
|
+
SELECT RAISE(ABORT,'deliveries are append-only');
|
|
504
|
+
END;
|
|
505
|
+
|
|
506
|
+
-- seat_turns (G12): each work turn of a seat: who woke it, how long it ran, why it ended.
|
|
507
|
+
CREATE TABLE IF NOT EXISTS seat_turns(
|
|
508
|
+
turn_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
509
|
+
seat_id TEXT NOT NULL REFERENCES seats(seat_id),
|
|
510
|
+
woken_by_delivery INTEGER REFERENCES deliveries(delivery_id),
|
|
511
|
+
started_at INTEGER NOT NULL, ended_at INTEGER,
|
|
512
|
+
end_reason TEXT CHECK(end_reason IS NULL OR end_reason IN ('idle','budget','interrupted','replaced','crashed')),
|
|
513
|
+
actions_count INTEGER NOT NULL DEFAULT 0,
|
|
514
|
+
span_id TEXT) STRICT;
|
|
515
|
+
CREATE INDEX IF NOT EXISTS ix_seat_turns ON seat_turns(seat_id,started_at);
|
|
516
|
+
|
|
517
|
+
-- seat_transcript_snapshots (UI-API sec. 2.10): periodic redacted scrollback snapshots of Kernel/Supervisor seats.
|
|
518
|
+
CREATE TABLE IF NOT EXISTS seat_transcript_snapshots(
|
|
519
|
+
snapshot_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
520
|
+
seat_id TEXT NOT NULL REFERENCES seats(seat_id),
|
|
521
|
+
terminal_handle TEXT,
|
|
522
|
+
at INTEGER NOT NULL, lines INTEGER NOT NULL, bytes INTEGER NOT NULL,
|
|
523
|
+
sha256 TEXT NOT NULL REFERENCES blobs(sha256),
|
|
524
|
+
UNIQUE(seat_id,sha256)) STRICT;
|
|
525
|
+
CREATE INDEX IF NOT EXISTS ix_seat_snap ON seat_transcript_snapshots(seat_id,at);
|
|
526
|
+
|
|
527
|
+
-- Worker accounting is Orca's (orchestration worker-list): which worker terminal is active, reclaimable or released, its
|
|
528
|
+
-- liveness and its next action are read from Orca, never from a runtime table. This table keeps only what Orca does not
|
|
529
|
+
-- account for: the GC's first sighting of a plain shell (role shell/other) and its verified close.
|
|
530
|
+
CREATE TABLE IF NOT EXISTS terminals(
|
|
531
|
+
handle TEXT PRIMARY KEY, title TEXT,
|
|
532
|
+
role TEXT NOT NULL CHECK(role IN ('shell','other')),
|
|
533
|
+
opened_at INTEGER, closed_at INTEGER, close_verified_at INTEGER, closed_by TEXT) STRICT;
|
|
534
|
+
CREATE INDEX IF NOT EXISTS ix_terminals_open ON terminals(closed_at,role);
|
|
535
|
+
|
|
536
|
+
CREATE TABLE IF NOT EXISTS host_locks(
|
|
537
|
+
name TEXT PRIMARY KEY, holder_pid INTEGER NOT NULL, holder TEXT, process_run_id INTEGER REFERENCES process_runs(run_id),
|
|
538
|
+
started_at INTEGER NOT NULL, heartbeat_at INTEGER NOT NULL, expires_at INTEGER NOT NULL,
|
|
539
|
+
handed_over_from INTEGER,
|
|
540
|
+
state TEXT NOT NULL DEFAULT 'held' CHECK(state IN ('starting','held','released'))) STRICT;
|
|
541
|
+
|
|
542
|
+
-- claims (G14, MB-04, MB-17): temporary resources (temp dirs, temp worktrees, lock files) are CLAIMED before
|
|
543
|
+
-- creation; GC removes them safely (safeRemove, never follows junctions) once the owner pid is dead.
|
|
544
|
+
CREATE TABLE IF NOT EXISTS claims(
|
|
545
|
+
claim_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
546
|
+
resource_path TEXT NOT NULL,
|
|
547
|
+
kind TEXT NOT NULL CHECK(kind IN ('temp-dir','worktree','lock-file','fixture','scratch')),
|
|
548
|
+
owner_action_id TEXT, owner_pid INTEGER NOT NULL, owner_run_id INTEGER REFERENCES process_runs(run_id),
|
|
549
|
+
has_junctions INTEGER NOT NULL DEFAULT 0 CHECK(has_junctions IN (0,1)),
|
|
550
|
+
created_at INTEGER NOT NULL, released_at INTEGER, swept_at INTEGER, sweep_error TEXT) STRICT;
|
|
551
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ux_claims_live ON claims(resource_path) WHERE released_at IS NULL AND swept_at IS NULL;
|
|
552
|
+
|
|
553
|
+
CREATE TABLE IF NOT EXISTS agent_sessions(
|
|
554
|
+
session_id TEXT PRIMARY KEY,
|
|
555
|
+
agent TEXT NOT NULL CHECK(agent IN ('devin','codex','claude')),
|
|
556
|
+
terminal_handle TEXT, ledger_id TEXT, workflow_id TEXT, job_id TEXT, attempt_id INTEGER, sup_attempt_id INTEGER, seat_id TEXT,
|
|
557
|
+
started_at INTEGER, ended_at INTEGER,
|
|
558
|
+
transcript_sha TEXT REFERENCES blobs(sha256), archive_ref TEXT, bytes INTEGER, archived_at INTEGER) STRICT;
|
|
559
|
+
CREATE INDEX IF NOT EXISTS ix_agent_sessions_attempt ON agent_sessions(ledger_id,attempt_id);
|
|
560
|
+
|
|
561
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
562
|
+
-- B4. Resources: RAM/CPU, pool, provider, quota, guard, host leases, budget
|
|
563
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
564
|
+
CREATE TABLE IF NOT EXISTS throttle_state( -- replaces ram-throttle.json (one current row; carries the writer's rev - MB-15)
|
|
565
|
+
id INTEGER PRIMARY KEY CHECK(id=1),
|
|
566
|
+
mode TEXT NOT NULL CHECK(mode IN ('normal','heavy','critical')),
|
|
567
|
+
effective_cap INTEGER, heavy_cap INTEGER, running INTEGER,
|
|
568
|
+
free_ram_pct REAL, free_ram_mb INTEGER, cpu_pct REAL, cpu_hot INTEGER, since INTEGER, updated_at INTEGER NOT NULL,
|
|
569
|
+
reason TEXT, writer TEXT NOT NULL, writer_rev TEXT NOT NULL,
|
|
570
|
+
slot_targets_json TEXT CHECK(slot_targets_json IS NULL OR json_valid(slot_targets_json)),
|
|
571
|
+
priorities_json TEXT CHECK(priorities_json IS NULL OR json_valid(priorities_json))) STRICT;
|
|
572
|
+
-- throttle_events (G7): EVERY mode change, APPEND-ONLY (no overwrite, no delete).
|
|
573
|
+
CREATE TABLE IF NOT EXISTS throttle_events(
|
|
574
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL,
|
|
575
|
+
from_mode TEXT, to_mode TEXT NOT NULL CHECK(to_mode IN ('normal','heavy','critical')), reason TEXT,
|
|
576
|
+
free_ram_pct REAL, cpu_pct REAL, effective_cap INTEGER, running INTEGER, writer_rev TEXT,
|
|
577
|
+
sample_json TEXT CHECK(sample_json IS NULL OR json_valid(sample_json))) STRICT;
|
|
578
|
+
CREATE TRIGGER IF NOT EXISTS throttle_events_no_update BEFORE UPDATE ON throttle_events BEGIN
|
|
579
|
+
SELECT RAISE(ABORT,'throttle_events are append-only');
|
|
580
|
+
END;
|
|
581
|
+
CREATE TRIGGER IF NOT EXISTS throttle_events_no_delete BEFORE DELETE ON throttle_events BEGIN
|
|
582
|
+
SELECT RAISE(ABORT,'throttle_events are append-only');
|
|
583
|
+
END;
|
|
584
|
+
-- A mode change in throttle_state requires a matching throttle_events row written first (no transition is lost).
|
|
585
|
+
CREATE TRIGGER IF NOT EXISTS throttle_state_recorded BEFORE UPDATE OF mode ON throttle_state
|
|
586
|
+
WHEN NEW.mode<>OLD.mode AND NOT EXISTS(SELECT 1 FROM throttle_events e WHERE e.seq=(SELECT max(seq) FROM throttle_events)
|
|
587
|
+
AND e.to_mode=NEW.mode AND e.from_mode IS OLD.mode) BEGIN
|
|
588
|
+
SELECT RAISE(ABORT,'throttle mode change must be recorded in throttle_events first');
|
|
589
|
+
END;
|
|
590
|
+
-- throttle_decisions (G7): which op was deferred by throttle, for how long.
|
|
591
|
+
CREATE TABLE IF NOT EXISTS throttle_decisions(
|
|
592
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL, ledger_id TEXT, workflow_id TEXT, job_id TEXT,
|
|
593
|
+
reason TEXT NOT NULL, waited_ms INTEGER, released_at INTEGER) STRICT;
|
|
594
|
+
|
|
595
|
+
CREATE TABLE IF NOT EXISTS host_samples(
|
|
596
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL,
|
|
597
|
+
kind TEXT NOT NULL CHECK(kind IN ('host','op-footprint','worker-footprint')),
|
|
598
|
+
ledger_id TEXT, workflow_id TEXT, attempt_id INTEGER, sup_attempt_id INTEGER, subject TEXT,
|
|
599
|
+
ram_mb INTEGER, cpu_pct REAL, free_ram_mb INTEGER, free_ram_pct REAL, free_disk_gb REAL,
|
|
600
|
+
mode TEXT, effective_cap INTEGER, running INTEGER,
|
|
601
|
+
detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json))) STRICT; -- kept 14 days
|
|
602
|
+
CREATE INDEX IF NOT EXISTS ix_host_samples ON host_samples(kind,at);
|
|
603
|
+
CREATE TABLE IF NOT EXISTS provider_health(
|
|
604
|
+
provider TEXT PRIMARY KEY CHECK(provider IN ('devin','codex','claude')),
|
|
605
|
+
status TEXT NOT NULL CHECK(status IN ('healthy','striking','unavailable','recovered')),
|
|
606
|
+
failure_kind TEXT, strikes INTEGER NOT NULL DEFAULT 0, strike_limit INTEGER,
|
|
607
|
+
circuit_open_until INTEGER, recovered_at INTEGER, reason TEXT, updated_at INTEGER NOT NULL,
|
|
608
|
+
detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json))) STRICT;
|
|
609
|
+
CREATE TABLE IF NOT EXISTS provider_health_events(
|
|
610
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT, provider TEXT NOT NULL, at INTEGER NOT NULL, from_status TEXT, to_status TEXT,
|
|
611
|
+
failure_kind TEXT, ledger_id TEXT, attempt_id INTEGER,
|
|
612
|
+
detail_json TEXT CHECK(detail_json IS NULL OR json_valid(detail_json))) STRICT;
|
|
613
|
+
CREATE TABLE IF NOT EXISTS pool_backoff(
|
|
614
|
+
pool TEXT PRIMARY KEY, until_at INTEGER, strikes INTEGER NOT NULL DEFAULT 0, reason TEXT, updated_at INTEGER NOT NULL) STRICT;
|
|
615
|
+
CREATE TABLE IF NOT EXISTS quotas(
|
|
616
|
+
provider TEXT NOT NULL, window TEXT NOT NULL, used REAL, limit_value REAL, reset_at INTEGER, source TEXT,
|
|
617
|
+
observed_at INTEGER NOT NULL, PRIMARY KEY(provider,window)) STRICT;
|
|
618
|
+
CREATE TABLE IF NOT EXISTS guard_jobs( -- replaces .claude/runtime/guards/jobs/<job>.json (STARCI_GUARD_FILE)
|
|
619
|
+
job_id TEXT PRIMARY KEY, ledger_id TEXT, workflow_id TEXT, attempt_id INTEGER,
|
|
620
|
+
allow_json TEXT NOT NULL CHECK(json_valid(allow_json)),
|
|
621
|
+
hooks_json TEXT CHECK(hooks_json IS NULL OR json_valid(hooks_json)),
|
|
622
|
+
created_at INTEGER NOT NULL, expires_at INTEGER NOT NULL, released_at INTEGER) STRICT;
|
|
623
|
+
CREATE TABLE IF NOT EXISTS guard_refusals( -- replaces .claude/runtime/guards/refusals.jsonl
|
|
624
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL, ledger_id TEXT, workflow_id TEXT, job_id TEXT, attempt_id INTEGER,
|
|
625
|
+
tool TEXT, command TEXT, code TEXT, reason TEXT, remedy TEXT, cwd TEXT) STRICT;
|
|
626
|
+
CREATE TABLE IF NOT EXISTS host_resources(resource_key TEXT PRIMARY KEY, capacity INTEGER NOT NULL CHECK(capacity>=0)) STRICT;
|
|
627
|
+
CREATE TABLE IF NOT EXISTS host_leases(
|
|
628
|
+
resource_key TEXT NOT NULL, token TEXT NOT NULL, ledger_id TEXT NOT NULL REFERENCES ledgers(ledger_id),
|
|
629
|
+
workflow_id TEXT NOT NULL, job_id TEXT NOT NULL, attempt_id INTEGER, holder TEXT, units INTEGER NOT NULL CHECK(units>0),
|
|
630
|
+
acquired_at INTEGER NOT NULL, expires_at INTEGER NOT NULL CHECK(expires_at>acquired_at), PRIMARY KEY(resource_key,token)) STRICT;
|
|
631
|
+
CREATE INDEX IF NOT EXISTS ix_host_leases_expiry ON host_leases(expires_at);
|
|
632
|
+
CREATE TABLE IF NOT EXISTS budgets(
|
|
633
|
+
scope_key TEXT PRIMARY KEY, limit_value INTEGER NOT NULL, used_value INTEGER NOT NULL DEFAULT 0,
|
|
634
|
+
reserved_value INTEGER NOT NULL DEFAULT 0, window TEXT, updated_at INTEGER) STRICT;
|
|
635
|
+
CREATE TABLE IF NOT EXISTS budget_reservations(
|
|
636
|
+
scope_key TEXT NOT NULL REFERENCES budgets(scope_key), ledger_id TEXT NOT NULL, job_id TEXT NOT NULL,
|
|
637
|
+
units INTEGER NOT NULL, at INTEGER, PRIMARY KEY(scope_key,ledger_id,job_id)) STRICT;
|
|
638
|
+
|
|
639
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
640
|
+
-- B5. GC, land gate, push, lane, worktree, environment
|
|
641
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
642
|
+
CREATE TABLE IF NOT EXISTS gc_runs(
|
|
643
|
+
run_id INTEGER PRIMARY KEY AUTOINCREMENT, action_id TEXT, started_at INTEGER NOT NULL, finished_at INTEGER,
|
|
644
|
+
trigger TEXT CHECK(trigger IS NULL OR trigger IN ('event','sweep','housekeeping','low-disk','low-ram','blob-sweep','manual')),
|
|
645
|
+
freed_bytes INTEGER,
|
|
646
|
+
collectors_json TEXT CHECK(collectors_json IS NULL OR json_valid(collectors_json)),
|
|
647
|
+
counts_json TEXT CHECK(counts_json IS NULL OR json_valid(counts_json)),
|
|
648
|
+
errors_json TEXT CHECK(errors_json IS NULL OR json_valid(errors_json)),
|
|
649
|
+
report_sha TEXT REFERENCES blobs(sha256)) STRICT; -- full report (G4: not truncated)
|
|
650
|
+
-- gc_items (G4, MB-14): EVERY thing GC touched, one row: collect/refuse/keep, how many bytes, retries, FINAL outcome.
|
|
651
|
+
CREATE TABLE IF NOT EXISTS gc_items(
|
|
652
|
+
item_id INTEGER PRIMARY KEY AUTOINCREMENT, run_id INTEGER REFERENCES gc_runs(run_id) ON DELETE CASCADE,
|
|
653
|
+
collector TEXT NOT NULL, kind TEXT NOT NULL, target TEXT NOT NULL, owner_ref TEXT, age_ms INTEGER,
|
|
654
|
+
action TEXT NOT NULL CHECK(action IN ('collect','refuse','keep','closed','killed','removed','archived','failed')),
|
|
655
|
+
reason TEXT, bytes INTEGER,
|
|
656
|
+
tries INTEGER NOT NULL DEFAULT 1, next_try_at INTEGER, -- retry scheduled at grace - age + margin, not exactly at grace
|
|
657
|
+
last_error TEXT,
|
|
658
|
+
outcome TEXT CHECK(outcome IS NULL OR outcome IN ('done','dropped','gave-up')), -- final outcome, always written
|
|
659
|
+
verified_gone_at INTEGER,
|
|
660
|
+
at INTEGER NOT NULL) STRICT;
|
|
661
|
+
CREATE INDEX IF NOT EXISTS ix_gc_items_kind ON gc_items(collector,kind,at);
|
|
662
|
+
CREATE INDEX IF NOT EXISTS ix_gc_items_open ON gc_items(outcome,next_try_at);
|
|
663
|
+
CREATE TABLE IF NOT EXISTS gc_marks(
|
|
664
|
+
run_id INTEGER NOT NULL REFERENCES gc_runs(run_id) ON DELETE CASCADE,
|
|
665
|
+
sha256 TEXT NOT NULL,
|
|
666
|
+
source TEXT NOT NULL, -- ledger name | 'machine'
|
|
667
|
+
pinned INTEGER NOT NULL DEFAULT 0 CHECK(pinned IN (0,1)),
|
|
668
|
+
PRIMARY KEY(run_id,sha256,source)) STRICT, WITHOUT ROWID;
|
|
669
|
+
|
|
670
|
+
CREATE TABLE IF NOT EXISTS lanes(
|
|
671
|
+
name TEXT PRIMARY KEY, worktree_path TEXT NOT NULL, branch TEXT NOT NULL, base_sha TEXT, head_sha TEXT,
|
|
672
|
+
owner TEXT NOT NULL, -- 'supervisor' | 'owner-chat' | 'worker:<job>'
|
|
673
|
+
sup_job_id TEXT REFERENCES sup_jobs(job_id),
|
|
674
|
+
state TEXT NOT NULL CHECK(state IN ('open','landing','landed','abandoned','removed')),
|
|
675
|
+
created_at INTEGER NOT NULL, landed_at INTEGER, removed_at INTEGER,
|
|
676
|
+
report_sha TEXT REFERENCES blobs(sha256)) STRICT;
|
|
677
|
+
-- land_queue (G9, MB-10): when a lane entered the gate and who holds the gate when busy.
|
|
678
|
+
CREATE TABLE IF NOT EXISTS land_queue(
|
|
679
|
+
ticket_id TEXT PRIMARY KEY, lane TEXT REFERENCES lanes(name), commit_sha TEXT NOT NULL, commits INTEGER, requested_by TEXT,
|
|
680
|
+
state TEXT NOT NULL CHECK(state IN ('queued','running','passed','failed','cancelled')),
|
|
681
|
+
enqueued_at INTEGER NOT NULL, gate_at INTEGER, busy_holder TEXT, started_at INTEGER, finished_at INTEGER) STRICT;
|
|
682
|
+
CREATE INDEX IF NOT EXISTS ix_land_queue_state ON land_queue(state,enqueued_at);
|
|
683
|
+
CREATE TABLE IF NOT EXISTS land_runs(
|
|
684
|
+
run_id INTEGER PRIMARY KEY AUTOINCREMENT, ticket_id TEXT REFERENCES land_queue(ticket_id), lane TEXT,
|
|
685
|
+
span_id TEXT NOT NULL CHECK(length(span_id)=16), parent_span_id TEXT,
|
|
686
|
+
commit_sha TEXT NOT NULL, landed_sha TEXT,
|
|
687
|
+
commits_json TEXT CHECK(commits_json IS NULL OR (json_valid(commits_json) AND json_type(commits_json)='array')), -- every picked commit, in order (a3-2)
|
|
688
|
+
result TEXT NOT NULL CHECK(result IN ('passed','failed','conflict','refused')), reason TEXT,
|
|
689
|
+
push_id INTEGER, -- MB-12: a 'passed' land links to the real push result
|
|
690
|
+
specs_json TEXT CHECK(specs_json IS NULL OR json_valid(specs_json)),
|
|
691
|
+
stdout_sha TEXT REFERENCES blobs(sha256), stderr_sha TEXT REFERENCES blobs(sha256),
|
|
692
|
+
started_at INTEGER NOT NULL, finished_at INTEGER) STRICT;
|
|
693
|
+
CREATE INDEX IF NOT EXISTS ix_land_runs_lane ON land_runs(lane,started_at);
|
|
694
|
+
-- pushes (G8, MB-03): one row per push, with a stable error signature and the FULL log in a blob.
|
|
695
|
+
CREATE TABLE IF NOT EXISTS pushes(
|
|
696
|
+
push_id INTEGER PRIMARY KEY AUTOINCREMENT, repo_root TEXT NOT NULL, branch TEXT, head TEXT NOT NULL, from_sha TEXT, to_sha TEXT,
|
|
697
|
+
result TEXT NOT NULL CHECK(result IN ('pushed','refused','skipped','failed')), reason TEXT,
|
|
698
|
+
failure_signature TEXT, -- secret-scan:<rule> | lint:<rule> | jest:<suite> ... (no HEAD)
|
|
699
|
+
ms INTEGER, action_id TEXT,
|
|
700
|
+
scan_json TEXT CHECK(scan_json IS NULL OR json_valid(scan_json)),
|
|
701
|
+
stdout_sha TEXT REFERENCES blobs(sha256), stderr_sha TEXT REFERENCES blobs(sha256),
|
|
702
|
+
at INTEGER NOT NULL,
|
|
703
|
+
CHECK(result IN ('pushed','skipped') OR failure_signature IS NOT NULL)) STRICT;
|
|
704
|
+
CREATE INDEX IF NOT EXISTS ix_pushes ON pushes(repo_root,at);
|
|
705
|
+
|
|
706
|
+
CREATE TABLE IF NOT EXISTS worktrees(
|
|
707
|
+
path TEXT PRIMARY KEY,
|
|
708
|
+
kind TEXT NOT NULL CHECK(kind IN ('workflow','critic','land-scratch','push-scratch','supervisor-staging','lane')),
|
|
709
|
+
repo_root TEXT NOT NULL, branch TEXT, base_sha TEXT, head_sha TEXT, port INTEGER,
|
|
710
|
+
ledger_id TEXT, workflow_id TEXT, job_id TEXT, attempt_id INTEGER, lane TEXT, claim_id INTEGER REFERENCES claims(claim_id),
|
|
711
|
+
created_at INTEGER NOT NULL, removed_at INTEGER, archived_ref TEXT, remove_error TEXT,
|
|
712
|
+
-- One worktree per Kernel workflow: Orca creates and owns it, so the registry keys it by Orca's worktree id, records the
|
|
713
|
+
-- workflow's last checkpoint and the moment its finish asked for its release (the host-side GC removes it once the
|
|
714
|
+
-- Kernel's and the ops' terminals are released; never from inside itself).
|
|
715
|
+
orca_id TEXT, checkpoint_sha TEXT, release_pending_at INTEGER) STRICT;
|
|
716
|
+
CREATE INDEX IF NOT EXISTS ix_worktrees_live ON worktrees(removed_at,kind);
|
|
717
|
+
CREATE INDEX IF NOT EXISTS ix_worktrees_attempt ON worktrees(ledger_id,attempt_id);
|
|
718
|
+
CREATE UNIQUE INDEX IF NOT EXISTS ux_worktrees_orca_id ON worktrees(orca_id) WHERE orca_id IS NOT NULL;
|
|
719
|
+
CREATE INDEX IF NOT EXISTS ix_worktrees_workflow ON worktrees(workflow_id,kind,removed_at);
|
|
720
|
+
|
|
721
|
+
CREATE TABLE IF NOT EXISTS env_servers(
|
|
722
|
+
server_id TEXT PRIMARY KEY, env TEXT, service TEXT, repo_root TEXT,
|
|
723
|
+
ledger_id TEXT, workflow_id TEXT, job_id TEXT, attempt_id INTEGER,
|
|
724
|
+
command TEXT, cwd TEXT, port INTEGER, pid INTEGER, url TEXT,
|
|
725
|
+
state TEXT NOT NULL CHECK(state IN ('starting','ready','failed','stopped')),
|
|
726
|
+
started_at INTEGER, stopped_at INTEGER, log_sha TEXT REFERENCES blobs(sha256)) STRICT;
|
|
727
|
+
CREATE TABLE IF NOT EXISTS uat_slots(
|
|
728
|
+
slot_id TEXT PRIMARY KEY, ledger_id TEXT, workflow_id TEXT, job_id TEXT, attempt_id INTEGER,
|
|
729
|
+
browser_profile TEXT, port INTEGER, acquired_at INTEGER, expires_at INTEGER, released_at INTEGER) STRICT;
|
|
730
|
+
CREATE TABLE IF NOT EXISTS connectors( -- holds NO secrets; secrets live in .starcistacks + sops
|
|
731
|
+
name TEXT PRIMARY KEY, kind TEXT, state TEXT, pid INTEGER, port INTEGER, public_url TEXT,
|
|
732
|
+
config_json TEXT CHECK(config_json IS NULL OR json_valid(config_json)),
|
|
733
|
+
cursor_json TEXT CHECK(cursor_json IS NULL OR json_valid(cursor_json)), -- e.g. telegram offset, route chats
|
|
734
|
+
updated_at INTEGER NOT NULL) STRICT;
|
|
735
|
+
CREATE TABLE IF NOT EXISTS ask_requests(
|
|
736
|
+
ask_id TEXT PRIMARY KEY, ledger_id TEXT, workflow_id TEXT, di_id TEXT, channel TEXT, question TEXT NOT NULL,
|
|
737
|
+
form_url TEXT,
|
|
738
|
+
state TEXT NOT NULL CHECK(state IN ('open','answered','retired','expired')),
|
|
739
|
+
asked_at INTEGER NOT NULL, answered_at INTEGER, answer_ref TEXT) STRICT;
|
|
740
|
+
|
|
741
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
742
|
+
-- B6. Machine-level observability
|
|
743
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
744
|
+
CREATE TABLE IF NOT EXISTS machine_logs(
|
|
745
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL,
|
|
746
|
+
actor TEXT NOT NULL CHECK(actor IN ('reconciler','supervisor','worker','gc','host','land','watchdog','connector','harness','runtime')),
|
|
747
|
+
controller TEXT, ledger_id TEXT, workflow_id TEXT, job_id TEXT, attempt_id INTEGER, action_id TEXT,
|
|
748
|
+
trace_id TEXT, span_id TEXT,
|
|
749
|
+
level TEXT NOT NULL CHECK(level IN ('debug','info','warn','error')),
|
|
750
|
+
kind TEXT NOT NULL, msg TEXT NOT NULL,
|
|
751
|
+
data_json TEXT CHECK(data_json IS NULL OR json_valid(data_json)),
|
|
752
|
+
refs_json TEXT CHECK(refs_json IS NULL OR json_valid(refs_json)),
|
|
753
|
+
src TEXT UNIQUE) STRICT; -- append-only; GC deletes by retention (debug 14 days, the rest 90 days)
|
|
754
|
+
CREATE INDEX IF NOT EXISTS ix_mlogs_at ON machine_logs(at);
|
|
755
|
+
CREATE INDEX IF NOT EXISTS ix_mlogs_kind ON machine_logs(actor,kind,seq);
|
|
756
|
+
CREATE INDEX IF NOT EXISTS ix_mlogs_ent ON machine_logs(ledger_id,workflow_id,job_id,seq);
|
|
757
|
+
CREATE TRIGGER IF NOT EXISTS machine_logs_append_only BEFORE UPDATE ON machine_logs BEGIN
|
|
758
|
+
SELECT RAISE(ABORT,'machine_logs are append-only');
|
|
759
|
+
END;
|
|
760
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS machine_logs_fts USING fts5(msg, kind, controller, content='machine_logs', content_rowid='seq',
|
|
761
|
+
tokenize='unicode61 remove_diacritics 2');
|
|
762
|
+
CREATE TRIGGER IF NOT EXISTS machine_logs_fts_insert AFTER INSERT ON machine_logs BEGIN
|
|
763
|
+
INSERT INTO machine_logs_fts(rowid,msg,kind,controller) VALUES (NEW.seq,NEW.msg,NEW.kind,NEW.controller);
|
|
764
|
+
END;
|
|
765
|
+
CREATE TRIGGER IF NOT EXISTS machine_logs_fts_delete AFTER DELETE ON machine_logs BEGIN
|
|
766
|
+
INSERT INTO machine_logs_fts(machine_logs_fts,rowid,msg,kind,controller) VALUES ('delete',OLD.seq,OLD.msg,OLD.kind,OLD.controller);
|
|
767
|
+
END;
|
|
768
|
+
|
|
769
|
+
-- metrics_snapshots: controllers write these (progress, rca, frontier, coverage, verify ...) so the harness does NOT have to run a verb.
|
|
770
|
+
CREATE TABLE IF NOT EXISTS metrics_snapshots(
|
|
771
|
+
snap_id INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL,
|
|
772
|
+
kind TEXT NOT NULL CHECK(kind IN ('op-health','progress','rca','frontier','coverage','verify','model-scorecard','throughput','ram')),
|
|
773
|
+
ledger_id TEXT, workflow_id TEXT, window_ms INTEGER, subject TEXT,
|
|
774
|
+
data_json TEXT CHECK(data_json IS NULL OR json_valid(data_json)),
|
|
775
|
+
data_sha TEXT REFERENCES blobs(sha256)) STRICT;
|
|
776
|
+
CREATE INDEX IF NOT EXISTS ix_metrics ON metrics_snapshots(kind,ledger_id,workflow_id,at);
|
|
777
|
+
|
|
778
|
+
CREATE TABLE IF NOT EXISTS notifications(
|
|
779
|
+
notif_id INTEGER PRIMARY KEY AUTOINCREMENT, channel TEXT NOT NULL,
|
|
780
|
+
kind TEXT NOT NULL CHECK(kind IN ('digest','urgent','ask','ack','media')),
|
|
781
|
+
text TEXT NOT NULL, media_sha TEXT REFERENCES blobs(sha256), sent_at INTEGER, delivery TEXT, ref TEXT,
|
|
782
|
+
dedupe_key TEXT UNIQUE) STRICT; -- replaces telegram-sent.json / telegram-media-sent.json
|
|
783
|
+
|
|
784
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
785
|
+
-- B7. Durable views of machine.sqlite
|
|
786
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
787
|
+
CREATE VIEW IF NOT EXISTS v_services AS
|
|
788
|
+
SELECT s.*, COALESCE(m.ui,'unknown') AS ui,
|
|
789
|
+
(SELECT count(*) FROM service_events e WHERE e.name=s.name AND e.action='restart'
|
|
790
|
+
AND e.at > CAST(unixepoch('subsec')*1000 AS INTEGER) - 86400000) AS restarts_24h,
|
|
791
|
+
(SELECT count(*) FROM service_probes p WHERE p.name=s.name AND p.ok=0
|
|
792
|
+
AND p.at > CAST(unixepoch('subsec')*1000 AS INTEGER) - 86400000) AS failed_probes_24h
|
|
793
|
+
FROM services s LEFT JOIN ui_state_map m ON m.entity='service' AND m.native=s.state;
|
|
794
|
+
|
|
795
|
+
CREATE VIEW IF NOT EXISTS v_seats AS
|
|
796
|
+
SELECT s.*, COALESCE(m.ui,'unknown') AS ui,
|
|
797
|
+
(SELECT max(at) FROM seat_transcript_snapshots x WHERE x.seat_id=s.seat_id) AS last_snapshot_at
|
|
798
|
+
FROM seats s LEFT JOIN ui_state_map m ON m.entity='seat' AND m.native=s.state;
|
|
799
|
+
|
|
800
|
+
CREATE VIEW IF NOT EXISTS v_engine_actions AS
|
|
801
|
+
SELECT a.*, COALESCE(m.ui,'unknown') AS ui FROM engine_actions a
|
|
802
|
+
LEFT JOIN ui_state_map m ON m.entity='engine-action' AND m.native=a.state;
|
|
803
|
+
|
|
804
|
+
-- Open SLA clocks (replaces the old sla_clocks table).
|
|
805
|
+
CREATE VIEW IF NOT EXISTS v_sla_open AS
|
|
806
|
+
SELECT e.*, e.entered_at + e.sla_ms AS due_at,
|
|
807
|
+
CASE WHEN e.violated_at IS NULL THEN 'waiting' WHEN e.severity='critical' THEN 'bad' ELSE 'warn' END AS ui
|
|
808
|
+
FROM sla_episodes e WHERE e.cleared_at IS NULL;
|
|
809
|
+
|
|
810
|
+
-- Periodic duties overdue or running too often (MB-01).
|
|
811
|
+
CREATE VIEW IF NOT EXISTS v_schedules AS
|
|
812
|
+
SELECT s.*, (CAST(unixepoch('subsec')*1000 AS INTEGER) - s.next_due_at) AS overdue_ms,
|
|
813
|
+
(SELECT count(*) FROM engine_actions a WHERE a.controller=s.controller AND a.duty=s.duty
|
|
814
|
+
AND a.started_at > CAST(unixepoch('subsec')*1000 AS INTEGER) - 86400000) AS runs_24h,
|
|
815
|
+
CASE WHEN (SELECT count(*) FROM engine_actions a WHERE a.controller=s.controller AND a.duty=s.duty
|
|
816
|
+
AND a.started_at > CAST(unixepoch('subsec')*1000 AS INTEGER) - 86400000) > 2 * (86400000 / s.interval_ms) + 1 THEN 'bad'
|
|
817
|
+
WHEN s.next_due_at < CAST(unixepoch('subsec')*1000 AS INTEGER) - s.interval_ms THEN 'warn' ELSE 'ok' END AS ui
|
|
818
|
+
FROM schedules s;
|
|
819
|
+
|
|
820
|
+
CREATE VIEW IF NOT EXISTS v_open_sup_decisions AS
|
|
821
|
+
SELECT di_id, kind, summary, status, opened_at, due_at, escalations, delivered_at,
|
|
822
|
+
(CAST(unixepoch('subsec')*1000 AS INTEGER) - opened_at) AS age_ms,
|
|
823
|
+
CASE WHEN due_at IS NOT NULL AND due_at < CAST(unixepoch('subsec')*1000 AS INTEGER) THEN 'bad'
|
|
824
|
+
WHEN delivered_at IS NULL THEN 'warn'
|
|
825
|
+
WHEN status='claimed' THEN 'running' ELSE 'waiting' END AS ui
|
|
826
|
+
FROM sup_decision_items WHERE status IN ('open','claimed','escalated');
|
|
827
|
+
|
|
828
|
+
-- Deaf seats (MB-05): consecutive input failures >= 3 -> SLA SEAT_DEAF -> replace the seat.
|
|
829
|
+
CREATE VIEW IF NOT EXISTS v_deaf_seats AS
|
|
830
|
+
SELECT seat_id, role, workflow_id, state, input_failures_consecutive, last_input_failure_at, last_input_ok_at
|
|
831
|
+
FROM seats WHERE state NOT IN ('parked','empty') AND input_failures_consecutive >= 3;
|
|
832
|
+
|
|
833
|
+
CREATE VIEW IF NOT EXISTS v_leaks AS
|
|
834
|
+
SELECT 'worktree' AS kind, path AS target, ledger_id, job_id AS owner, created_at AS since FROM worktrees
|
|
835
|
+
WHERE removed_at IS NULL AND kind IN ('push-scratch','land-scratch')
|
|
836
|
+
UNION ALL SELECT 'lease', resource_key, ledger_id, job_id, acquired_at FROM host_leases
|
|
837
|
+
WHERE expires_at < CAST(unixepoch('subsec')*1000 AS INTEGER)
|
|
838
|
+
UNION ALL SELECT 'lease', path, NULL, job_id, acquired_at FROM sup_leases WHERE expires_at < CAST(unixepoch('subsec')*1000 AS INTEGER)
|
|
839
|
+
UNION ALL SELECT 'guard', job_id, ledger_id, job_id, created_at FROM guard_jobs
|
|
840
|
+
WHERE released_at IS NULL AND expires_at < CAST(unixepoch('subsec')*1000 AS INTEGER)
|
|
841
|
+
UNION ALL SELECT 'claim', resource_path, NULL, owner_action_id, created_at FROM claims
|
|
842
|
+
WHERE released_at IS NULL AND swept_at IS NULL AND created_at < CAST(unixepoch('subsec')*1000 AS INTEGER) - 3600000
|
|
843
|
+
UNION ALL SELECT 'lock', name, NULL, holder, started_at FROM host_locks
|
|
844
|
+
WHERE state<>'released' AND expires_at < CAST(unixepoch('subsec')*1000 AS INTEGER);
|
|
845
|
+
|
|
846
|
+
CREATE VIEW IF NOT EXISTS v_engine_health AS
|
|
847
|
+
SELECT l.holder, l.pid, l.epoch, l.rev, l.heartbeat_at, l.draining, l.passes, l.last_pass_ms, l.last_error,
|
|
848
|
+
(CAST(unixepoch('subsec')*1000 AS INTEGER) - l.heartbeat_at) AS heartbeat_age_ms,
|
|
849
|
+
(SELECT count(*) FROM process_runs r WHERE r.role='engine' AND r.started_at > CAST(unixepoch('subsec')*1000 AS INTEGER) - 3600000) AS starts_last_hour,
|
|
850
|
+
(SELECT count(*) FROM process_runs r WHERE r.role='engine' AND r.exit_reason IN ('crash','killed','lost-lease')
|
|
851
|
+
AND r.ended_at > CAST(unixepoch('subsec')*1000 AS INTEGER) - 86400000) AS bad_exits_24h,
|
|
852
|
+
(SELECT count(*) FROM engine_queue) AS queue_depth,
|
|
853
|
+
(SELECT count(*) FROM sla_episodes WHERE violated_at IS NOT NULL AND cleared_at IS NULL) AS open_violations,
|
|
854
|
+
CASE WHEN l.expires_at < CAST(unixepoch('subsec')*1000 AS INTEGER) THEN 'bad'
|
|
855
|
+
WHEN l.last_error IS NOT NULL OR l.draining=1 THEN 'warn' ELSE 'ok' END AS ui
|
|
856
|
+
FROM engine_leader l;
|
|
857
|
+
|
|
858
|
+
CREATE VIEW IF NOT EXISTS v_search_ids AS
|
|
859
|
+
SELECT 'sup-decision' AS kind, di_id AS id, summary AS title FROM sup_decision_items
|
|
860
|
+
UNION ALL SELECT 'sup-job', job_id, title FROM sup_jobs
|
|
861
|
+
UNION ALL SELECT 'trace', trace_id, title FROM sup_jobs
|
|
862
|
+
UNION ALL SELECT 'lane', name, branch FROM lanes
|
|
863
|
+
UNION ALL SELECT 'land-ticket', ticket_id, commit_sha FROM land_queue
|
|
864
|
+
UNION ALL SELECT 'commit', landed_sha, lane FROM land_runs WHERE landed_sha IS NOT NULL
|
|
865
|
+
UNION ALL SELECT 'action', id, controller||' '||COALESCE(verb,'') FROM engine_actions
|
|
866
|
+
UNION ALL SELECT 'terminal', handle, title FROM terminals
|
|
867
|
+
UNION ALL SELECT 'seat', seat_id, state FROM seats
|
|
868
|
+
UNION ALL SELECT 'service', name, state FROM services
|
|
869
|
+
UNION ALL SELECT 'worktree', path, branch FROM worktrees
|
|
870
|
+
UNION ALL SELECT 'ledger', name, repo_root FROM ledgers
|
|
871
|
+
UNION ALL SELECT 'blob', sha256, media_type FROM blobs;
|
|
872
|
+
|
|
873
|
+
CREATE VIEW IF NOT EXISTS v_live_marks AS
|
|
874
|
+
SELECT 'machine_logs' AS topic, COALESCE(max(seq),0) AS mark FROM machine_logs
|
|
875
|
+
UNION ALL SELECT 'engine_actions', COALESCE(max(COALESCE(finished_at,started_at)),0) FROM engine_actions
|
|
876
|
+
UNION ALL SELECT 'violations', COALESCE(max(max(violation_id), max(COALESCE(cleared_at,0))),0) FROM invariant_violations
|
|
877
|
+
UNION ALL SELECT 'services', COALESCE(max(seq),0) FROM service_events
|
|
878
|
+
UNION ALL SELECT 'deliveries', COALESCE(max(delivery_id),0) FROM deliveries
|
|
879
|
+
UNION ALL SELECT 'sup_decisions', COALESCE(max(max(opened_at), max(COALESCE(resolved_at,0))),0) FROM sup_decision_items;
|
|
880
|
+
|
|
881
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
882
|
+
-- B8. Cross-DB queries - NO durable view (SQLite forbids a main view referencing an ATTACHed DB).
|
|
883
|
+
-- * Cross-ledger lists (progress, op_history, media, open_work, blocking, settle_overdue, scorecard): engine/db/machine.mjs
|
|
884
|
+
-- forEachLedger(fn) opens each runtime.sqlite read-only, runs the same-named view, adds the ledger column, merges in JS.
|
|
885
|
+
-- attachLedgers(batch <= 9) is for ad-hoc queries only.
|
|
886
|
+
-- * Blob GC: mark PER ledger into gc_marks (per each DB's blob_ref_columns) then sweep - no ATTACH-UNION.
|
|
887
|
+
-- ---------------------------------------------------------------------------------------------------------
|
|
888
|
+
|
|
889
|
+
-- Provider/account capacity and durable launch/release evidence share this current host schema.
|
|
890
|
+
-- Additive host provider/account admission receipts. Slot units are concurrent launches,
|
|
891
|
+
-- never provider tokens, credits or measured spend. Released receipts retain attempt identity.
|
|
892
|
+
CREATE TABLE provider_reservations(
|
|
893
|
+
fence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
894
|
+
id TEXT NOT NULL UNIQUE,
|
|
895
|
+
attempt_id TEXT NOT NULL UNIQUE,
|
|
896
|
+
provider TEXT NOT NULL,
|
|
897
|
+
account TEXT NOT NULL,
|
|
898
|
+
model TEXT NOT NULL,
|
|
899
|
+
role TEXT NOT NULL CHECK(role IN ('kernel','op','supervisor','worker','critic')),
|
|
900
|
+
scope_json TEXT,
|
|
901
|
+
state TEXT NOT NULL CHECK(state IN ('reserved','launching','live','unknown','released')),
|
|
902
|
+
slots INTEGER NOT NULL DEFAULT 1 CHECK(slots=1),
|
|
903
|
+
max_parallel INTEGER NOT NULL CHECK(max_parallel>=0),
|
|
904
|
+
quota_json TEXT,
|
|
905
|
+
estimate_json TEXT,
|
|
906
|
+
override_json TEXT,
|
|
907
|
+
launch_identity TEXT,
|
|
908
|
+
host_request_id TEXT,
|
|
909
|
+
handle TEXT,
|
|
910
|
+
pid INTEGER,
|
|
911
|
+
created_at INTEGER NOT NULL,
|
|
912
|
+
updated_at INTEGER NOT NULL,
|
|
913
|
+
released_at INTEGER,
|
|
914
|
+
proof_json TEXT
|
|
915
|
+
) STRICT;
|
|
916
|
+
CREATE INDEX provider_reservations_active ON provider_reservations(provider,account,state);
|
|
917
|
+
CREATE TABLE provider_reservation_events(
|
|
918
|
+
id INTEGER PRIMARY KEY,
|
|
919
|
+
reservation_id TEXT NOT NULL REFERENCES provider_reservations(id),
|
|
920
|
+
at INTEGER NOT NULL,
|
|
921
|
+
from_state TEXT,
|
|
922
|
+
to_state TEXT NOT NULL,
|
|
923
|
+
proof_json TEXT
|
|
924
|
+
) STRICT;
|