@open-mercato/cli 0.6.8-develop.6931.1.4a1e1c786b → 0.6.8-develop.6941.1.3c26284542
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/.turbo/turbo-build.log +64 -0
- package/build.mjs +57 -7
- package/dist/agentic/guides/backend-ui.md +7 -1
- package/dist/agentic/guides/module-facts.json +565 -224
- package/dist/agentic/guides/module-facts.v2.json +122933 -0
- package/dist/agentic/guides/modules/ai_assistant.md +2 -2
- package/dist/agentic/guides/modules/api_docs.md +2 -2
- package/dist/agentic/guides/modules/api_keys.md +2 -2
- package/dist/agentic/guides/modules/attachments.md +2 -2
- package/dist/agentic/guides/modules/audit_logs.md +2 -2
- package/dist/agentic/guides/modules/auth.md +2 -2
- package/dist/agentic/guides/modules/business_rules.md +2 -2
- package/dist/agentic/guides/modules/catalog.md +11 -4
- package/dist/agentic/guides/modules/channel_gmail.md +2 -2
- package/dist/agentic/guides/modules/channel_imap.md +2 -2
- package/dist/agentic/guides/modules/checkout.md +8 -2
- package/dist/agentic/guides/modules/communication_channels.md +6 -6
- package/dist/agentic/guides/modules/configs.md +2 -2
- package/dist/agentic/guides/modules/content.md +2 -2
- package/dist/agentic/guides/modules/currencies.md +2 -2
- package/dist/agentic/guides/modules/customer_accounts.md +2 -2
- package/dist/agentic/guides/modules/customers.md +8 -8
- package/dist/agentic/guides/modules/dashboards.md +12 -12
- package/dist/agentic/guides/modules/data_sync.md +4 -4
- package/dist/agentic/guides/modules/design_system.md +2 -2
- package/dist/agentic/guides/modules/dictionaries.md +2 -2
- package/dist/agentic/guides/modules/directory.md +2 -2
- package/dist/agentic/guides/modules/entities.md +3 -3
- package/dist/agentic/guides/modules/eudr.md +3 -3
- package/dist/agentic/guides/modules/events.md +2 -2
- package/dist/agentic/guides/modules/feature_toggles.md +2 -2
- package/dist/agentic/guides/modules/gateway_stripe.md +2 -2
- package/dist/agentic/guides/modules/generators.md +2 -2
- package/dist/agentic/guides/modules/inbox_ops.md +2 -2
- package/dist/agentic/guides/modules/integrations.md +5 -2
- package/dist/agentic/guides/modules/messages.md +2 -2
- package/dist/agentic/guides/modules/notifications.md +2 -2
- package/dist/agentic/guides/modules/onboarding.md +2 -2
- package/dist/agentic/guides/modules/payment_gateways.md +7 -3
- package/dist/agentic/guides/modules/perspectives.md +2 -2
- package/dist/agentic/guides/modules/planner.md +2 -2
- package/dist/agentic/guides/modules/portal.md +2 -2
- package/dist/agentic/guides/modules/progress.md +2 -2
- package/dist/agentic/guides/modules/query_index.md +2 -2
- package/dist/agentic/guides/modules/record_locks.md +3 -3
- package/dist/agentic/guides/modules/resources.md +2 -2
- package/dist/agentic/guides/modules/sales.md +13 -4
- package/dist/agentic/guides/modules/scheduler.md +2 -2
- package/dist/agentic/guides/modules/search.md +4 -4
- package/dist/agentic/guides/modules/security.md +3 -3
- package/dist/agentic/guides/modules/shipping_carriers.md +2 -2
- package/dist/agentic/guides/modules/sso.md +2 -2
- package/dist/agentic/guides/modules/staff.md +7 -4
- package/dist/agentic/guides/modules/storage_s3.md +2 -2
- package/dist/agentic/guides/modules/sync_akeneo.md +4 -4
- package/dist/agentic/guides/modules/sync_excel.md +2 -2
- package/dist/agentic/guides/modules/system_status_overlays.md +2 -2
- package/dist/agentic/guides/modules/translations.md +2 -2
- package/dist/agentic/guides/modules/webhooks.md +2 -2
- package/dist/agentic/guides/modules/wms.md +31 -4
- package/dist/agentic/guides/modules/workflows.md +2 -2
- package/dist/agentic/guides/reference-module-facts.json +8335 -0
- package/dist/agentic/guides/reference-modules/example.md +489 -0
- package/dist/agentic/guides/spec-delivery.md +34 -0
- package/dist/agentic/guides/testing-debugging.md +2 -1
- package/dist/agentic/guides/upstream/BACKWARD_COMPATIBILITY.md +3 -2
- package/dist/agentic/guides/upstream/manifest.json +2 -2
- package/dist/agentic/shared/AGENTS.md.template +10 -14
- package/dist/agentic/shared/ai/harness/README.md +4 -4
- package/dist/agentic/shared/ai/harness/RELEASE.md +4 -4
- package/dist/agentic/shared/ai/harness/cases.json +11350 -5088
- package/dist/agentic/shared/ai/harness/cases.schema.json +70 -7
- package/dist/agentic/shared/ai/harness/design-system-inventory.json +6697 -0
- package/dist/agentic/shared/ai/harness/fixtures/index.json +3 -1
- package/dist/agentic/shared/ai/harness/fixtures/seeds.json +4 -0
- package/dist/agentic/shared/ai/harness/knowledge-change.schema.json +228 -0
- package/dist/agentic/shared/ai/harness/release-matrix.json +9 -4
- package/dist/agentic/shared/ai/harness/result.schema.json +60 -0
- package/dist/agentic/shared/ai/harness/routing-response.schema.json +10 -0
- package/dist/agentic/shared/ai/harness/source-link-inventory.json +3231 -0
- package/dist/agentic/shared/ai/harness/validators.json +8 -4
- package/dist/agentic/shared/ai/harness/writable-ast-oracles.mjs +5 -2
- package/dist/agentic/shared/ai/harness/writable-behavior-oracles.mjs +3 -0
- package/dist/agentic/shared/ai/harness/writable-spec-oracles.mjs +879 -0
- package/dist/agentic/shared/ai/skills/om-auto-upgrade-0.6.7-to-0.7.0/SKILL.md +102 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/crud-surfaces.md +15 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/frontend-and-design-system.md +6 -0
- package/dist/agentic/shared/ai/skills/om-backend-ui-design/references/page-and-navigation.md +4 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/integrity-and-concurrency.md +2 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/migration-workflow.md +2 -0
- package/dist/agentic/shared/ai/skills/om-data-model-design/references/schema-design.md +3 -1
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-eject-and-customize/references/decision-and-procedure.md +2 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/SKILL.md +2 -0
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-template.md +3 -3
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/case-workflow.md +1 -1
- package/dist/agentic/shared/ai/skills/om-evolve-harness/references/knowledge-change.md +133 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-integration-builder/references/provider-families.md +11 -0
- package/dist/agentic/shared/ai/skills/om-judge-agent-session/references/judge-workflow.md +1 -1
- package/dist/agentic/shared/ai/skills/om-module-scaffold/SKILL.md +2 -2
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/api-and-domain.md +14 -1
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/data-and-migrations.md +2 -0
- package/dist/agentic/shared/ai/skills/om-module-scaffold/references/module-surfaces.md +19 -0
- package/dist/agentic/shared/ai/skills/om-share-this-session/scripts/prepare-share-bundle.mjs +1 -4
- package/dist/agentic/shared/ai/skills/om-system-extension/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/extension-branches.md +24 -0
- package/dist/agentic/shared/ai/skills/om-system-extension/references/unified-overrides.md +3 -1
- package/dist/agentic/shared/ai/skills/om-troubleshooter/SKILL.md +1 -0
- package/dist/agentic/shared/ai/skills/om-troubleshooter/references/diagnosis-map.md +13 -0
- package/dist/agentic/shared/ai/skills/tiers.json +2 -1
- package/dist/agentic/shared/ai/specs/2026-08-06-reference-module-activation.md +248 -0
- package/dist/agentic/shared/scripts/agent-harness-tool-server.mjs +39 -2
- package/dist/agentic/shared/scripts/design-source-contract.mjs +108 -0
- package/dist/agentic/shared/scripts/evaluate-agent-harness.mjs +935 -28
- package/dist/agentic/shared/scripts/framework-context.mjs +4 -1
- package/dist/agentic/shared/scripts/run-agent-harness-release.mjs +1 -1
- package/dist/agentic/shared/scripts/validate-knowledge-change.mjs +1511 -0
- package/dist/lib/__integration__/TC-INT-008.spec.js +1 -0
- package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
- package/dist/lib/agentic-setup.js +9 -1
- package/dist/lib/agentic-setup.js.map +2 -2
- package/dist/lib/generators/module-extension-facts.js +93 -26
- package/dist/lib/generators/module-extension-facts.js.map +3 -3
- package/dist/lib/generators/module-facts-discovery.js +23 -0
- package/dist/lib/generators/module-facts-discovery.js.map +2 -2
- package/dist/lib/generators/module-facts.js +969 -41
- package/dist/lib/generators/module-facts.js.map +2 -2
- package/dist/lib/generators/module-override-targets.js +35 -11
- package/dist/lib/generators/module-override-targets.js.map +2 -2
- package/dist/lib/generators/module-registry.js +105 -2
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/resolver.js +5 -0
- package/dist/lib/resolver.js.map +2 -2
- package/dist/lib/testing/integration-discovery.js +34 -0
- package/dist/lib/testing/integration-discovery.js.map +2 -2
- package/dist/lib/testing/integration.js +0 -2
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +4 -4
- package/dist/mercato.js.map +2 -2
- package/package.json +6 -6
- package/src/lib/__integration__/TC-INT-008.spec.ts +4 -2
- package/src/lib/__tests__/resolve-environment.test.ts +18 -0
- package/src/lib/agentic-setup.ts +10 -2
- package/src/lib/generators/__tests__/helpers/override-target-diagnostic-fixtures.ts +150 -0
- package/src/lib/generators/__tests__/module-extension-facts.test.ts +290 -0
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +72 -7
- package/src/lib/generators/__tests__/module-facts.computed-di-token.test.ts +88 -0
- package/src/lib/generators/__tests__/module-facts.example-fact-coverage.test.ts +502 -0
- package/src/lib/generators/__tests__/module-facts.local-reference.test.ts +414 -0
- package/src/lib/generators/__tests__/module-facts.search-entity-id.test.ts +151 -0
- package/src/lib/generators/__tests__/module-facts.source-links.test.ts +42 -1
- package/src/lib/generators/__tests__/module-override-targets.diagnostic-wiring.test.ts +92 -0
- package/src/lib/generators/__tests__/module-override-targets.test.ts +24 -0
- package/src/lib/generators/__tests__/module-override-targets.unknown-mode.test.ts +117 -0
- package/src/lib/generators/__tests__/module-subset.test.ts +60 -0
- package/src/lib/generators/module-extension-facts.ts +181 -25
- package/src/lib/generators/module-facts-discovery.ts +46 -0
- package/src/lib/generators/module-facts.ts +1330 -86
- package/src/lib/generators/module-override-targets.ts +70 -26
- package/src/lib/generators/module-registry.ts +135 -2
- package/src/lib/resolver.ts +6 -1
- package/src/lib/testing/__tests__/integration-discovery.test.ts +35 -0
- package/src/lib/testing/integration-discovery.ts +50 -0
- package/src/lib/testing/integration.ts +0 -2
- package/src/mercato.ts +3 -3
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
"omh-189": { "purpose": "Calendar provider stub missing the integration definition, DI health registration, and the hardened transport.", "seededArtifacts": ["src/modules/room_calendar_sync/index.ts"], "precondition": "oracle.business.provider-transport must fail" },
|
|
45
45
|
"omh-190": { "purpose": "Room bookings data layer without the customers response enricher.", "seededArtifacts": ["src/modules/room_bookings/index.ts", "src/modules/room_bookings/data/entities.ts"], "precondition": "oracle.umes.response-enricher must fail" },
|
|
46
46
|
"omh-191": { "purpose": "Room bookings data layer without the durable hold-expiry workflow.", "seededArtifacts": ["src/modules/room_bookings/index.ts", "src/modules/room_bookings/data/entities.ts"], "precondition": "oracle.workflow.durable-timer must fail" },
|
|
47
|
-
"omh-192": { "purpose": "Partial CRM-backed library loan slice that trusts payload scope, races checkout, inverts lifecycle undo, and ships non-executable Jest coverage.", "seededArtifacts": ["src/modules/library/commands/crm-loans.ts", "src/modules/library/api/schemas.ts", "src/modules/library/commands/__tests__/crm-loans.test.ts"], "precondition": "oracle.regression.crm-library must fail" }
|
|
47
|
+
"omh-192": { "purpose": "Partial CRM-backed library loan slice that trusts payload scope, races checkout, inverts lifecycle undo, and ships non-executable Jest coverage.", "seededArtifacts": ["src/modules/library/commands/crm-loans.ts", "src/modules/library/api/schemas.ts", "src/modules/library/commands/__tests__/crm-loans.test.ts"], "precondition": "oracle.regression.crm-library must fail" },
|
|
48
|
+
"planning-new-feature": { "purpose": "Fresh scaffold whose .ai/specs holds only the emitted scaffolding — README, blank template, and the shipped reference-module activation spec — none of which covers the requested capability.", "seededArtifacts": [], "precondition": "oracle.planning.spec-first must fail" },
|
|
49
|
+
"planning-existing-spec": { "purpose": "Covering specification for reminders on a confirmed appointment, seeded without the rescheduled/cancelled and per-channel outcome contract the prompt introduces.", "seededArtifacts": [".ai/specs/2026-08-04-service-appointment-reminders.md"], "precondition": "oracle.planning.spec-reuse must fail" }
|
|
48
50
|
}
|
|
49
51
|
}
|
|
@@ -157,6 +157,10 @@
|
|
|
157
157
|
"src/modules/library/commands/crm-loans.ts": "export type TrustedScope = { tenantId?: string; organizationId?: string }\nexport type LibraryEffects = {\n createBook(record: Record<string, unknown>, scope: TrustedScope): Promise<Record<string, unknown>>\n softDeleteBook(id: string, scope: TrustedScope): Promise<Record<string, unknown>>\n restoreBook(id: string, scope: TrustedScope): Promise<Record<string, unknown>>\n resolveCustomer(id: string, scope: TrustedScope): Promise<{ id: string; displayName: string }>\n findActiveLoan(bookId: string, scope: TrustedScope): Promise<Record<string, unknown> | undefined>\n createLoan(input: Record<string, unknown>, scope: TrustedScope): Promise<Record<string, unknown>>\n claimCheckout(input: Record<string, unknown>, scope: TrustedScope): Promise<Record<string, unknown>>\n findLoan(id: string, scope: TrustedScope): Promise<Record<string, unknown> | undefined>\n updateLoan(id: string, scope: TrustedScope, patch: Record<string, unknown>): Promise<Record<string, unknown>>\n}\n\ntype ScopedInput = { tenantId?: string; organizationId?: string }\nconst payloadScope = (input: ScopedInput): TrustedScope => ({ tenantId: input.tenantId, organizationId: input.organizationId })\n\nexport async function createBook(input: { id: string; title: string } & ScopedInput, _scope: TrustedScope, effects: LibraryEffects) {\n return effects.createBook(input, payloadScope(input))\n}\n\nexport async function undoCreateBook(id: string, scope: TrustedScope, effects: LibraryEffects) {\n return effects.restoreBook(id, scope)\n}\n\nexport async function deleteBook(id: string, scope: TrustedScope, effects: LibraryEffects) {\n return effects.softDeleteBook(id, scope)\n}\n\nexport async function undoDeleteBook(id: string, scope: TrustedScope, effects: LibraryEffects) {\n return effects.softDeleteBook(id, scope)\n}\n\nexport async function checkoutBook(input: { bookId: string; customerEntityId: string; idempotencyKey: string } & ScopedInput, _scope: TrustedScope, effects: LibraryEffects) {\n const scope = payloadScope(input)\n const active = await effects.findActiveLoan(input.bookId, scope)\n if (active) return { status: 'conflict' }\n const customer = await effects.resolveCustomer(input.customerEntityId, scope)\n const loan = await effects.createLoan({ bookId: input.bookId, memberId: customer.id, idempotencyKey: input.idempotencyKey }, scope)\n return { status: 'created', loan }\n}\n\nexport async function returnLoan(input: { id: string } & ScopedInput, _scope: TrustedScope, effects: LibraryEffects) {\n const scope = payloadScope(input)\n await effects.findLoan(input.id, scope)\n return effects.updateLoan(input.id, scope, { status: 'returned' })\n}\n\nexport async function renewLoan(input: { id: string } & ScopedInput, _scope: TrustedScope, effects: LibraryEffects) {\n const scope = payloadScope(input)\n await effects.findLoan(input.id, scope)\n return effects.updateLoan(input.id, scope, { status: 'renewed' })\n}\n\nexport async function markLoanLost(input: { id: string } & ScopedInput, _scope: TrustedScope, effects: LibraryEffects) {\n const scope = payloadScope(input)\n await effects.findLoan(input.id, scope)\n return effects.updateLoan(input.id, scope, { status: 'lost' })\n}\n",
|
|
158
158
|
"src/modules/library/api/schemas.ts": "import { z } from 'zod'\n\nexport const createBookRequestSchema = z.object({\n title: z.string().min(1),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n})\n\nexport const checkoutBookRequestSchema = z.object({\n bookId: z.string().uuid(),\n customerEntityId: z.string().uuid(),\n idempotencyKey: z.string().min(1),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n})\n",
|
|
159
159
|
"src/modules/library/commands/__tests__/crm-loans.test.ts": "import { createBook } from '../crm-loans'\n\ndescribe('CRM library loans', () => {\n it('persists a book', async () => {\n const create = jest.fn(async (record) => record)\n await createBook({ id: 'book-a', title: 'Book', tenantId: 'tenant-a', organizationId: 'org-a' }, { tenantId: 'tenant-a', organizationId: 'org-a' }, { createBook: create } as never)\n expect(create).toHaveBeenCalledTimes(2)\n })\n})\n"
|
|
160
|
+
},
|
|
161
|
+
"planning-new-feature": {},
|
|
162
|
+
"planning-existing-spec": {
|
|
163
|
+
".ai/specs/2026-08-04-service-appointment-reminders.md": "# Service Appointment Reminders\n\n**Date**: 2026-08-04\n**Status**: Ready for implementation\n\n## TLDR\n\nBranch staff spend part of every afternoon telephoning customers about tomorrow's confirmed appointment. This slice sends that reminder automatically for a confirmed appointment so staff keep the phone free for booking work and the customer still arrives on the agreed day.\n\n## Problem Statement\n\nEvery service branch books work into an appointment diary, and a booking becomes real for the customer only once a member of staff marks it confirmed. Today nothing tells the customer about that confirmation except a manual telephone call made the afternoon before the visit. Two branches keep a paper call list, one keeps a spreadsheet, and none of them records whether the call was ever made. When the afternoon is busy the calls are skipped, the customer forgets, the technician arrives at an empty address, and the branch loses a whole slot it could have sold to somebody else. Staff also cannot tell an auditing manager which customers were actually contacted, so a complaint about a missed visit turns into an argument about memory rather than a look at a record. The branches have asked for the reminder to leave the diary automatically once an appointment is confirmed, and for the app to keep the proof that it went out.\n\n## Users, Permissions, and Scope\n\n| Actor | Allowed outcomes | Scope rule | Required feature IDs |\n|---|---|---|---|\n| Branch staff | view the reminder history for an appointment | own organization | `appointment_reminders.view` |\n| Branch manager | view history and trigger one manual resend | own organization | `appointment_reminders.manage` |\n\nBoth the tenant and the organization are always derived from the trusted request context. A reminder record is written with the same scope as the appointment that produced it, and every read filters on that scope so one branch can never see another branch's customer contact history.\n\n## API, Command, and Error Contracts\n\n| Method / command | Path / ID | Auth and feature gate | Input | Success response / event | Errors and concurrency |\n|---|---|---|---|---|---|\n| `GET` | `/api/appointment-reminders` | auth + `appointment_reminders.view` | `appointmentId`, `page`, `pageSize` | `{ items, totalCount }` | 400 invalid query, 401 unauthenticated, 403 wrong feature |\n| `POST` | `/api/appointment-reminders/resend` | auth + `appointment_reminders.manage` | `appointmentId`, `reason` | 201 and `appointment_reminders.reminder.sent` | 400 invalid body, 403 wrong feature, 409 stale appointment version |\n\nThe list route is built on the CRUD route factory and returns only reminder rows for appointments inside the caller's trusted scope. The resend command is a guarded command route rather than a plain handler because it has an external side effect: it loads the appointment, refuses the write when the caller's appointment version is behind the stored one, records a new reminder row, and only then hands the message to the mail sender. The command carries an idempotency key derived from the appointment identifier and the scheduled reminder moment, so a retry after a transport timeout reuses the existing row instead of contacting the same customer twice. A reminder row stores the appointment identifier, the address it was sent to, the moment it was queued, and the moment the sender accepted it.\n\n## Integration Coverage\n\nTests are self-contained: each one creates its own tenant, organization, staff user, customer, and appointment, and removes those records in a `finally` block.\n\n| Test ID | Level | Setup / fixture | Actions | Assertions |\n|---|---|---|---|---|\n| TEST-001 | integration | one organization, one confirmed appointment for tomorrow | run the reminder worker | one reminder row exists, the sender received one message, and a second worker run adds nothing |\n| TEST-002 | security | two organizations, one appointment each | read the list route as the first organization's staff | only the caller's own reminder row is returned and no identifier from the other organization leaks |\n| TEST-003 | integration | one confirmed appointment with an existing reminder | call the resend command twice with the same idempotency key | exactly one additional reminder row exists and the second call reports the first result |\n\n## Implementation Phases\n\nPhases are dependency ordered, and each one leaves the application working on its own.\n\n### Phase 1 — Reminder record and scoped read path\n\n- **Depends on:** none\n- **Outcome:** staff can open an appointment and see whether a reminder was recorded for it.\n- **Deliverables:** the reminder entity with its tenant and organization columns, its migration, the zod validators, the list route on the CRUD route factory, and the feature identifiers in the access-control declaration.\n- **Tests:** TEST-001, TEST-002\n- **Validation:** `yarn generate`, focused typecheck, and the two named integration tests.\n- **Exit gate:** a reminder row created by hand in one organization is visible to that organization's staff and invisible to another organization's staff.\n\n### Phase 2 — Automatic send for a confirmed appointment\n\n- **Depends on:** Phase 1 exit gate\n- **Outcome:** a confirmed appointment produces its reminder without anyone touching the diary.\n- **Deliverables:** the scheduled worker that selects tomorrow's confirmed appointments, the guarded resend command, the idempotency key, and the typed event emitted after the sender accepts the message.\n- **Tests:** TEST-003\n- **Validation:** focused worker and command tests plus the named integration test.\n- **Exit gate:** running the worker twice over the same confirmed appointment contacts the customer exactly once, and a manual resend is recorded as a separate audited row.\n\n## Risks and Tradeoffs\n\n| Risk / tradeoff | Impact | Mitigation / detection | Residual risk |\n|---|---|---|---|\n| A transport timeout is retried and contacts the customer twice | annoyed customer, lost trust | idempotency key on appointment and scheduled moment, asserted by TEST-003 | a sender that accepts and then silently drops a message is not detectable here |\n| The worker runs long after the confirmed appointment has already started | a useless reminder | the worker selects only appointments that start after the run moment | clock skew between the worker host and the diary |\n\n## Changelog\n\n| Date | Change |\n|---|---|\n| 2026-08-04 | Initial covering specification for reminders on a confirmed appointment. |\n"
|
|
160
164
|
}
|
|
161
165
|
}
|
|
162
166
|
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://open-mercato.dev/schemas/standalone-harness-knowledge-change.schema.json",
|
|
4
|
+
"title": "Open Mercato standalone harness knowledge-change run manifest",
|
|
5
|
+
"description": "Validation artifact for a harness knowledge-contract or asset-sync change. Authored input declares the intended contract surface; the controller resolves SHAs and focused base/head execution evidence. Authored input MUST omit resolvedBaseSha, headSha, and focusedExecutions.",
|
|
6
|
+
"$ref": "#/$defs/authoredManifest",
|
|
7
|
+
"$defs": {
|
|
8
|
+
"sha256": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
11
|
+
},
|
|
12
|
+
"gitSha": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"pattern": "^[0-9a-f]{40}$"
|
|
15
|
+
},
|
|
16
|
+
"gitRef": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"minLength": 1,
|
|
19
|
+
"maxLength": 200
|
|
20
|
+
},
|
|
21
|
+
"exactPath": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"minLength": 1,
|
|
24
|
+
"maxLength": 400,
|
|
25
|
+
"pattern": "^(?!/)(?![A-Za-z]:)(?!.*(?:^|/)\\.\\.(?:/|$))(?!.*//)[^*?\\\\<>|\"]+(?<!/)$",
|
|
26
|
+
"description": "Repository-relative POSIX path to one exact regular file. Absolute paths, parent traversal, wildcards, and directory targets are rejected."
|
|
27
|
+
},
|
|
28
|
+
"caseId": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"pattern": "^OMH-[0-9]{3}$"
|
|
31
|
+
},
|
|
32
|
+
"rangeId": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"pattern": "^OMH-[0-9]{3}\\.\\.OMH-[0-9]{3}$",
|
|
35
|
+
"description": "Inclusive contiguous case-ID range, low bound first."
|
|
36
|
+
},
|
|
37
|
+
"laneId": {
|
|
38
|
+
"enum": [
|
|
39
|
+
"deterministic",
|
|
40
|
+
"routing",
|
|
41
|
+
"writable",
|
|
42
|
+
"generatedCodeReview",
|
|
43
|
+
"generativeJudge",
|
|
44
|
+
"generatedTests"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"changedContract": {
|
|
48
|
+
"enum": [
|
|
49
|
+
"routing",
|
|
50
|
+
"skill-link",
|
|
51
|
+
"source-link",
|
|
52
|
+
"example-source",
|
|
53
|
+
"installed-source",
|
|
54
|
+
"discovery",
|
|
55
|
+
"context-read",
|
|
56
|
+
"evaluator",
|
|
57
|
+
"oracle"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"authoritativeFile": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"additionalProperties": false,
|
|
63
|
+
"required": ["path", "sha256"],
|
|
64
|
+
"properties": {
|
|
65
|
+
"path": { "$ref": "#/$defs/exactPath" },
|
|
66
|
+
"sha256": { "$ref": "#/$defs/sha256" }
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"generatedFile": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"additionalProperties": false,
|
|
72
|
+
"required": ["path", "sha256", "sourcePath"],
|
|
73
|
+
"properties": {
|
|
74
|
+
"path": { "$ref": "#/$defs/exactPath" },
|
|
75
|
+
"sha256": { "$ref": "#/$defs/sha256" },
|
|
76
|
+
"sourcePath": { "$ref": "#/$defs/exactPath" }
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"sourceLinkInventory": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"additionalProperties": false,
|
|
82
|
+
"required": [
|
|
83
|
+
"path",
|
|
84
|
+
"baselineRef",
|
|
85
|
+
"expectedOwnerCount",
|
|
86
|
+
"expectedTopicCount",
|
|
87
|
+
"resolvedLinkCount",
|
|
88
|
+
"baselineAssetCount",
|
|
89
|
+
"baselineDispositionCount",
|
|
90
|
+
"baselinePath",
|
|
91
|
+
"baselineSchemaPath"
|
|
92
|
+
],
|
|
93
|
+
"properties": {
|
|
94
|
+
"path": { "$ref": "#/$defs/exactPath" },
|
|
95
|
+
"baselineRef": { "$ref": "#/$defs/gitSha" },
|
|
96
|
+
"expectedOwnerCount": { "type": "integer", "minimum": 0 },
|
|
97
|
+
"expectedTopicCount": { "type": "integer", "minimum": 0 },
|
|
98
|
+
"resolvedLinkCount": { "type": "integer", "minimum": 0 },
|
|
99
|
+
"baselineAssetCount": { "type": "integer", "minimum": 0 },
|
|
100
|
+
"baselineDispositionCount": { "type": "integer", "minimum": 0 },
|
|
101
|
+
"baselinePath": { "$ref": "#/$defs/exactPath" },
|
|
102
|
+
"baselineSchemaPath": { "$ref": "#/$defs/exactPath" }
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"executionOutcome": {
|
|
106
|
+
"type": "object",
|
|
107
|
+
"additionalProperties": false,
|
|
108
|
+
"required": ["exitCode", "stdoutSha256", "stderrSha256"],
|
|
109
|
+
"properties": {
|
|
110
|
+
"exitCode": { "type": "integer", "minimum": 0, "maximum": 255 },
|
|
111
|
+
"stdoutSha256": { "$ref": "#/$defs/sha256" },
|
|
112
|
+
"stderrSha256": { "$ref": "#/$defs/sha256" }
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"focusedExecution": {
|
|
116
|
+
"type": "object",
|
|
117
|
+
"additionalProperties": false,
|
|
118
|
+
"required": ["testFile", "command", "baseWithTestPatch", "head"],
|
|
119
|
+
"properties": {
|
|
120
|
+
"testFile": { "$ref": "#/$defs/exactPath" },
|
|
121
|
+
"command": {
|
|
122
|
+
"type": "array",
|
|
123
|
+
"minItems": 1,
|
|
124
|
+
"items": {
|
|
125
|
+
"type": "string",
|
|
126
|
+
"minLength": 1,
|
|
127
|
+
"pattern": "^[^`$;&|<>\\n]*$",
|
|
128
|
+
"description": "One argv token. Shell metacharacters are rejected; the controller never interpolates a shell."
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"baseWithTestPatch": { "$ref": "#/$defs/executionOutcome" },
|
|
132
|
+
"head": { "$ref": "#/$defs/executionOutcome" }
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"manifest": {
|
|
136
|
+
"type": "object",
|
|
137
|
+
"additionalProperties": false,
|
|
138
|
+
"required": [
|
|
139
|
+
"changeClass",
|
|
140
|
+
"baseRef",
|
|
141
|
+
"affectedCaseIds",
|
|
142
|
+
"affectedRanges",
|
|
143
|
+
"changedContracts",
|
|
144
|
+
"focusedTestFiles",
|
|
145
|
+
"authoritativeFiles",
|
|
146
|
+
"generatedFiles",
|
|
147
|
+
"expectedCatalogCount",
|
|
148
|
+
"requiredReleaseLanes",
|
|
149
|
+
"documentationFiles",
|
|
150
|
+
"sourceLinkInventory"
|
|
151
|
+
],
|
|
152
|
+
"properties": {
|
|
153
|
+
"changeClass": { "enum": ["knowledge-contract", "asset-sync"] },
|
|
154
|
+
"baseRef": { "$ref": "#/$defs/gitRef" },
|
|
155
|
+
"resolvedBaseSha": { "$ref": "#/$defs/gitSha" },
|
|
156
|
+
"headSha": { "$ref": "#/$defs/gitSha" },
|
|
157
|
+
"affectedCaseIds": {
|
|
158
|
+
"type": "array",
|
|
159
|
+
"uniqueItems": true,
|
|
160
|
+
"items": { "$ref": "#/$defs/caseId" }
|
|
161
|
+
},
|
|
162
|
+
"affectedRanges": {
|
|
163
|
+
"type": "array",
|
|
164
|
+
"uniqueItems": true,
|
|
165
|
+
"items": { "$ref": "#/$defs/rangeId" }
|
|
166
|
+
},
|
|
167
|
+
"changedContracts": {
|
|
168
|
+
"type": "array",
|
|
169
|
+
"uniqueItems": true,
|
|
170
|
+
"items": { "$ref": "#/$defs/changedContract" }
|
|
171
|
+
},
|
|
172
|
+
"focusedTestFiles": {
|
|
173
|
+
"type": "array",
|
|
174
|
+
"uniqueItems": true,
|
|
175
|
+
"items": { "$ref": "#/$defs/exactPath" }
|
|
176
|
+
},
|
|
177
|
+
"authoritativeFiles": {
|
|
178
|
+
"type": "array",
|
|
179
|
+
"uniqueItems": true,
|
|
180
|
+
"items": { "$ref": "#/$defs/authoritativeFile" }
|
|
181
|
+
},
|
|
182
|
+
"generatedFiles": {
|
|
183
|
+
"type": "array",
|
|
184
|
+
"uniqueItems": true,
|
|
185
|
+
"items": { "$ref": "#/$defs/generatedFile" }
|
|
186
|
+
},
|
|
187
|
+
"expectedCatalogCount": { "type": "integer", "minimum": 0 },
|
|
188
|
+
"requiredReleaseLanes": {
|
|
189
|
+
"type": "array",
|
|
190
|
+
"uniqueItems": true,
|
|
191
|
+
"items": { "$ref": "#/$defs/laneId" }
|
|
192
|
+
},
|
|
193
|
+
"documentationFiles": {
|
|
194
|
+
"type": "array",
|
|
195
|
+
"uniqueItems": true,
|
|
196
|
+
"items": { "$ref": "#/$defs/exactPath" }
|
|
197
|
+
},
|
|
198
|
+
"sourceLinkInventory": { "$ref": "#/$defs/sourceLinkInventory" },
|
|
199
|
+
"focusedExecutions": {
|
|
200
|
+
"type": "array",
|
|
201
|
+
"uniqueItems": true,
|
|
202
|
+
"items": { "$ref": "#/$defs/focusedExecution" }
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"authoredManifest": {
|
|
207
|
+
"allOf": [
|
|
208
|
+
{ "$ref": "#/$defs/manifest" },
|
|
209
|
+
{
|
|
210
|
+
"not": {
|
|
211
|
+
"anyOf": [
|
|
212
|
+
{ "required": ["resolvedBaseSha"] },
|
|
213
|
+
{ "required": ["headSha"] },
|
|
214
|
+
{ "required": ["focusedExecutions"] }
|
|
215
|
+
]
|
|
216
|
+
},
|
|
217
|
+
"description": "resolvedBaseSha, headSha, and focusedExecutions are controller-owned output fields; author-supplied evidence fails validation."
|
|
218
|
+
}
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
"completedManifest": {
|
|
222
|
+
"allOf": [
|
|
223
|
+
{ "$ref": "#/$defs/manifest" },
|
|
224
|
+
{ "required": ["resolvedBaseSha", "headSha", "focusedExecutions"] }
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"OMH-093", "OMH-105", "OMH-107", "OMH-115", "OMH-122", "OMH-128", "OMH-130", "OMH-133",
|
|
26
26
|
"OMH-137", "OMH-140", "OMH-144", "OMH-146", "OMH-149", "OMH-150", "OMH-151", "OMH-153",
|
|
27
27
|
"OMH-156", "OMH-163", "OMH-164", "OMH-165", "OMH-171", "OMH-172", "OMH-181", "OMH-185",
|
|
28
|
-
"OMH-188", "OMH-189", "OMH-190", "OMH-191", "OMH-192", "OMH-193"
|
|
28
|
+
"OMH-188", "OMH-189", "OMH-190", "OMH-191", "OMH-192", "OMH-193",
|
|
29
|
+
"OMH-223", "OMH-224"
|
|
29
30
|
]
|
|
30
31
|
},
|
|
31
32
|
"runners": {
|
|
@@ -79,7 +80,9 @@
|
|
|
79
80
|
{ "caseId": "OMH-190" },
|
|
80
81
|
{ "caseId": "OMH-191" },
|
|
81
82
|
{ "caseId": "OMH-192" },
|
|
82
|
-
{ "caseId": "OMH-193" }
|
|
83
|
+
{ "caseId": "OMH-193" },
|
|
84
|
+
{ "caseId": "OMH-223" },
|
|
85
|
+
{ "caseId": "OMH-224" }
|
|
83
86
|
],
|
|
84
87
|
"generatedCodeReview": {
|
|
85
88
|
"required": true,
|
|
@@ -92,7 +95,8 @@
|
|
|
92
95
|
"OMH-130", "OMH-133", "OMH-137", "OMH-140", "OMH-144", "OMH-146",
|
|
93
96
|
"OMH-149", "OMH-150", "OMH-151", "OMH-153", "OMH-156", "OMH-163",
|
|
94
97
|
"OMH-164", "OMH-165", "OMH-171", "OMH-172", "OMH-181", "OMH-185",
|
|
95
|
-
"OMH-188", "OMH-189", "OMH-190", "OMH-191", "OMH-192", "OMH-193"
|
|
98
|
+
"OMH-188", "OMH-189", "OMH-190", "OMH-191", "OMH-192", "OMH-193",
|
|
99
|
+
"OMH-223", "OMH-224"
|
|
96
100
|
],
|
|
97
101
|
"runners": {
|
|
98
102
|
"codex": { "modelSelector": "default" },
|
|
@@ -115,7 +119,8 @@
|
|
|
115
119
|
"OMH-130", "OMH-133", "OMH-137", "OMH-140", "OMH-144", "OMH-146",
|
|
116
120
|
"OMH-149", "OMH-150", "OMH-151", "OMH-153", "OMH-156", "OMH-163",
|
|
117
121
|
"OMH-164", "OMH-165", "OMH-171", "OMH-172", "OMH-181", "OMH-185",
|
|
118
|
-
"OMH-188", "OMH-189", "OMH-190", "OMH-191", "OMH-192", "OMH-193"
|
|
122
|
+
"OMH-188", "OMH-189", "OMH-190", "OMH-191", "OMH-192", "OMH-193",
|
|
123
|
+
"OMH-223", "OMH-224"
|
|
119
124
|
],
|
|
120
125
|
"runners": {
|
|
121
126
|
"codex": { "modelSelector": "default" },
|
|
@@ -25,6 +25,66 @@
|
|
|
25
25
|
"status": { "enum": ["pass", "fail", "error"] },
|
|
26
26
|
"sanitizedError": { "type": "string", "maxLength": 4096 },
|
|
27
27
|
"refusedContextReads": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
|
28
|
+
"exampleReadPolicy": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"description": "Sanitized accounting of the case's canonical-example, declared source-reference, and reason-gated installed-source reads. Present when the case declares context.exampleRoots or context.sourceReferenceIds. Carries no file content.",
|
|
31
|
+
"additionalProperties": false,
|
|
32
|
+
"required": ["roots", "fallback", "references"],
|
|
33
|
+
"properties": {
|
|
34
|
+
"references": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"description": "Declared source-link references: what the case named, which origin owners it read first, and which exact targets it followed. Carries no file content.",
|
|
37
|
+
"additionalProperties": false,
|
|
38
|
+
"required": ["declared", "owners", "followed"],
|
|
39
|
+
"properties": {
|
|
40
|
+
"declared": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
|
41
|
+
"owners": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
|
42
|
+
"followed": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"items": {
|
|
45
|
+
"type": "object",
|
|
46
|
+
"additionalProperties": false,
|
|
47
|
+
"required": ["referenceId", "originAsset", "resolvedPath", "targetKind", "package", "version", "hash"],
|
|
48
|
+
"properties": {
|
|
49
|
+
"referenceId": { "type": "string" },
|
|
50
|
+
"originAsset": { "type": "string" },
|
|
51
|
+
"resolvedPath": { "type": "string" },
|
|
52
|
+
"targetKind": { "type": ["string", "null"] },
|
|
53
|
+
"package": { "type": ["string", "null"] },
|
|
54
|
+
"version": { "type": ["string", "null"] },
|
|
55
|
+
"hash": { "type": ["string", "null"] }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"roots": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"additionalProperties": false,
|
|
66
|
+
"required": ["root", "entrypoints", "capabilities", "files", "bytes"],
|
|
67
|
+
"properties": {
|
|
68
|
+
"root": { "type": "string" },
|
|
69
|
+
"entrypoints": { "type": "array", "items": { "type": "string" } },
|
|
70
|
+
"capabilities": { "type": "array", "uniqueItems": true, "items": { "type": "string" } },
|
|
71
|
+
"files": { "type": "integer", "minimum": 0 },
|
|
72
|
+
"bytes": { "type": "integer", "minimum": 0 }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"fallback": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"additionalProperties": false,
|
|
79
|
+
"required": ["reason", "files", "bytes"],
|
|
80
|
+
"properties": {
|
|
81
|
+
"reason": { "type": ["string", "null"], "enum": ["SPECIALIST_ROUTE_NOT_DECLARED", "INSTALLED_VERSION_CONTRACT_MISMATCH", null] },
|
|
82
|
+
"files": { "type": "integer", "minimum": 0 },
|
|
83
|
+
"bytes": { "type": "integer", "minimum": 0 }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
28
88
|
"actualContext": {
|
|
29
89
|
"type": "object",
|
|
30
90
|
"additionalProperties": false,
|
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
"selectedSkills": { "type": "array", "items": { "type": "string", "pattern": "^om-[a-z0-9-]+$", "maxLength": 100 } },
|
|
8
8
|
"selectedContext": { "type": "array", "items": { "type": "string", "maxLength": 300 } },
|
|
9
9
|
"decisions": { "type": "array", "items": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$", "maxLength": 100 } },
|
|
10
|
+
"specRouting": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"additionalProperties": false,
|
|
13
|
+
"required": ["decision", "reasonCodes"],
|
|
14
|
+
"properties": {
|
|
15
|
+
"decision": { "type": "string", "enum": ["spec-first", "direct", "reuse-spec", "ask"] },
|
|
16
|
+
"reasonCodes": { "type": "array", "minItems": 1, "maxItems": 8, "uniqueItems": true, "items": { "type": "string", "pattern": "^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$", "maxLength": 60 } },
|
|
17
|
+
"coveringSpecPath": { "type": "string", "maxLength": 300 }
|
|
18
|
+
}
|
|
19
|
+
},
|
|
10
20
|
"violations": { "type": "array", "items": { "type": "string", "maxLength": 4096 } }
|
|
11
21
|
}
|
|
12
22
|
}
|