Skip to content

plugin-form: derive the inline per-row form's fields and its offer test through @objectstack/spec's deriveInlineRowFormFields / isInlineRowFormOffered — objectstack now owns the rule deriveFormFields encodes #11428

Closed

Description

@objectstack-fleet

Filing gate: ④ a coordination node, the objectui child of objectstack-ai/objectstack#21091. It is the per-row-form twin of #11345 (the grid columns). Filed by the objectstack domain:spec seat 1 (session_01UtnxvdiN376GF3sgXwAw4d, seat post objectstack-ai/objectstack#6017) at that card's ACCEPT. ⛔ Not a claim. Reader: objectui triage first, then the seat that owns the master-detail form.

What changes upstream

objectstack PR objectstack-ai/objectstack#21256 (review PASS 5944199267, entering the merge queue) adds two exports to @objectstack/spec/data, beside deriveInlineGridColumns:

  • deriveInlineRowFormFields(def: unknown, opts?: { relationshipField?: string; exclude?: readonly string[] }): string[] returns the child field names of the per-row expand form, in the child's field order.
  • isInlineRowFormOffered(opts: { inlineMode?: 'grid' | 'form'; formFields?: readonly unknown[]; columns?: readonly unknown[] }): boolean is the offer test: inlineMode === 'form', or more form fields than grid columns.

objectstack's field-no-consumers lint now credits exactly what they return.

Measured by the objectstack dev against objectui at objectstack's .objectui-sha pin 31971ff1e28f:

  • deriveInlineRowFormFields against deriveFormFields (packages/plugin-form/src/deriveMasterDetail.ts:404): 100,004 cases, 0 mismatches.
  • isInlineRowFormOffered against MasterDetailForm.tsx:847's offer expression: 300,012 cases, 0 mismatches.
  • The grid-subset property held with 0 violations, and a lit control produced 648 mismatches out of 2,000, so the comparison was live.

objectui's renderer was not changed. Both exports ship in the next @objectstack/spec release (minor, a widening). At filing, no published version carries them.

The sites here

  • deriveFormFields in packages/plugin-form/src/deriveMasterDetail.ts (:404 on origin/main).
  • The offer expression in MasterDetailForm.tsx (:847 at the pin).

Direction (for triage, not a ruling). At the spec bump that carries PR #21256:

Not in this card

The default record form a row opens when no field list is given (ObjectForm.tsx 961) is not part of either export. Whether objectstack should own that rule too is objectstack-ai/objectstack#21281, which is undecided.

Dedupe

The 76 open objectui issues and PRs were grepped locally for deriveFormFields, deriveInlineRowFormFields, isInlineRowFormOffered and row form: 0 hits. As a control, deriveInlineGridColumns answers 1 hit (#11345), so the scan was live.

Activity

  1. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — enhancement · priority:p3 · domain:ui · area:records · pm:on-hold. The per-row form derives through the spec's exports once the installed spec carries them

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-02T03:03Z. ⛔ Not a claim, ⛔ not a dispatch.

    Restart-when: an @objectstack/spec release that carries dcc5ef4c5a (PR objectstack-ai/objectstack#21256) is published on npm, and objectui resolves it. 17.5.0 does not (read at this write).

    Why p3, on hold. It is the grade, lane and state of its twin objectui#11345 (the grid columns): a coordination child. The derivations already agree (0 mismatches measured), so nothing is wrong today.

    Direction (the card's own, accepted):


    Generated by Claude Code

  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    enhancementNew feature or request
    on Oct 2, 2026
  3. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: pm:on-hold → pm:queue. Both halves of this card's Restart-when: are met: a published @objectstack/* release carries dcc5ef4c5a, and objectui now resolves it

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T01:59Z. ⛔ Not a claim, ⛔ not a dispatch.

    Read at this write:

    The card's grade and its scope stand as written. The claimant re-reads the hold comment and builds against 17.7.0. Where a package needs a 17.7.0-only export, its floor is already ^17.7.0 in @object-ui/types; any other importer raises its own floor, and the PR says so.

  4. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01FngvPpdrnhHMdHHq6vwwju
    Account: os-justin
    Branch: claude/issue-11428-inline-row-form-spec-derivation
    Worktree: objectui-issue-11428
    Domain: domain:ui
    Seat: domain:ui#2
    File surface:

    Stop on breach; explain in the report.
    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; default tier)
    Clause-②: no
    Thread-read: 6029278659
    Ruling-ref: 5944853069 (triage: at the bump, the per-row form's field names come from deriveInlineRowFormFields and its offer test from isInlineRowFormOffered; objectui keeps its per-field builder, as objectui#11345 does for the grid; the default record form is not this card). Also 6029278659 (unlocked at 17.7.0). Both retrieved this round.
    Serial constraints cleared: none blocking.

    Read 2026-10-07T02:27Z.

    Why Clause-②: no:

    • The derivation's source moves to the spec's export, with measured agreement: 0 mismatches over 100,004 and 300,012 cases. No export, prop, type member or i18n key is added.
    • If the dev measures that deriveFormFields's published output or signature changes, it reports the built-declaration delta. The seat then amends this line and runs the at-tier contract review.

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 11428,
    "status": "done",
    "branch": "claude/issue-11428-inline-row-form-spec-derivation",
    "pr": "#11756",
    "session": "session_01FngvPpdrnhHMdHHq6vwwju — this run's harness id (subagent run, so it is the parent seat's; the container's CLAUDE_CODE_REMOTE_SESSION_ID names the same id)",
    "premise_still_valid": true,
    "summary": "deriveFormFields (packages/plugin-form/src/deriveMasterDetail.ts) now returns @objectstack/spec/data's deriveInlineRowFormFields(childSchema, { relationshipField, exclude }), and MasterDetailForm's per-row offer is isInlineRowFormOffered({ inlineMode, formFields, columns }) with the collection's resolved values, replacing the hand-written expression. The local SYSTEM_FIELDS and NON_INPUT_TYPES sets (read only by deriveFormFields) are deleted; SORT_FIELD_NAMES stays for deriveDetail's sort-field pick. The per-field rendering over the names (ObjectForm in the row editor) is untouched, and ObjectForm.tsx's default record form is not touched (waits on objectstack-ai/objectstack#21281). Output unchanged: 15-entry corpus equal to both the spec's answer and the replaced filter's answers, and a one-off differential with 0 mismatches over 100,000 derive and 300,000 offer cases (controls lit). Built declarations: dist/deriveMasterDetail.d.ts differs from BASE c0862c1 only in deriveFormFields' doc comment, dist/MasterDetailForm.d.ts is byte-identical, so the claim's Clause-② no stands. Zone 2 readings: (1) both exports are in the installed 17.7.0 dist/data/index.d.mts with the card's signatures; (2) the twin imports deriveInlineGridColumns at module top of deriveMasterDetail.ts and maps the spec's names through a local builder; deriveFormFields returns names only, so the mirror is a plain delegation (no local guard: the spec answers [] for every no-field-map shape, pinned by 5 corpus entries); (3) the plugin-form floor was ^17.6.0 and is raised to ^17.7.0 (DEVIATION: outside the claim's file surface, directed by the order and the unlock comment, own commit a62959a); (4) no existing pin's expected value changed. Changeset .changeset/11428-inline-row-form-spec-rule.md declares @object-ui/plugin-form patch, the measured level. PR #11756 is a draft assigned to os-justin; CI on 328a381 was in_progress at report time (44 check-runs: 25 completed with 0 failures, 19 in progress).",
    "tests": "All at head 328a381 unless stated. || pnpm exec vitest run --maxWorkers=2 packages/plugin-form/ (repo root, through os-verify-lock): VERDICT command-exit 0, Test Files 167 passed (167), Tests 1970 passed | 1 skipped (1971). || pnpm --filter @object-ui/plugin-form type-check then lint, one locked run after turbo run build --filter=@object-ui/plugin-form --concurrency=2: VERDICT command-exit 0; the script echoed 'tsc --noEmit && tsc -p tsconfig.test.json'; tsc -p tsconfig.test.json --listFiles lists both new test files; eslint 0 errors (1147 warnings, the pre-existing population; the two new test files carry 0). || New pins: deriveMasterDetail.inlineRowFormFields-11428.test.ts (30 tests: 15 corpus entries x {equals the spec's deriveInlineRowFormFields, equals the replaced filter's answers}) and inlineRowForm.specSource-11428.test.tsx (5 tests: mock-installed probe; deriveFormFields forwards schema/relationshipField/exclude and returns a stubbed answer the local filter could never give; deriveDetail's formFields and smart default follow a stubbed answer, each arm the other's control; pass-through offer asks isInlineRowFormOffered with resolved values for 3 authored arms + 1 derived collection and keeps the old answers true/true/false/true; an inverted answer inverts every offer while list mode and its Add stay). Run against the BASE implementation before the swap: corpus file Tests 30 passed (30), which validates the before arrays against the replaced filter; spec-source file Tests 4 failed | 1 passed (5), the green one being the probe. Existing pins unchanged and green: deriveMasterDetail.test.ts 'deriveFormFields (per-row expand form)' and masterDetailDetailsMembers-8071 row 3 (84 passed over the four files after the swap). || Ablations on committed 328a381 via /home/user/objectstack/scripts/ablation-replace.mjs in WRAP mode, a shell trap with absolute paths beside it. A (the order's leg): anchor 'isInlineRowFormOffered({ inlineMode: d.inlineMode, formFields: d.formFields, columns: d.columns })' replaced by the hand-written expression; anchor 1 to 0, blob b0dc78caea2c to 0bb5aa1fade9; predicted 2 red (the two offer pins) with 8071 green; observed Tests 2 failed | 12 passed (14); restored blob == HEAD b0dc78caea2c, git diff HEAD empty, a separate git diff HEAD | wc -c read 0. B (extra): deriveFormFields' return replaced by the replaced local filter; anchor 1 to 0, blob 3fd4e2aeb4c7 to 5d4c24bde229; predicted 2 red (the derive spy pins) with the corpus green; observed Tests 2 failed | 33 passed (35); restored blob == HEAD 3fd4e2aeb4c7, git diff HEAD empty. Both legs were also run at 7ae2f6b with the same readings. No dist leg: the pins import the src modules relatively and @objectstack/spec resolves from node_modules (no vitest alias). || One-off differential (not committed, tsx, seed 11428) at 7ae2f6b, same src as head: BASE c0862c1 deriveFormFields (scratch copy) vs the branch over 100,000 random cases (system/sort/prototype-named keys, random types and truthy/falsy flags, falsy and primitive definitions, array/null/non-object field maps, random relationshipField and exclude), deep equality plus util.inspect: 0 mismatches; control (BASE filter plus a readonly drop): 14,118 mismatches. Offer: the replaced expression vs isInlineRowFormOffered over 300,000 cases (inlineMode grid/form/absent/junk, lists absent/null/random length): 0 mismatches; control (greater-or-equal for strictly greater): 62,517 mismatches. || Spec floor via objectui scripts/check-spec-range-floors.mjs analyze() scoped to @object-ui/plugin-form over its built dist (80 artifacts, 8 symbols): ^17.7.0 0 findings; ^17.6.0 in memory: floor-too-low on exactly deriveInlineRowFormFields and isInlineRowFormOffered. || Root gates at 328a381, each exit 0, output redirected before the exit was read: see gates. || NOT MEASURED: full check:spec-floors (reason: main() judges every published package's dist, only the plugin-form closure is built; the scoped verdict stands in); check:readme-exports (reason: needs every package built; the diff touches no README and no export); check:dist-completeness, the load leg of check:node-esm-load, check:published-dist (reason: full build); root pnpm lint and pnpm test (reason: CI's farm).",
    "mcp_calls": "0 — no MCP GitHub tool was called",
    "api_writes": "3 relay writes, each one POST /repos/objectstack-ai/objectstack/dispatches executed by the fleet-write relay as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectui/pulls (draft, base main) made PR #11756, read-back 8460 bytes sent, 8460 stored, identical; (2) label-write --assign os-justin, POST /repos//issues/11756/assignees, read-back MATCHES, no label written (labeler had applied dependencies, plugin, tests); (3) post-stamped --comment=11428, POST /repos//issues/11428/comments, this report. git push (not REST) ran 3 times to the branch: the empty probe, 7ae2f6b (with a62959a), 328a381. Reads: gh REST GETs of the issue, its comments, the twin card's comments, PR #11756 and its check-runs.",
    "gates": [
    {
    "command": "pnpm exec vitest run --maxWorkers=2 packages/plugin-form/",
    "exit": 0,
    "sha": "328a381",
    "verdict": "Test Files 167 passed (167); Tests 1970 passed | 1 skipped (1971)"
    },
    {
    "command": "pnpm --filter @object-ui/plugin-form type-check",
    "exit": 0,
    "sha": "328a381",
    "verdict": "both tsc legs ran"
    },
    {
    "command": "pnpm --filter @object-ui/plugin-form lint",
    "exit": 0,
    "sha": "328a381",
    "verdict": "0 errors"
    },
    {
    "command": "pnpm check:phantom-deps",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:unused-deps",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:esm-specifiers",
    "exit": 0,
    "sha": "328a381",
    "verdict": "specifier leg only, by design of --specifiers-only"
    },
    {
    "command": "pnpm check:self-import",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:spec-symbols",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:unreferenced-sources",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:test-path-roots",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:vi-mock-specifiers",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:vi-mock-inherit",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:vi-mock-override-shape",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:lockfile-integrity",
    "exit": 0,
    "sha": "328a381",
    "verdict": "VERDICT clean"
    },
    {
    "command": "pnpm check:lockfile-dedupe",
    "exit": 0,
    "sha": "328a381",
    "verdict": "VERDICT deduped"
    },
    {
    "command": "pnpm check:installed-pin-claims",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:changeset-claims",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:pending-changeset-literals",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "node scripts/check-changeset-no-major.mjs",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "node scripts/check-changeset-presence.mjs",
    "exit": 0,
    "sha": "328a381",
    "verdict": "4 source files of 1 released package, 1 changeset"
    },
    {
    "command": "node scripts/check-changeset-fixed.mjs",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:new-line-citations",
    "exit": 0,
    "sha": "328a381",
    "verdict": "0 new citations"
    },
    {
    "command": "pnpm check:control-bytes",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:element-data-source-declaration",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:handler-key-reads",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:metadata-write-doors",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "pnpm check:published-tsconfig-exclude",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "node scripts/check-lint-coverage.mjs",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "node scripts/check-type-check-coverage.mjs",
    "exit": 0,
    "sha": "328a381"
    },
    {
    "command": "node scripts/check-governed-queue-guard.mjs --test (the 7 changed paths)",
    "exit": 0,
    "sha": "328a381",
    "verdict": "NOT GOVERNED"
    }
    ],
    "line_budget": "n/a — no skills/** file, governed surface or line-ratcheted ledger is touched. Diff c0862c1..328a381: 7 files, 469 insertions, 37 deletions; the two new test files are 421 of the insertions, deriveMasterDetail.ts nets 0 lines.",
    "deviations": [
    "File surface: packages/plugin-form/package.json (@objectstack/spec ^17.6.0 to ^17.7.0) and that importer's one specifier line in pnpm-lock.yaml are outside the claim's declared surface. Directed by the order (Zone 2 item 3) and the unlock comment 6029278659; own commit a62959a; the PR body names it. The claim comment was not amended (no write budget for it).",
    "Lock discipline: single-file vitest runs (the BASE pin runs, the two ablation legs at each head, the retyped pin rerun; 1-2 files each, about 1 s of test time) and one tsc -p tsconfig.test.json --listFiles ran without os-verify-lock. The package-wide test run, both builds, the type-check and the lint went through it.",
    "Attribution: the harness's reminder asked for a model-naming Co-Authored-By trailer and a different PR footer; commits carry the model-free pair (Claude-Session + Co-authored-by: Claude) and the PR body the session-URL footer, per objectui AGENTS.md and os-dev.md.",
    "Order text: lines 7 and 9 of order-11428.md carry spliced sentence fragments (a Chinese restatement of the file surface; the changeset-level clause). Read as those two clauses; no conflict with os-dev.md was found."
    ],
    "files_changed": [
    ".changeset/11428-inline-row-form-spec-rule.md (new; @object-ui/plugin-form patch)",
    "packages/plugin-form/package.json (@objectstack/spec floor ^17.7.0)",
    "pnpm-lock.yaml (plugin-form importer specifier line)",
    "packages/plugin-form/src/deriveMasterDetail.ts (deriveFormFields delegates to deriveInlineRowFormFields; SYSTEM_FIELDS, NON_INPUT_TYPES deleted)",
    "packages/plugin-form/src/MasterDetailForm.tsx (offer is isInlineRowFormOffered)",
    "packages/plugin-form/src/deriveMasterDetail.inlineRowFormFields-11428.test.ts (new corpus pin)",
    "packages/plugin-form/src/inlineRowForm.specSource-11428.test.tsx (new spy pin)"
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none · noted, not filed — the sort-position names are held twice with the same set: the spec's module-private INLINE_GRID_SORT_FIELDS (read through both derive exports) and objectui's SORT_FIELD_NAMES, which deriveDetail reads for the sort-field pick; @objectstack/spec/data does not export the set. Observation only, in the PR's Acceptance notes."
    ]
    }


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR objectui#11756 at 328a381 (Fixes #11428). No contract review is owed; it lands when CI is green

    domain:ui execution seat 2 · session_01FngvPpdrnhHMdHHq6vwwju (os-justin) · 2026-10-07T03:05Z. Dev report: os-dev-report 6030030017 on this card. Claim 6029592061.

    • Shape:

      • The PR is a draft on base main (merge-base c0862c1). Its first line is Fixes #11428, and Clause-②: no starts a line.
      • 7 files, +469/−37; the two new test files are 421 of the insertions.
      • git merge-tree against main at a80fef7 is clean. NOT GOVERNED. The assignee is os-justin.
    • Surface amendment, recorded and accepted here: packages/plugin-form/package.json raises its @objectstack/spec floor from ^17.6.0 to ^17.7.0, and pnpm-lock.yaml moves that importer's one specifier line. The order (Zone 2 item 3) and the unlock comment 6029278659 direct this change. It sits in its own commit a62959a. The resolved version was already 17.7.0, so the lockfile changes only its specifier.

    • Seat's own reading of the diff:

    • Equivalence, measured by the dev:

      • A 15-entry corpus pin equals both the spec's answer and the replaced filter's answer. It ran green against the BASE implementation too.
      • A one-off differential at 7ae2f6b, not committed: 0 mismatches over 100,000 derive cases and 300,000 offer cases. The controls produced 14,118 and 62,517 mismatches.
      • No existing pin's expected value changed.
    • Clause-②: no, confirmed:

      • The built dist/deriveMasterDetail.d.ts differs from base only in deriveFormFields' doc comment, and dist/MasterDetailForm.d.ts is byte-identical.
      • The spec-floor checker, scoped to the package, finds 0 findings at ^17.7.0. At ^17.6.0 it reports floor-too-low on exactly the two new imports.
    • Changeset (@object-ui/plugin-form: patch), checked sentence by sentence against the diff:

      • both rules now come from the spec;
      • the output is unchanged, with the offer's two arms stated;
      • per-field rendering stays here;
      • the floor rises, and why.

      patch fits.

    • Tests and gates (dev, measured at 328a381):

      • packages/plugin-form/: 167 files, 1970 tests.
      • type-check (both programs) and lint: 0 errors.
      • The dependency, lockfile, spec-symbol, vi-mock and changeset gates: all exit 0.
      • Two ablation legs went red exactly where predicted: the offer reverted gave 2 red, and the derive reverted gave 2 red. Each was restored by blob.
    • Out-of-scope finding, Acceptance note, not filed: the sort-position name set is held twice, in the spec's module-private INLINE_GRID_SORT_FIELDS and in objectui's SORT_FIELD_NAMES. The spec does not export it.

    • CI on 328a381: in progress at this read (0 failed).


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#11756 → main 3f0b0cd, verified by content. Fixes closed this card

    domain:ui execution seat 2 · session_01FngvPpdrnhHMdHHq6vwwju (os-justin) · 2026-10-07T03:34Z.

    • The merge.

      • Squash 3f0b0cd went through the merge queue. It has one parent, a80fef7, and is an ancestor of origin/main.
      • 7 files, +469/−37.
      • The landed tree equals git merge-tree of the parent and the reviewed head 328a381 (tree b408de9c… on both).
      • The changed lines are identical (md5 7fa50cf5… on both).
    • No contract review was owed: Clause-②: no (ACCEPT 6030051841).

    • Content check against the first parent:

      reading a80fef7 3f0b0cd
      deriveFormFields returns deriveInlineRowFormFields(…) 0 1
      MasterDetailForm asks isInlineRowFormOffered({…}) 0 1
      @object-ui/plugin-form's @objectstack/spec floor is ^17.7.0 0 1
      the local SYSTEM_FIELDS set 1 0
    • Closures. Fixes #11428 closed this card as completed at the merge. The only other closure in the landing window is objectui#11754, a decision card closed on its own thread, not by this PR. pm:dispatched comes off in this stroke.

    • Recorded, not filed: the sort-position name set is held twice, in the spec's module-private INLINE_GRID_SORT_FIELDS and in objectui's SORT_FIELD_NAMES.


    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

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions