NEXT
Checks / test (push) Failing after 2m25s

This commit is contained in:
Ultradesu committed 2026-10-07 15:30:31 +01:00
1 parent e37d583179
commit 5260c2828b
65 files changed
+8469 -380

No files matched your search

+71 -3
View File
@@ -10,7 +10,7 @@ Users, sessions, workspaces, memberships, audit, history, provider checkpoints,
Cot 0.7 has no transaction API. `Store::commit` uses one parameterized data-modifying PostgreSQL CTE through Cot `Database::raw_with`: compare-and-swap checks revision and authorization, then writes membership, history, audit, and the durable sync request atomically. A constraint failure rolls the entire statement back. Ordinary reads, sessions, and checkpoints use Cot queries/models. Pending requests do not change effective coverage. Published state is separate from desired state.
The worker conditionally claims a five-minute lease token. Publication has a four-minute deadline and HTTP requests a twenty-second timeout; no document lock spans HTTP. Verified operations get checkpoints. Completion updates status and audit atomically, guarded by the lease token. Newer revisions remain queued when older runs succeed or fail. Jobs retry with bounded backoff; fifteen-minute reconciliation extends the horizon and detects drift. Crashed workers leave recoverable leases. This is not a distributed fencing protocol: read-back/conflict handling remains essential after process suspension or an uncertain remote timeout.
The worker conditionally claims a five-minute lease token. Publication has a four-minute deadline and HTTP requests a twenty-second timeout; no document lock spans HTTP. Verified operations get checkpoints. Completion updates status and audit atomically, guarded by the lease token. Newer revisions remain staged when older runs succeed or fail. Authorized jobs retry their pinned document with bounded backoff; a successful publication runs again only after another explicit Sync. Crashed workers leave recoverable leases. This is not a distributed fencing protocol: read-back/conflict handling remains essential after process suspension or an uncertain remote timeout.
Run Cot migrations once in a deployment job, then start replicas with `MEGURI_SKIP_MIGRATIONS=true`. The initial migration creates frozen Cot models; the second adds scoped foreign keys, constraints, and indexes in one atomic PostgreSQL block. A JSM destination can have only one local workspace binding. Never edit applied migrations.
@@ -34,9 +34,15 @@ Replacement preview is a read-only service using the same engine, revision, part
## Provider contract
Operations collection reads use pages of at most 50 items and traverse every page for ownership recovery and drift checks. Team identifiers retain the optional `og-` prefix through validation, storage and HTTP paths.
Readable provider names append the first 128 bits of SHA-256 over workspace and resource UUID bytes. Discovery matches this stable suffix or the legacy full technical name; duplicate matches fail. Checkpointed resources rename in place. Recovery without a checkpoint accepts the legacy name only when every other managed field matches the desired state.
Publication includes the explicit compilation clock `as_of`. For plans with boundaries outside local half-hour marks, the adapter uses the currently effective assignee as a finite base rotation, or `noone` if coverage has not started. Future assignments use schedule overrides with millisecond precision; future gaps and the rounded base tail use `noone` overrides. Native base endpoints are rounded outward to local half-hour marks; current/future effective coverage remains exact. JSM rejects new overrides starting in the past, so publication guarantees coverage from `as_of` forward without rewriting local history. A transition overtaken by HTTP latency fails and is recomputed on retry. Coverage checkpoints contain parent schedule ID, expected payload and returned alias; an empty alias records a durable create intent. Recovery claims a matching remote override only against such an intent, rejects ambiguous matches, and verifies read-back before recording success. Stale owned intervals are removed after replacements are written; unknown/manual overrides still block unless overwrite is explicit. Expired owned intervals may disappear from the provider's ongoing/future collection without being drift. Rotation arrays are compared without order only for these independent generated intervals; escalation and participant order remains significant.
The `Provider` trait consumes canonical `Publication` data and a checkpoint store. Plugins are Rust modules linked at build time, without an unstable dynamic-library ABI. New providers add a typed integration variant, capability validation, dispatcher constructor, module, and contract tests. No engine changes should be needed.
JSM publishes finite single-person rotations with exact timestamps (maximum 500 per schedule). Escalations resolve local IDs to remote IDs; routing priorities become consecutive indices. Deterministic ownership names allow recovery when a create succeeds but its local checkpoint is lost. Read-back checks managed fields, arrays, timestamps, and external overrides. Only checkpointed owned resources may be deleted. Workspace-specific environment credentials never enter documents or audit.
JSM publishes finite single-person rotations for half-hour-aligned plans, and base rotations plus exact future overrides otherwise (maximum 500 canonical periods per schedule). Escalations resolve local IDs to remote IDs; routing priorities become consecutive indices. Deterministic ownership names allow recovery when a create succeeds but its local checkpoint is lost. Read-back checks managed fields, arrays, timestamps, and external overrides. Only checkpointed owned resources may be deleted. Workspace-specific environment credentials never enter documents or audit.
Reconciliation covers configuration, not user notification preferences, forwarding rules, or delivered notifications. JSM has no cross-resource transaction here: partially published revisions stay failed until retries complete. A remote edit between GET and PATCH cannot be fenced with the local lease. A dedicated-team acceptance test must compare actual provider timelines as well as CRUD.
@@ -111,10 +117,72 @@ Variable-tree indentation uses stylesheet depth classes, not inline custom prope
Generation map opens from Generation rules as a read-only, draggable/zoomable Cytoscape canvas. Server preview returns actual iteration counts, input contexts, predicate outcomes and produced IDs; no scheduling evaluation is duplicated in JavaScript. Iterated outputs start collapsed into a group; inspecting a node or pass reveals source data and verified resources. Invalid drafts show diagnostics rather than stale resources. The map is a captured draft preview refreshed explicitly, and never applies changes. Bundled Cytoscape 3.33.1 is served locally with its MIT license; no CDN or new framework is required. Browser coverage checks groups, details, source navigation, pan/zoom and mobile layout; engine regression verifies traced pass results.
The generation map arranges numbered rules in saved execution order from left to right, joined by solid sequence arrows. Each rule owns a vertical column of iterations, conditions and outputs. Dashed secondary edges show data dependencies rather than execution order. Repeated output groups use offset background cards; decorative layers follow dragging and do not receive selection. Browser checks verify rule ordering, aligned output columns and stack movement.
The generation map arranges numbered rules in saved execution order from left to right, joined by solid sequence arrows. Variables occupy the upper band in first-consumer order, rules and their iterations and conditions occupy the middle band, and outputs occupy their producer columns in the lower resource band. Dashed edges show data dependencies. Repeated output groups expand into individual resources within the resource band. Browser checks verify rule ordering, band separation, output expansion and manual resources.
Map input details display evaluated server values for each block and pass, never serialized bindings. Shared values are deduplicated across passes; differing values are explicitly counted. Generated references collapse to type/name cards, and people resolve by display name. Empty binding metadata and raw reference UUIDs are not presented. Condition operands and escalation recipients/delays come from the same resolver used during expansion.
The map’s all-passes input overview lists deduplicated upstream sources, not expanded output settings: variables with used binding addresses and resource references grouped by producing block. References internal to the selected whole rule are omitted; selecting an individual output block shows its dependencies. Selecting a concrete pass still exposes its evaluated field values.
Expanded map resources use type-specific labeled fields and the same compact reference cards as inputs, never JSON dumps. Priority schedules show ordered people, fallback and zoned handover; rotations add anchor/cycle; policies show recipient/timing/condition and repeat behavior; routes show conditions, working window and destination. Reference names resolve from the preview snapshot. Browser regression checks visible names, participant order and absence of UUID metadata.
When a checkpointed resource GET returns 404, discard its obsolete checkpoint and schedule child checkpoints, then rediscover the stable ownership marker before creating. This also recovers a replacement whose create response was lost. Do not query child collections of a missing parent. Rebuild dependent references with the new remote ID. A missing collection or authorization failure remains an error; only resource absence authorizes recreation.
## Explicit publication and shared drafts
Saving workspace configuration, approving replacements, importing data and editing generator drafts never authorize provider writes. These changes persist in PostgreSQL and are visible to other authorized members. Ordinary unfinished modal forms remain local until Save. Generator drafts autosave separately, including invalid intermediate values, with their own optimistic revision and workspace scope.
The top Review changes panel compares desired resources with the last successfully published document. Its Sync button is yellow when unpublished changes exist. Sync validates/applies the shared generator draft and explicitly authorizes a specific workspace revision; stale reviews fail. Provider status, errors and create/update/remove counts live in this panel. Failed authorized publications may retry the same snapshot; newer saved changes must never enter those retries. Successful jobs do not automatically refresh their horizon: the displayed coverage end requires a further explicit sync to extend it.
The worker persists the authorized document and publishes that snapshot, not the newest workspace document. A click while a publication lease is active is rejected. Existing jobs are paused by the manual-publication migration until an explicit click. Published snapshots survive history pruning. Tests cover no writes before a click, pinned retries across later edits, no periodic writes after success, scoped shared-draft persistence, stale concurrent edits, resource review against the published baseline, and the browser workflow across sessions.
## Compact recurring provider rotations
A plain base rotation whose effective published coverage matches its ordered calendar-day cycle is exported to JSM as one finite recurring rotation named after the schedule. The engine supplies the current cycle phase, ordered participants and calendar-day shift length; the provider only translates these fields to daily/weekly API values. The remote schedule ID and ownership marker stay unchanged. A publication replaces the old per-shift rotations rather than accumulating new ones. Native boundary precision must be representable; irregular effective coverage and replacements retain the exact interval export. The canonical expanded timeline remains available for verification and preview. Tests cover mid-shift starts, pre-anchor phases, participant ordering, DST, replacements, migration of an existing owned schedule and idempotent repeated publication.
When an owned JSM schedule has one current and one desired rotation, edits preserve the rotation ID through the dedicated rotation PATCH endpoint. Schedule metadata is patched without a rotations array. Verified intermediate writes are checkpointed; a durable pending-step snapshot recovers a lost response without mistaking that exact planned state for external drift. Tests model nested rotation replacement by schedule PATCH and require stable rotation identity across participant reorder, rename, retry and unchanged republish. Historical rows already retained by JSM are not deleted by this repair.
Workspace state save/reload controls live beside Sync in the top Review changes panel. The localized hint distinguishes shared draft autosave, validated local application, and explicit publication; Sync includes application, so a separate save is optional. Reload retrieves the shared draft, not a historical rollback. Removing a variable or generation rule requires confirmation before mutating or autosaving the draft. Browser regression covers cancellation, confirmation, top-panel controls and narrow layout.
JSM coverage rotation names use the schedule name, including priority coverage and the exact-time base rotation. Multiple finite rotations append the interval start in the schedule IANA timezone with date, time and UTC offset to distinguish DST folds. This is presentation only; ownership markers, coverage, checkpoints and explicit publication remain unchanged. Existing rotation names update on the next authorized synchronization.
Manual and generated routing editors expose the existing greater-than and less-than operations. Priority follows alert severity (P1 highest); P3 and above is represented as less-than P3 with negate=true, including the boundary. The editors show comparison controls without an additional priority instruction; the provider wire contract is unchanged.
Publication status exposes the lease expiry and a server-calculated publication_busy flag. Sync is disabled for an active lease, not merely the persisted publishing state. The review panel explains restart recovery and expired leases; normal polling refreshes eligibility. Restart never clears a live lease. PostgreSQL regression checks active-lease rejection and explicit reauthorization after expiry.
Nested binding paths retain the raw input text while typing, including trailing spaces and slash separators. The parsed path still updates live for shared drafts and server previews. Reopening shows the normalized path; changing source resets it. Browser regression types a nested list path character by character and checks its resolved value, edits, reopening and source reset.
JSM omits `repeat` when escalation repeats are disabled. Read-back and drift comparison accept an absent repeat field only for an expected escalation with `waitInterval: 0` (the provider disabled representation). Present repeat objects and enabled repeats remain strictly compared. Fake-server regressions reproduce omission, recovery without a checkpoint, idempotence and detection of externally enabled repeats. No overwrite policy is needed to recover an otherwise matching escalation.
Sync immediately shows submitting feedback, then stays disabled for an authorized pending job as well as an active publication lease. Pending publication has a visible queue message. The UI polls every two seconds while queued or leased and keeps the twenty-second idle refresh; expired leases remain manually recoverable. A successful sync request updates local queue status before refreshing the workspace. Browser regression holds the queued response and verifies disabled state and automatic completion without reload.
Generated escalation steps support Everyone on the team in addition to schedules and people. The optional team_all flag defaults to false for existing drafts; team recipients do not resolve an individual binding. They compile to Recipient::TeamAll and JSM uses the configured workspace integration team ID with notifyType=all. Delay and acknowledgment condition remain explicit. Generator, wire-contract and browser regressions cover the 30-minute team step and legacy recipients.
## Layered generation map and value provenance
The read-only map uses three separated horizontal bands: variables, generators, resources. Generator columns follow saved execution order; variables sort by first consumer, and generated resources occupy their producer column. Manual resources are included in the resource band with explicit manual attribution. Shapes distinguish bands; resource colors distinguish schedules, escalations and routes. Expanding output groups retains these bands.
Server preview provides binding provenance using the same resolver as generation: source bindings, iteration sources, lookup keys, list items, intermediate path values, final values, node identities and errors. The browser presents this captured snapshot rather than re-evaluating scheduling logic. An inspector popover supports history, source navigation and per-pass examples. Dotted address segments are independently colored, with neutral separators; quoted keys containing dots remain intact. Generated names retain separate bound and literal affix segments, and resource fields link to their binding or explicit default/manual origin. Clicking the map backdrop closes it; clicks on the canvas only clear selection. Tests cover provenance, layout, manual resources, source exploration and safe text rendering.
The value explorer renders source traversal as ordered monospace steps with neutral arrows and a selected-step indicator. Source navigation is a separate footer action; producer fields are independent choices rather than sequential path steps. Browser coverage checks stage values and separate source navigation.
## Portable generation configuration
[meguri/v2](portable-config.md) defines compact JSON import/export (with legacy v1 import support) for variables and generators only. Merge by name retains omitted inputs; nested identity keys preserve resource identity across editing and repeated imports. People transfer by email, manual resource references by exact name, and generated links by generator/block. The server provides a read-only parsed/expanded preview and revalidates before saving the shared draft with workspace and draft revisions. Provider writes require a later explicit Sync. Tests cover cross-workspace remapping, repeated imports, unknown fields, scoped permissions, stale previews, email contacts, parse errors and browser application.
### Compact portable configuration
`meguri/v2` is the default export: ordinary JSON variables, typed wrappers only for special scalar types, compact binding references, flattened output fields, readable output keys and omitted semantic defaults. The v1 importer remains supported. Inactive binding metadata must never be exported. Human output keys persist in shared drafts; list entries reconcile by unique name/value first and position for unmatched edits. The preview remains authoritative for identity-changing edits. Regression checks compare expanded resources, repeat imports and actual size reductions.
The Import / Export dialog includes a localized Guide tab with a complete compact v2 reference, defaults, binding scope, operations, limits, merge semantics and a runnable example covering all output types. Copy guide copies every section as Markdown for hand editing or LLM use, without workspace data. Switching tabs preserves import text and does not apply it. Browser checks verify copying, sample preview, tab preservation and mobile layout.
Generation steps preserve backward-compatible `team_all` and `team_random` flags, mutually exclusive with `user`. Team recipients ignore stale person/schedule bindings. The compiler emits `Recipient::TeamRandom`; JSM publishes it as a team recipient with `notifyType: random`.
## Site control plane
`site` owns global authorization, section-versioned settings, account access flags and an installation audit stream. Site mutations compare a global control revision and the actor role inside a single PostgreSQL statement; workspace metadata also compares its own revision. Site permissions never bypass workspace membership. Account suspension does not mutate historical scheduling state. Authentication configuration is stored as a typed section, but is intentionally not connected to login enforcement yet. A future identity adapter will consume the section after secure OIDC execution is implemented.
Approval calculation is shared by replacement and absence preview/save. Only actual workspace account participants other than the requester are approvers; unlinked email contacts never gain login, membership or privileges. Empty approval sets apply immediately through the same validated, atomic history/audit/staged-sync boundary, without forced_by. Requests involving a contact may be submitted on its behalf with EditSchedules; changes solely between other account holders retain the force requirement. Preview exposes the exact approval set for truthful UI status.
Account identity stores required unique normalized email in the user row. The domain User embeds its canonical Person (same ID); workspace Person records are snapshots, not independently editable account profiles. Directory, provider identity resolution and portable configuration use this email. Editing a linked person cannot change account identity; profile changes update current snapshots atomically while historical snapshots remain intact. Password signup never claims planning contacts merely by email.
The preparatory contact/account migration runs before account email enforcement on legacy databases. An explicit deployment email mapping authorizes association only in workspaces where the account is already a member. It rewrites current scheduling references, person-valued generator inputs, shared drafts and explicit provider identity keys, retaining resource IDs and old history/publication checkpoints. Missing/ambiguous mappings, conflicting provider identities or collapsed invalid schedules/replacements block the repair before writes. Already email-migrated installations are skipped. Regression coverage includes migration ordering, retry after failure, generator drafts and unchanged access/history.