Skip to content

spec: IJobService.replay gains an optional force argument — the contract half of #14501's A+a2 ruling #14766

Closed

Description

@os-sales

Filed by the domain:services execution seat (session session_01AUF1NoViznQK32gqpK8wS8) as the contract-first half of a ruled card in its own lane. Unassigned, ⛔ not graded by this seat, ⛔ never dispatched by it — packages/spec is the domain:spec seat's single-owner surface.

Why this card exists separately

The maintainer ruled A + a2 on #14501 (relayed by the director seat, 14501#issuecomment-5518058223, provenance: live PM chat, verbatim reply 「同意」). The ruling's own execution note reads "Execution: domain:services lane, M" — but it also names the file the change lands in:

Clause-② yes (IJobService.replay gains an optional force argument in packages/spec/src/contracts/job-service.ts): CONTRACT_REVIEW_TIER.

packages/spec is not the services lane's to write, whoever needs it. So this is split contract-first: the contract moves here, the behaviour stays on #14501 behind a Blocked-by:. ⛔ Nothing about the ruling's substance is reopened — only its landing seats. Precedent for this exact shape: #13937 → #14384.

The change, stated from the tree

Current declaration, packages/spec/src/contracts/job-service.ts:200-206 on origin/main 7a17f3bf1:

    /**
     * Equivalent to `trigger(name)` but records that this run is a replay
     */
    replay?(name: string, data?: unknown): Promise<void>;

The ruling requires a third, optional parameter carrying force: true, so that:

  • replay() on a scheduled flow whose (flow, tick-window) claim is absent or failed re-runs the window (unchanged behaviour);
  • replay() on a window whose claim succeeded is refused loudly with an ADR-0112 envelope naming the window and the claim;
  • replay(name, data, { force: true }) sends anyway.

Options a1 (refuse always, no door for a genuine re-send) and a3 (send anyway, accept duplicates) were considered and not taken.

One-line executable criterion for whoever grades this

git show origin/main:packages/spec/src/contracts/job-service.ts | sed -n '200,206p' still shows the two-parameter signature ⇒ this card is live. When it shows the force parameter, this card is done and #14501 unblocks.

Scope

In: the replay signature in packages/spec/src/contracts/job-service.ts, its TSDoc, and whatever packages/spec-side machinery a signature change there owes (declaration baselines, liveness ledger, ADR-0087 disposition if the spec seat grades one owed).

⛔ Out: the ledger behaviour itself — the (flow, tick-window) claim through sys_flow_dispatch, the schedule-trigger.ts catch recording a failed outcome, the DbJobAdapter.replay implementation and every pin. All of that is #14501, in domain:services, and it is blocked on this card.

⚠️ The ruling grades the change Clause-② yes and names CONTRACT_REVIEW_TIER. That grading travels with the contract half; it is stated here so the spec seat does not have to re-derive it from #14501, and ⛔ it is not this seat's to relax.

Not asserted

This seat did not grade this card's priority, size, or type — priority:p2 is carried over from #14501 as a starting point and the domain:spec seat should re-grade it on its own terms. If the spec seat judges that the force parameter is better shaped some other way (an options object, a distinct verb), that is its call on its own surface; #14501's behaviour half will follow whatever contract lands.

Refs: #14501 (the ruled parent, blocked on this) · 14501#issuecomment-5518058223 (the ruling, verbatim) · #14619 (the second door the same ledger answers) · #14149 (the digest work that meets it first) · #10220 (sys_flow_dispatch, the existing ledger) · #13686 (leader election).

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    domain:specDomain lane — seat card indexed by label:pm:seat
    on Sep 3, 2026
  2. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 4, 2026
  3. self-assigned this
    on Sep 4, 2026
  4. os-justin commented on Sep 4, 2026

    @os-justin
    Collaborator

    Claim: domain:spec execution seat, session session_01H2oQebDDxYKfWZusyd8GXk, branch claude/issue-14766-job-service-replay-force. Labels pm:queue → pm:dispatched written in one stroke with the assignee (read back 2026-09-04T12:45Z: priority:p2, pm:dispatched, domain:spec; assignee set; no concurrent label stripped).

    Surface (read on origin/main c4d1354e3, 2026-09-04T12:44Z): packages/spec/src/contracts/job-service.ts:200-206 still declares replay?(name: string, data?: unknown): Promise<void> — the card's own liveness criterion holds, card is live. Files: that declaration + its TSDoc, and whatever packages/spec-side machinery the change owes (API-surface baseline, liveness ledger row if one names replay, changeset). ⛔ No behaviour: the (flow, tick-window) ledger, DbJobAdapter.replay, schedule-trigger.ts and every pin stay on #14501 (domain:services, pm:blocked on this card).

    Tier: dispatch-gates --tier reports no path-derived mandate (floor). Card content: a published contract method's parameter list changes and its refusal semantics are declared ⇒ Clause ② yes, dispatched at CONTRACT_REVIEW_TIER; the dev hangs needs:contract-review on PR + card, in-seat review before ready.

    Serial check (2026-09-04T12:44Z): no open PR touches packages/spec/src/contracts/job-service.ts; no H17 on-hold trigger file intersects this surface (anchor #9857, swept 07:48Z). No generated-registry file is expected to change (additive optional parameter, no ADR-0087 retirement) — if the dev finds one is owed, it lands serially after PR #15299.

    Re-grade on this seat's terms: priority:p2 stands (it gates queued work on #14501), size S.


    Generated by Claude Code

  5. os-justin commented on Sep 4, 2026

    @os-justin
    Collaborator

    Dispatch — round R3 slot refill, 2026-09-04T12:47Z

    Seat domain:spec, session session_01H2oQebDDxYWfWZusyd8GXk, os-dev subagent at CONTRACT_REVIEW_TIER, branch claude/issue-14766-job-service-replay-force, tree origin/main c4d1354e3 (2026-09-04T12:44Z).

    ① Task

    Land the contract half of the maintainer's A+a2 ruling on #14501 (relayed verbatim on 14501#issuecomment-5518058223, reply 「同意」): IJobService.replay in packages/spec/src/contracts/job-service.ts:200-206 gains an optional third argument that carries force: true. The behaviour the contract must be able to express, quoted from the card:

    • replay() on a scheduled flow whose (flow, tick-window) claim is absent or failed re-runs the window (unchanged behaviour);
    • replay() on a window whose claim succeeded is refused loudly with an ADR-0112 envelope naming the window and the claim;
    • replay(name, data, { force: true }) sends anyway.

    Shape is your call on this surface (the card leaves it to the spec seat): the seat's default is an options object replay?(name: string, data?: unknown, options?: { force?: boolean }): Promise<void> — extensible, no boolean-trap positional. A bare force?: boolean third positional is acceptable if you find a spec-wide convention that prefers it; state the reason in the PR body either way. The TSDoc must declare the three behaviours above and name the refusal (ADR-0112 envelope, the window and the claim) so the services implementer on #14501 codes against the contract text, not against this card.

    In scope: the declaration + TSDoc; the API-surface / declaration baselines check:generated --fix regenerates; a liveness-ledger row if one names replay; a spec-side type-level pin (the options type is exported and accepted); one changeset @objectstack/spec minor (additive optional parameter — state in the changeset that the refusal semantics are declared here and enforced by #14501). ADR-0087: no retirement, no registry entry expected — if check-adr-0087-registration or the migration-registry generator disagrees, register what it asks for and say so in the report.

    Out of scope (⛔): the ledger behaviour, sys_flow_dispatch, schedule-trigger.ts, DbJobAdapter.replay (packages/services/service-job/src/db-job-adapter.ts:211 keeps compiling because the new argument is optional — verify with the typecheck of @objectstack/service-job, do not edit it), every pin outside packages/spec.

    Acceptance: git show origin/main:packages/spec/src/contracts/job-service.ts | sed -n '200,215p' shows the new signature; pnpm --filter @objectstack/spec check:generated reports all artifacts up to date; @objectstack/service-job typechecks unchanged.

    ② Constraints

    • Worktree-first: git fetch origin main && git worktree add --no-track /home/user/objectstack-14766 -b claude/issue-14766-job-service-replay-force origin/main && cd /home/user/objectstack-14766 && pnpm install. Never edit the shared checkout; never git stash.
    • Clause ② yes: open the PR as draft, hang needs:contract-review on the PR and on this card (read-modify-write, read back), Fixes #14766 in the body. The seat reviews in-seat and flips ready; ⛔ you never flip ready or arm auto-merge.
    • Run node scripts/pm/dispatch-gates.mjs --commands on your change set and every command it derives; report real output lines.
    • No model identifiers anywhere in the PR, code, comments, changeset or commit messages. English only on GitHub.
    • Serial: no open PR touches this file; if packages/spec/src/migrations/registry.ts ends up regenerated, say so — it lands after PR feat(spec)!: retire connector.errorMapping — eleven inert authorable keys, one spelled like the live userMessage channel (#14676, ADR-0049) #15299.
    • Implemented-by: line in the PR body with your session id; the seat's Reviewed-by: is independent.

    ③ Report

    Return the os-dev JSON report (status, PR number + head SHA, changed files, commands run with real output lines, contract_flags, open_questions, findings). Contract flags: any place where the declared refusal semantics conflict with an existing consumer of replay.

    升级与决策(逐字,runbook 步骤 1bc3c092;块 md5 22f2339f0acb64cdb50c7adc9db681c3,SKILL.md ## 升级与决策 at origin/main c4d1354e3)

    每个方案必须沿四条固定评估轴分析,这是决策分析的核心原则,不是可选项:

    • 实际业务需求 — 它服务的是真实存在的业务场景,
      还是投机性能力面?判据要求实测(谁在写这个键、谁在读、
      示例应用与真实部署的用法),「读起来像有用」不作数。这条轴会改变结论,不是陪衬。
    • 项目长远合理性 — 哪个方案符合北极星方向与可持续架构(no workarounds、
      contract-first),临时补丁式选项要明说长期代价。
    • 防 AI 写代码犯错,尤其是防 AI 写元数据 app 犯错 — 哪个方案让 AI 在结构上更难写错:
      契约收紧(严格 schema、publish 时响亮拒绝)优于消费端宽容(?? 回退、静默容错)——
      宽容恰是 AI 批量犯错被掩盖的温床;声明即强制,绝不让 AI 声明一个运行时不兑现的能力。
    • 创业阶段不扩散需求 — 创业阶段聚焦原则(维护者 2026-08-04 指示:
      「我们是一个创业项目,应该先专注于核心能力」):能力扩张默认从紧,
      无拉动的声明面按 implementation-first 处置,已发布零消费的能力不因沉没成本获得豁免。
      过渡也从紧 —— 创业阶段不渐进(维护者 2026-08-27 裁,逐字:「项目在创业阶段,
      用户也很少,短期不考虑渐进。」):废弃别名/拼写与能力退役默认立即退休,
      不设分阶段窗口、不留双拼写宽限;staged 选项仅凭具名外部用户证据才可呈报为推荐。

    推荐意见必须基于这四条轴给出理由;四轴冲突时如实呈现权衡,
    交维护者拍板。


    Generated by Claude Code

  6. os-justin commented on Sep 4, 2026

    @os-justin
    Collaborator

    Correction to the dispatch comment above (5540639299): the seat session id there is mistyped. The dispatching session is session_01H2oQebDDxYKfWZusyd8GXk, as on the claim comment. Nothing else changes.


    Generated by Claude Code

  7. added
    needs:contract-reviewMarker only — PR awaits its at-tier Contract review PASS; no check reads it, the record decides
    on Sep 4, 2026
  8. os-justin commented on Sep 4, 2026

    @os-justin
    Collaborator

    os-dev-report

    {
      "issue": 14766,
      "status": "done",
      "branch": "claude/issue-14766-job-service-replay-force",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/15377",
      "pr_number": 15377,
      "head_sha": "07f86ba7ff8f3fd52f74be140c0ea5e3dfc30327",
      "premise_still_valid": true,
      "changed_files": [
        "packages/spec/src/contracts/job-service.ts",
        "packages/spec/src/contracts/job-service.test.ts",
        "packages/spec/api-surface/contracts.json",
        "packages/spec/export-origins/contracts.json",
        ".changeset/job-service-replay-force.md"
      ],
      "summary": "IJobService.replay now reads replay?(name: string, data?: unknown, options?: JobReplayOptions) with JobReplayOptions { force?: boolean } exported from @objectstack/spec — an options object by the interface's own schedule(..., options?: JobScheduleOptions) convention (no spec-wide positional-boolean convention exists; every other trailing optional in contracts/*.ts is an options object). The TSDoc declares the three outcomes by (flow, tick-window) claim state — absent/failed re-run the window, succeeded is refused with an ADR-0112 envelope code RESOURCE_CONFLICT (HttpStatusErrorCodeMap[409], standard catalog, no new ledger row) and status 409 naming the window and the claim, force: true sends anyway — and names a1/a3 as not taken. Behaviour untouched: DbJobAdapter.replay unedited and typechecks unchanged. check:generated --fix regenerated exactly api-surface/contracts.json and export-origins/contracts.json; src/migrations/registry.ts and authorable-surface.base.json did NOT change (nothing lands serially after PR 15299). No liveness-ledger row names replay (liveness/job.json governs JobSchema props, not contract methods). Changeset @objectstack/spec minor states the semantics are declared here and enforced by 14501. Draft PR 15377 opened with Fixes 14766 and an Implemented-by line; needs:contract-review hung on the issue (read back: priority:p2, pm:dispatched, domain:spec, needs:contract-review — nothing stripped) and on the PR (read back: size/m, needs:contract-review — nothing stripped). Channel note: repo-scoped REST returned 403 on this seat (authenticated and anonymous probes), so all label writes went through MCP issue_write as read-modify-write unions with read-back. The branch was merged with origin/main dc46c4ec1 (3 commits, none touching packages/spec) after dispatch-gates flagged a stale derivation tree; the gate list was byte-identical before and after. Platform observation: the PR body's stored form has the two footer lines re-ordered (the harness footer line now sits above the rule line + session footer); content otherwise byte-intact on read-back, left as is.",
      "tests": "All at head 07f86ba7f (merge commit; spec dist built at 1ffdfbcbc, unchanged by the merge). pnpm --filter '@objectstack/spec^...' build: 'No projects matched' (spec has no workspace deps). pnpm --filter @objectstack/spec build (verify lock): 'check-dts-emitted: @objectstack/spec - 34/34 declared declaration file(s) present.' VERDICT command-exit 0, held 147s then 158s on the post-ablation rebuild. vitest run --maxWorkers=2 src/contracts/job-service.test.ts: 'Test Files 1 passed (1)' 'Tests 16 passed (16)'. pnpm --filter @objectstack/spec typecheck: 'check:test-typecheck: OK — 54 file(s) / 261 error(s) / 145 pinned signature(s) held' VERDICT command-exit 0; tsc -p tsconfig.test.json --listFiles counts contracts/job-service.test.ts = 1 (pins are inside the measured program). pnpm --filter @objectstack/service-job typecheck (after building its closure minus spec, VERDICT command-exit 0): VERDICT command-exit 0, waited 103s on the lock. pnpm --filter @objectstack/spec check:generated --fix: '2 of 15 artifact(s) stale' gen:api-surface + gen:export-origins; re-run after the final rebuild: '✓ All 15 generated artifacts are up to date.' dispatch-gates --commands (no paths, change set 5 paths vs merge base dc46c4ec1): 61 commands; 59 exit 0 with judgment lines captured pre-pipe (check:api-surface 'public API surface + factory signatures unchanged ✓'; check:export-origins '5260 exports across 17 entry points resolve exactly as recorded'; check:exported-any 'no exported type resolves to any: 2457 types + 1524 schemas'; check:dual-source-exports '0 accepted dual-source (baseline)'; check:entry-nameability '434 call probes across 17 public entries, 0 new'; check:browser-reachable-entries green; check:liveness 'state-counts.md is current'; check:docs '230 generated files in sync'; check:nul-bytes 'OK (scanned 7451 text file(s))'; check:closing-keyword-parity 'OK'; check:adr-0087-registration --self-test '292 assertions'; check:changeset-no-major --self-test '116 assertions'; check:empty-changeset --self-test '118 assertions'; the 21 root node-script gates and the remaining root pnpm check:* all exit 0). NOT MEASURED locally (declared narrowing, 2 of 61): pnpm check:type-check-debt and pnpm check:dual-build-cjs-loads both exit 3 'PREREQUISITE NOT MET — this gate reads built output' asking for the full ./packages/* turbo build closure — CI's run. Extra gates judged implicated by the code literal in TSDoc: check:error-code-provenance 'OK — every registered-code stamp site is listed under its own owner key or carries a recorded waiver' exit 0; pnpm check:dispatcher-error-vocabulary exit 0; pnpm check:error-code-casing exit 0. First-pass log note: my batch runner wrote per-index logs into one directory so parallel batches overwrote each other's logs (exit codes were captured per command and survived); every gate whose log was lost was re-run with prefixed logs, and six spec reds in that first pass (api-surface, browser-reachable-entries, dual-source-exports, entry-nameability, exported-any, generated) were stale-dist phantoms caused by the ablation restore touching src after the build — all green on the rebuilt dist. ABLATION (committed tree, restore anchored on HEAD, absolute paths, trap on EXIT INT TERM): mutation narrowed the declaration to replay?(name: string, data?: unknown); on-disk confirmation by anchored grep counts new=0 old=1. Predicted direction: red on pins (b),(c),(d), green on (a) and legacy. Observed: tsc -p tsconfig.test.json 8 errors in job-service.test.ts, all in the 14766 block ('Expected 1-2 arguments, but got 3' x2, identity pin 'Type true is not assignable to type false' + 'Tuple type [name: string, data?: unknown] of length 2 has no element at index 2', and the (b) implementation no longer assignable); vitest 'Tests 1 failed | 15 passed (16)' — pin (d). Restore: git checkout HEAD -- ABS_PATH; git diff HEAD --stat empty; git hash-object = 9263c64d99fdaa91f2912e35468d1850e377fc80 = HEAD blob; counts back to new=1 old=0; control tsc 0 errors in the file. No rebuild inside the ablation (tsc and vitest resolve ./job-service from src, not dist); spec rebuilt afterwards because the restore made src newer than dist, and dist-reading gates re-run on it.",
      "gates_run": "See tests: 61 derived (59 green, 2 NOT MEASURED prerequisite class) + 3 extra error-code gates green + spec build/test/typecheck + service-job typecheck.",
      "contract_flags": [],
      "contract_flags_note": "No existing consumer conflicts. In-repo callers of IJobService.replay: none outside packages/services/service-job (DbJobAdapter.replay is the sole implementer; its tests call replay(name) with one argument; no REST/runtime route exposes job replay; IQueueService.replay(messageId) is a different contract). objectui at 24e027e: only packages/mobile offline-sync replay(), unrelated. Interim semantics until 14501: DbJobAdapter.replay accepts and ignores the third argument, re-running as before — stated in the changeset.",
      "mcp_calls": "13 — 3 reads at start (issue comments, issue 14766, issue 14501 body), create_pull_request, issue labels read, issue labels write, one failed issue_read on the PR number (does not resolve PRs), pull_request_read x2, issue labels read-back, PR labels write, add_issue_comment, comments read-back",
      "open_questions": [
        {
          "question": "Should the refusal carry a service extension code (e.g. a JOB_REPLAY_WINDOW_CLAIMED row under service-job in error-code-ledger.zod.ts) instead of the standard-catalog 409 member RESOURCE_CONFLICT the contract now names?",
          "options": [
            "A — keep RESOURCE_CONFLICT / 409 (landed): closed vocabulary already, no ledger row before a producer exists (the declared-but-unproduced shape ADR-0112's 2026-08-18 amendment retired), consumers assert code + status; a console cannot distinguish this 409 from other 409s by code alone",
            "B — 14501 registers an extension code together with its producer and this contract text is amended in that PR to name it: distinguishable on the wire, at the cost of a ledger row and a second edit of the contract"
          ],
          "recommendation": "A, because no consumer branches on this refusal today (measured: zero callers in-repo and in objectui), the startup-focus axis says no new vocabulary without pull, and B stays available to 14501 the day a console needs the distinction — the contract text already says so."
        }
      ],
      "out_of_scope_findings": [],
      "findings": []
    }

    Generated by Claude Code

  9. os-justin commented on Sep 4, 2026

    @os-justin
    Collaborator

    Contract review (Clause ②) — PR #15377 at head 07f86ba7f — PASS · ACCEPT

    Reviewed-by: domain:spec seat, session session_01H2oQebDDxYKfWZusyd8GXk (independent of the Implemented-by: dev subagent; tier fuse read by get_session at 2026-09-04T13:30Z — configured and last-served model both equal CONTRACT_REVIEW_TIER). Read against GitHub: the branch fetched into a named ref and diffed against merge base dc46c4ec1 — 5 files, +189/−2: the contract, its test, api-surface/contracts.json + export-origins/contracts.json (one new exported name each), one changeset.

    Verified against the ruling (A + a2 on #14501, relayed 5518058223):

    • replay?(name: string, data?: unknown, options?: JobReplayOptions): Promise<void>; JobReplayOptions { force?: boolean } exported from @objectstack/spec contracts. Options object by the interface's own schedule(…, options?: JobScheduleOptions) convention — the seat's default shape, with the convention cited rather than asserted. Additive: the pre-change two-argument implementation stays assignable (pin (a)), and packages/services/service-job typechecks unchanged (dev's reading; DbJobAdapter.replay untouched — as the card's ⛔ requires).
    • TSDoc declares exactly the three outcomes by claim state (absent / failed → re-run; succeeded → refused; force: true → sends anyway), names a1 / a3 as not taken, and declares the refusal as an ADR-0112 envelope that rejects (never a silent no-op) with code: 'RESOURCE_CONFLICT' + status: 409, naming the window and the claim — the text the [finding] A schedule (cron) flow has no dispatch-claim ledger while a time_relative flow does — a re-run of a digest re-notifies #14501 implementer codes against. Pin (d) reads that prose; pins (b)/(c) are compile-time identity checks under check:test-typecheck; ablation (narrowing the signature back) reported red on (b)(c)(d) and green on (a) — the additivity asymmetry.
    • Changeset @objectstack/spec minor, additive, "declared here, enforced by [finding] A schedule (cron) flow has no dispatch-claim ledger while a time_relative flow does — a re-run of a digest re-notifies #14501" — correct; no ADR-0087 entry owed; migrations/registry.ts untouched (no serial constraint).
    • Generated followers: exactly api-surface/contracts.json and export-origins/contracts.json — matches the surface predicted on the claim.

    Seat ruling on the dev's open question (third tier, falsifiable premise): A — keep RESOURCE_CONFLICT / 409, the standard-catalog 409 member. Premise: no consumer branches on this refusal today (dev measured zero callers of IJobService.replay outside service-job in-repo and none in objectui), so a distinguishable extension code has no pull; ADR-0112's closed vocabulary and the no-declared-but-unproduced-code amendment both point the same way. #14501 may register a service-job extension code with its producer the day a console needs to tell this 409 apart, amending this contract's code literal in the same PR — the contract text already leaves that door. Any reader with a consumer that needs the distinction now falsifies the premise; say so on #14501.

    Conditions: none. Carriers cleared in this stroke (read-modify-write, read back): needs:contract-review removed from this card and from PR #15377. Landing: ready + auto-merge (squash through the queue) armed by the seat once the head's checks are green (source gates, queue guard, changeset, liveness green at 13:30Z; Test Core / Lint in progress). On MERGED: strip pm:dispatched, probe origin/main for the third parameter, landing note, and an unlock note on #14501 (Blocked-by: #14766 satisfied — the services lane's behaviour half is dispatchable).


    Generated by Claude Code

  10. removed
    needs:contract-reviewMarker only — PR awaits its at-tier Contract review PASS; no check reads it, the record decides
    on Sep 4, 2026
  11. os-justin commented on Sep 4, 2026

    @os-justin
    Collaborator

    Landed — PR #15377 MERGED 2026-09-04T14:26:02Z through the merge queue (squash 222dc0f32 on origin/main, probed 14:45Z: packages/spec/src/contracts/job-service.ts:274 replay?(name: string, data?: unknown, options?: JobReplayOptions): Promise<void>). pm:dispatched stripped by the domain:spec seat (session session_01H2oQebDDxYKfWZusyd8GXk); the card closed via Fixes. The card's own liveness criterion now reads the force door ⇒ done; unlock note posted on #14501 (its Blocked-by: #14766 is satisfied — the behaviour half lands there, in domain:services).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:specDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions