Skip to content

Commit 48db2cf

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-15330-list-view-grouping-platform-pin
2 parents caab50b + ed9d876 commit 48db2cf

3 files changed

Lines changed: 211 additions & 30 deletions

File tree

content/docs/data-modeling/field-types.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ These properties are available on **all** field types:
653653
| `description` | `string` | — | Field description / help text |
654654
| `type` | `FieldType` | **required** | One of the supported field types |
655655
| `required` | `boolean` | `false` | Whether the field is required |
656-
| `unique` | `boolean \| 'global' \| 'organization'` | `false` | Unique constraint **and its scope** (ADR-0120). `'organization'` = one holder per organization; `true` = that same per-organization scope (positional synonym — prefer the explicit spelling in new code); `'global'` = one holder across the whole installation; `false` = no constraint. `'tenant'`/`'org'` are rejected — the word is `'organization'`. Full rule in the `unique` doc block in [`FieldSchema`](/docs/references/data/field) |
656+
| `unique` | `boolean \| 'global' \| 'organization'` | `false` (`'organization'` on `autonumber`) | Unique constraint **and its scope** (ADR-0120). `'organization'` = one holder per organization; `true` = that same per-organization scope (positional synonym — prefer the explicit spelling in new code); `'global'` = one holder across the whole installation; `false` = no constraint. Omitted ⇒ `false`, except on an `autonumber` field, where omitted ⇒ `'organization'` — an auto-number is a business identifier, so the platform makes it unique per organization by default; write `unique: false` explicitly to opt out. `'tenant'`/`'org'` are rejected — the word is `'organization'`. Full rule in the `unique` doc block in [`FieldSchema`](/docs/references/data/field) |
657657
| `multiple` | `boolean` | `false` | Allow array of values (multi-record lookup, multi-select, multi-file). An emptied multi-value lookup reads back as `[]`, never `null` — the `multiple` doc block in [`FieldSchema`](/docs/references/data/field) |
658658
| `searchable` | `boolean` | `false` | Include in search index |
659659
| `sortable` | `boolean` | `true` | Allow sorting by this field |

scripts/check-durability-degradation-log-level.mjs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4201,11 +4201,21 @@ function reportDepthCost() {
42014201
// fixtures pin both directions: it must FLAG the #4420 shape and must NOT flag
42024202
// the shapes that are legitimately `warn`.
42034203

4204-
// Set by `selfTest()` only after its verdict is printed, and read at the
4205-
// dispatch: a `return` that leaves the function above that line prints nothing
4206-
// and still exits 0 — a self-test that never finished, reported as one that
4207-
// passed (#13798). The self-test's own exit code stays load-bearing, so the
4208-
// handshake is a flag rather than a returned sentinel.
4204+
// Set by `selfTest()` at BOTH its verdict sites — the green line and the red
4205+
// one — and read at the dispatch AFTER both batteries have run. What it asserts
4206+
// is "ran to the end", pass or fail: a `return` that leaves the function above
4207+
// both verdict lines prints nothing and still exits 0 — a self-test that never
4208+
// finished, reported as one that passed (#13798). The self-test's own exit code
4209+
// stays load-bearing, so the handshake is a flag rather than a returned sentinel.
4210+
//
4211+
// ⛔ Not the sibling gates' shape, deliberately (#14962). Those set the flag on
4212+
// the success path alone, which is sound THERE because their failure path calls
4213+
// `process.exit(1)` inside the self-test, so the flag is never consulted on a
4214+
// red. Here the failure path `return`s and the dispatch keeps running, so a
4215+
// success-only flag reads a genuine red as "never reached its verdict" — a false
4216+
// diagnostic that sends a maintainer hunting for a truncated run that did not
4217+
// happen, and, when the flag was read between the two calls, stopped the second
4218+
// battery from running at all.
42094219
let selfTestReachedVerdict = false;
42104220

42114221
// ── The two self-tests' battery roster and floors (#13489, batch 10c) ────────
@@ -5526,6 +5536,12 @@ function selfTest() {
55265536
);
55275537
if (failures > 0) {
55285538
console.error(`\n✗ self-test (log-level rule): ${failures} failure(s) (cases and floor)\n`);
5539+
// A printed red verdict IS a reached verdict (#14962). The handshake
5540+
// asserts "ran to the end", pass or FAIL; the returned 1 keeps carrying
5541+
// the verdict, so the dispatch still exits 1. Set HERE, adjacent to the
5542+
// line it certifies, rather than once before the branch: the flag can
5543+
// then only be true if one of the two verdict lines was really printed.
5544+
selfTestReachedVerdict = true;
55295545
return 1;
55305546
}
55315547
console.log(`\n✓ self-test (log-level rule): ${cases.length} case(s) passed\n`);
@@ -5543,7 +5559,9 @@ function selfTest() {
55435559
// three instances, in both directions, or the fourth recurrence lands green.
55445560
// The dispatch calls TWO self-test entries and combines their statuses, so each
55455561
// one needs its own handshake: a `return` above either verdict prints nothing and
5546-
// leaves `undefined`, which the `||` below reads as a pass (#13798).
5562+
// leaves `undefined`, which the `||` below reads as a pass (#13798). Set at both
5563+
// of this battery's verdict sites, green and red, for the reason spelled out at
5564+
// `selfTestReachedVerdict` (#14962).
55475565
let readSeamsReachedVerdict = false;
55485566

55495567
function selfTestReadSeams() {
@@ -6793,6 +6811,9 @@ function selfTestReadSeams() {
67936811
);
67946812
if (failures > 0) {
67956813
console.error(`\n✗ self-test (read-seam invention rule): ${failures} failure(s) (cases and floor)\n`);
6814+
// Its own handshake, same reading as `selfTest`'s red path (#14962): a
6815+
// printed red verdict is a reached verdict, and the returned 1 carries it.
6816+
readSeamsReachedVerdict = true;
67966817
return 1;
67976818
}
67986819
console.log(
@@ -6805,26 +6826,35 @@ function selfTestReadSeams() {
68056826

68066827
const args = process.argv.slice(2);
68076828
if (args.includes('--self-test')) {
6808-
// Both rules' fixtures always run — a red one must not hide the other.
6829+
// Both rules' fixtures always run — a red one must not hide the other. That
6830+
// is why BOTH batteries run BEFORE either handshake is read (#14962): reading
6831+
// the first handshake between the two calls exited the process on a red
6832+
// battery 1, so battery 2 never ran — the very thing this comment forbids —
6833+
// and it did so under a message saying no verdict had been reached, while the
6834+
// red verdict line sat directly above it in the same output.
68096835
const logLevelStatus = selfTest();
6836+
const readSeamStatus = selfTestReadSeams();
6837+
// Read AFTER both have reported. An early `return` from either one still
6838+
// trips its own named diagnostic here; a genuine red does not, because a
6839+
// printed verdict sets the flag.
6840+
let handshakeMissing = false;
68106841
if (!selfTestReachedVerdict) {
68116842
console.error(
68126843
'\n✗ check-durability-degradation-log-level self-test: selfTest() returned without reaching its verdict,\n'
68136844
+ 'so no success line was printed. Exiting 0 here would report a self-test\n'
68146845
+ 'that never finished as a self-test that passed.\n',
68156846
);
6816-
process.exit(1);
6847+
handshakeMissing = true;
68176848
}
6818-
const readSeamStatus = selfTestReadSeams();
68196849
if (!readSeamsReachedVerdict) {
68206850
console.error(
68216851
'\n✗ check-durability-degradation-log-level self-test: selfTestReadSeams() returned without\n'
68226852
+ 'reaching its verdict, so no success line was printed. Exiting 0 here would report a\n'
68236853
+ 'self-test that never finished as a self-test that passed.\n',
68246854
);
6825-
process.exit(1);
6855+
handshakeMissing = true;
68266856
}
6827-
process.exit(logLevelStatus || readSeamStatus ? 1 : 0);
6857+
process.exit(handshakeMissing || logLevelStatus || readSeamStatus ? 1 : 0);
68286858
} else if (args.includes('--depth-cost')) {
68296859
// A diagnostic, deliberately not part of any verdict — see `reportDepthCost`.
68306860
process.exit(reportDepthCost());

0 commit comments

Comments
 (0)