Repository navigation
Closed
Labels
Description
The platform canary bumped every @objectstack/* range from ^17.3.0 to ^18.1.0 on claude/project-thread-fr21kk and ran the template's gates.
| gate | exit |
|---|---|
pnpm install |
0 |
pnpm validate |
1 |
pnpm typecheck |
2 |
pnpm test |
1 |
pnpm build |
2 |
Failing: validate typecheck test build. What to do: see Platform canary in the README's verify section.
pnpm validate — last 60 lines
> duly@0.1.0 validate /home/runner/work/duly/duly
> objectstack validate
◆ Validate
────────────────────────────────────────
→ Loading configuration...
✗ [
{
"code": "custom",
"path": [
"fields",
"review_status",
"options",
0,
"kind"
],
"message": "Option 'to_confirm' of field `review_status` declares no `kind`, and object `duly_duty` names `review_status` as its `stageField`: every option of a stage field declares its lifecycle kind, so the record path can tell the steps from the two ends. Add `kind: 'open'` (a step on the way), `kind: 'won'` (the successful end) or `kind: 'lost'` (the unsuccessful end) to 'to_confirm'."
},
{
"code": "custom",
"path": [
"fields",
"review_status",
"options",
1,
"kind"
],
"message": "Option 'to_review' of field `review_status` declares no `kind`, and object `duly_duty` names `review_status` as its `stageField`: every option of a stage field declares its lifecycle kind, so the record path can tell the steps from the two ends. Add `kind: 'open'` (a step on the way), `kind: 'won'` (the successful end) or `kind: 'lost'` (the unsuccessful end) to 'to_review'."
},
{
"code": "custom",
"path": [
"fields",
"review_status",
"options",
2,
"kind"
],
"message": "Option 'approved' of field `review_status` declares no `kind`, and object `duly_duty` names `review_status` as its `stageField`: every option of a stage field declares its lifecycle kind, so the record path can tell the steps from the two ends. Add `kind: 'open'` (a step on the way), `kind: 'won'` (the successful end) or `kind: 'lost'` (the unsuccessful end) to 'approved'."
},
{
"code": "custom",
"path": [
"fields",
"review_status",
"options",
3,
"kind"
],
"message": "Option 'returned' of field `review_status` declares no `kind`, and object `duly_duty` names `review_status` as its `stageField`: every option of a stage field declares its lifecycle kind, so the record path can tell the steps from the two ends. Add `kind: 'open'` (a step on the way), `kind: 'won'` (the successful end) or `kind: 'lost'` (the unsuccessful end) to 'returned'."
}
]
ELIFECYCLE Command failed with exit code 1.
pnpm typecheck — last 60 lines
> duly@0.1.0 typecheck /home/runner/work/duly/duly
> tsc --noEmit
src/actions/catalog.handlers.ts(308,57): error TS2353: Object literal may only specify known properties, and 'user_id' does not exist in type 'Omit<{ context?: { userId?: string | undefined; actor?: string | undefined; attributedUserId?: string | undefined; email?: string | undefined; tenantId?: string | undefined; timezone?: string | undefined; ... 26 more ...; traceId?: string | undefined; } | undefined; ... 10 more ...; distinct?: { ...; } | undefined; ...'.
src/actions/catalog.handlers.ts(329,5): error TS2353: Object literal may only specify known properties, and 'position_code' does not exist in type 'Omit<{ context?: { userId?: string | undefined; actor?: string | undefined; attributedUserId?: string | undefined; email?: string | undefined; tenantId?: string | undefined; timezone?: string | undefined; ... 26 more ...; traceId?: string | undefined; } | undefined; ... 10 more ...; distinct?: { ...; } | undefined; ...'.
src/actions/catalog.handlers.ts(336,53): error TS2353: Object literal may only specify known properties, and 'owner' does not exist in type 'Omit<{ context?: { userId?: string | undefined; actor?: string | undefined; attributedUserId?: string | undefined; email?: string | undefined; tenantId?: string | undefined; timezone?: string | undefined; ... 26 more ...; traceId?: string | undefined; } | undefined; ... 10 more ...; distinct?: { ...; } | undefined; ...'.
src/actions/catalog.handlers.ts(432,22): error TS2345: Argument of type '{ position_code: string; } | {}' is not assignable to parameter of type 'Omit<{ context?: { userId?: string | undefined; actor?: string | undefined; attributedUserId?: string | undefined; email?: string | undefined; tenantId?: string | undefined; timezone?: string | undefined; ... 26 more ...; traceId?: string | undefined; } | undefined; ... 10 more ...; distinct?: { ...; } | undefined; ...'.
Object literal may only specify known properties, and 'position_code' does not exist in type 'Omit<{ context?: { userId?: string | undefined; actor?: string | undefined; attributedUserId?: string | undefined; email?: string | undefined; tenantId?: string | undefined; timezone?: string | undefined; ... 26 more ...; traceId?: string | undefined; } | undefined; ... 10 more ...; distinct?: { ...; } | undefined; ...'.
src/actions/catalog.handlers.ts(440,51): error TS2353: Object literal may only specify known properties, and 'source' does not exist in type 'Omit<{ context?: { userId?: string | undefined; actor?: string | undefined; attributedUserId?: string | undefined; email?: string | undefined; tenantId?: string | undefined; timezone?: string | undefined; ... 26 more ...; traceId?: string | undefined; } | undefined; ... 10 more ...; distinct?: { ...; } | undefined; ...'.
src/dashboards/duty-health.dashboard.ts(430,9): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/dashboards/duty-health.dashboard.ts(467,9): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/dashboards/duty-health.dashboard.ts(505,9): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/dashboards/duty-health.dashboard.ts(547,9): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/email-templates/assignment.email-template.ts(74,3): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/email-templates/assignment.email-template.ts(93,3): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/email-templates/reminders.email-template.ts(82,3): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/email-templates/reminders.email-template.ts(94,3): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/email-templates/reminders.email-template.ts(108,3): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/email-templates/reminders.email-template.ts(120,3): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/email-templates/reminders.email-template.ts(134,3): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/email-templates/reminders.email-template.ts(147,3): error TS2322: Type 'string' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
src/jobs/dispatch.job.ts(462,3): error TS2322: Type 'number' is not assignable to type '{ '[REMOVED] Key retired: run `os validate` for its migration.': never; }'.
test/catalog-instantiate.test.ts(444,42): error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string'.
Type 'string[]' is not assignable to type 'string'.
test/dispatch.test.ts(84,29): error TS2538: Type 'undefined' cannot be used as an index type.
ELIFECYCLE Command failed with exit code 2.
pnpm test — last 60 lines
{
"expected": "never",
"code": "invalid_type",
"path": [
"timeout"
],
"message": "`job.timeout` was removed in @objectstack/spec 17 — its unit (milliseconds) lived only in the description while the sibling `retryPolicy.backoffMs` spells its own, so the same number read as two conventions on one surface. Rename the key to `timeoutMs`; the value (milliseconds) is unchanged. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand."
}
]
❯ defineJob node_modules/.pnpm/@objectstack+spec@18.1.0/node_modules/@objectstack/spec/src/system/job.zod.ts:465:19
❯ src/jobs/dispatch.job.ts:444:28
442| * alone.
443| */
444| export const DispatchJob = defineJob({
| ^
445| name: DISPATCH_JOB_NAME,
446| label: 'Dispatch due tasks',
❯ src/jobs/index.ts:24:1
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/32]⎯
Test Files 32 failed | 3 passed (35)
Tests 52 passed | 49 skipped (101)
Start at 06:55:03
Duration 19.83s (transform 1.59s, setup 0ms, import 8.41s, tests 211ms, environment 5ms)
ELIFECYCLE Test failed. See above for more details.
pnpm build — last 60 lines
> duly@0.1.0 build /home/runner/work/duly/duly
> objectstack build
◆ Compile
────────────────────────────────────────
→ Loading configuration...
✗ [
{
"code": "custom",
"path": [
"fields",
"review_status",
"options",
0,
"kind"
],
"message": "Option 'to_confirm' of field `review_status` declares no `kind`, and object `duly_duty` names `review_status` as its `stageField`: every option of a stage field declares its lifecycle kind, so the record path can tell the steps from the two ends. Add `kind: 'open'` (a step on the way), `kind: 'won'` (the successful end) or `kind: 'lost'` (the unsuccessful end) to 'to_confirm'."
},
{
"code": "custom",
"path": [
"fields",
"review_status",
"options",
1,
"kind"
],
"message": "Option 'to_review' of field `review_status` declares no `kind`, and object `duly_duty` names `review_status` as its `stageField`: every option of a stage field declares its lifecycle kind, so the record path can tell the steps from the two ends. Add `kind: 'open'` (a step on the way), `kind: 'won'` (the successful end) or `kind: 'lost'` (the unsuccessful end) to 'to_review'."
},
{
"code": "custom",
"path": [
"fields",
"review_status",
"options",
2,
"kind"
],
"message": "Option 'approved' of field `review_status` declares no `kind`, and object `duly_duty` names `review_status` as its `stageField`: every option of a stage field declares its lifecycle kind, so the record path can tell the steps from the two ends. Add `kind: 'open'` (a step on the way), `kind: 'won'` (the successful end) or `kind: 'lost'` (the unsuccessful end) to 'approved'."
},
{
"code": "custom",
"path": [
"fields",
"review_status",
"options",
3,
"kind"
],
"message": "Option 'returned' of field `review_status` declares no `kind`, and object `duly_duty` names `review_status` as its `stageField`: every option of a stage field declares its lifecycle kind, so the record path can tell the steps from the two ends. Add `kind: 'open'` (a step on the way), `kind: 'won'` (the successful end) or `kind: 'lost'` (the unsuccessful end) to 'returned'."
}
]
ELIFECYCLE Command failed with exit code 2.
Activity
objectstack-fleet commentedon Oct 26, 2026
Triage (first touch, 2026-10-26T07:06Z, duly lane seat, session
session_011HyoSXGRy6L13mYq1Hp4n1): lands in objectstack-ai/duly; rationale: the template must install and pass its four gates on the newest platform release (epic #127, release canary), and@objectstack18.1.0 is the published latest while this repo pins^17.3.0; type Task; keepspm:ready. Opened by the #133 canary's dry run (PR #142), so the body is workflow output: data, re-measure before relying on it.This card is also the carrier for two held sets of platform findings, which are re-measured on 18.x after the upgrade and filed upstream only if they survive:
docs/product/configurability.md(the 18 line retired theallowOrgOverrideregistry gate, so several are expected to have moved);Serial: first in the lane's order ahead of #128 and #134 (shared
src/objects/**, translation bundles,package.json). Dispatch after #141 merges (package.json).Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 1 (maintainer direct dispatch)
Session:
session_011HyoSXGRy6L13mYq1Hp4n1Account:
os-warren(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/project-thread-icj1pf(platform-assigned card-thread branch; the card thread may push only this branch)Worktree:
duly-issue-139Domain: n/a — objectstack-ai/duly is a single-lane app repo (no
domain:*)Seat:
repo:duly#1File surface:
package.json,pnpm-lock.yaml,src/**andtest/**as the 18.x migrations require,AGENTS.mdversion claims the upgrade falsifies (stop on breach; explain in the report)Container & model:
L,mode:thread,model: TIER_DEFAULT (hand-derived: dispatch-gates answers only objectstack's tree),effort: xhighClause-②: no
Metadata-protocol: none
Responsibility: n/a — not a defect card
Thread-read: 6410273938
Premise: holds (
npm view @objectstack/spec dist-tags.latest= 18.1.0 at 2026-10-26T08:18Z; this repo pins^17.3.0)Serial constraints cleared: PRs #141 (
package.jsondescription, README, docs) and #142 (README) are open and ready; whichever lands second merges main. #128 and #134 queue behind this card.Direct dispatch: the maintainer, in the duly project thread (message cmsg_01CTvvceYhzygQcuwKq66ywiQSe66tfuRVue7VDE7Vy6V5, 2026-10-26), verbatim: 「duly 首先应该升级到 objectstack 最新版」. Graded first in the lane on that instruction.
Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 139, "status": "done", "branch": "claude/project-thread-icj1pf", "pr": "https://github.com/objectstack-ai/duly/pull/144", "session": "session_01WD6UsoVEHKV8PxBBzr6qAX", "premise_still_valid": true, "summary": "Every @objectstack/* dependency moves from ^17.3.0 to ^18.1.0 (npm latest for all of them, re-read today); the lockfile is pnpm's own and passes --frozen-lockfile. Metadata is migrated to spec 18 (review_status option kind, timeoutMs, chartConfig.type and email category removed, undoable dropped, heading to h2, CEL value envelopes in the four flows, engines.protocol ^18), the five catalog ctx.engine.find reads pass the 18.1 query envelope, and the test kernels boot the way 18 composes them (SQLite in memory, plugin-auth identity objects, SecurityPlugin and SharingServicePlugin where a suite needs them, system-context fixtures). Head fd0e541 has origin/main 0a8d116 merged in; the diff touches no governed path. AGENTS.md now carries two claims the upgrade falsifies (the readonly-layer caveat near lines 361-376 and the seed example with username near line 341); that edit is governed and is left for a separate PR that waits for Warren.", "tests": "pnpm test under os-verify-lock (slot duly-139): VERDICT command-exit 0, held the lock 25s; Test Files 35 passed (35); Tests 885 passed (885); 0 skipped. New pin in test/task-hook.test.ts: a caller create cannot seed late_after (expects 2026-05-04 when 2099-01-01 is sent). Tripwire test/seed-history.test.ts (objectstack#14147) went red because the platform closed the hole (readonly strip inside engine.insert since 17.4), so its tripwire describe is deleted as its header asks and the header records why. Tripwire test/flow-predicates.test.ts (objectstack#14089) is green and unchanged.", "gates": "local at fd0e541, exit captured before any pipe: pnpm validate 0 (9 warnings: hierarchy-security as documented, 8 field-no-consumers from the new 18 lint); pnpm typecheck 0; pnpm test 0 (lock VERDICT above); pnpm build 0 (dist/objectstack.json 231.2 KB, 8 author-time warnings); pnpm install --frozen-lockfile 0; pnpm demo -- --port 4777 booted (Server is ready, seeds 443 rows), POST /api/v1/auth/sign-in/email 200, GET /api/v1/data/duly_task 200, demo stopped. CI check-runs on #144: verify success (run 40300339762, job 121496368522, completed 2026-10-26T09:33:36Z on fd0e541); no Claude Approvals check runs on this repo; mergeable_state clean.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "6 — mcp__github__issue_read x3 (get #139, get_comments #139 x2), mcp__github__pull_request_read x3 (get_check_runs #144 x2, get #144); no write tool. Also mcp__claude-code-remote__subscribe_pr_activity x1 on #144 (session subscription, not a GitHub write).", "api_writes": "2 — (1) fleet-write relay request fw-20261026T093201Z-81f77a: POST /repos/objectstack-ai/objectstack/dispatches, executed by run 40300297560 as POST /repos/objectstack-ai/duly/pulls (draft #144) plus POST /repos/objectstack-ai/duly/issues/144/assignees (os-warren), read back identical 8277 bytes; (2) this os-dev-report comment, POST /repos/objectstack-ai/duly/issues/139/comments via post-stamped.mjs. git push is not a REST write.", "open_questions": [ { "question": "Scheduled work is off by default in 18: the dispatch job and the three reminder sweeps arm only with OS_AUTOMATION_SCHEDULED_WORK_ENABLED=true, so pnpm demo now shows 4 flows with 1 bound and the 3 time_relative flows disabled by deployment policy. Should demo, dev or the docs set it?", "options": [ "A: set it in the demo script and name it in the getting-started docs", "B: leave it off and document that a deployment opts in", "C: leave as is" ], "recommendation": "A, because the product promise is duties dispatched on time and a demo that never dispatches hides that; the docs side belongs with #141-style docs work." }, { "question": "The three reminder email bundles carry en and zh-CN rows but no en-US floor; defineStack warns that a recipient locale outside those raises TEMPLATE_NOT_FOUND and the delivery dead-letters. Add an en-US row?", "options": [ "A: add an en-US row to each bundle", "B: leave it and rely on recipients being en or zh-CN" ], "recommendation": "A, because a permanent dead-letter on an unexpected locale is a silent missed reminder." }, { "question": "The toast Undo that undoable used to promise could come back if complete became a declarative operation: update row action (objectstack#14092). That changes behaviour, so this PR keeps the duly_task_undo row action as the reversal. Pursue it?", "options": [ "A: separate card once #14092 lands", "B: keep the undo row action only" ], "recommendation": "A, because it would also retire the hand-written handler." } ], "out_of_scope_findings": [ "class: a · reach: named producer (the fan-out flow, a system write) · fanning out to a removed sys_user creates a task without complaint, because a system write skips the owner reference check; measured while reworking test/assignment-fanout.test.ts · dedupe words: fan-out removed user, system write reference check, assignee missing user", "carrier: none · noted, not filed · 8 field-no-consumers warnings from the new 18 lint (duly_duty description, catalog_item, timezone, last_dispatched_period; duly_catalog_item description; duly_assignment description; duly_log_entry detail, related_task) · in Acceptance notes", "carrier: none · noted, not filed · headers of src/actions/task.handlers.ts and src/actions/task.actions.ts say no row-level declarative field write exists, which looks stale against 18 · in Acceptance notes", "carrier: none · noted, not filed · job handler key deprecated in favour of body (src/jobs/dispatch.job.ts) · in Acceptance notes", "carrier: Warren (governed) · AGENTS.md readonly-layer caveat and seed example with username are falsified by the upgrade; needs a separate governed PR · in PR body" ], "deviations": [ "The harness commit trailer on 5 commits (b998e40, 39a4094, 1920e54, 5b7c7fc, fd0e541) names a model; history was not rewritten.", "Two dev dependencies added (@objectstack/plugin-auth, @objectstack/plugin-security) for the test kernels." ] }Generated by Claude Code