@things-factory/worklist 10.1.254 → 10.1.256
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/work-door/work-door-declaration.d.ts +5 -4
- package/dist-server/service/work-door/work-door-declaration.js +17 -5
- package/dist-server/service/work-door/work-door-declaration.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
|
@@ -102,11 +102,12 @@ export interface WorkDoorRegistration {
|
|
|
102
102
|
seats?: readonly string[];
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
|
-
* An application declares its doors. Called at module import time
|
|
105
|
+
* An application declares its doors. Called at module import time.
|
|
106
106
|
*
|
|
107
|
-
*
|
|
108
|
-
* watch rebuild would otherwise show every door twice, and a screen that double-counts the doors
|
|
109
|
-
*
|
|
107
|
+
* A module registered again keeps one door per name, the later declaration of a name winning: a module imported twice
|
|
108
|
+
* under a watch rebuild would otherwise show every door twice, and a screen that double-counts the doors that need
|
|
109
|
+
* attention is one nobody trusts. A module that declares its doors in more than one call keeps all of them - replacing
|
|
110
|
+
* the whole registration dropped the earlier call's doors without a word.
|
|
110
111
|
*/
|
|
111
112
|
export declare function registerWorkDoors(registration: WorkDoorRegistration): void;
|
|
112
113
|
/** Every registration in this installation, in registration order. */
|
|
@@ -36,14 +36,26 @@ exports.declaredDoor = declaredDoor;
|
|
|
36
36
|
exports.whyNotUsedCannotBeDeclared = whyNotUsedCannotBeDeclared;
|
|
37
37
|
const registered = new Map();
|
|
38
38
|
/**
|
|
39
|
-
* An application declares its doors. Called at module import time
|
|
39
|
+
* An application declares its doors. Called at module import time.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
* watch rebuild would otherwise show every door twice, and a screen that double-counts the doors
|
|
43
|
-
*
|
|
41
|
+
* A module registered again keeps one door per name, the later declaration of a name winning: a module imported twice
|
|
42
|
+
* under a watch rebuild would otherwise show every door twice, and a screen that double-counts the doors that need
|
|
43
|
+
* attention is one nobody trusts. A module that declares its doors in more than one call keeps all of them - replacing
|
|
44
|
+
* the whole registration dropped the earlier call's doors without a word.
|
|
44
45
|
*/
|
|
45
46
|
function registerWorkDoors(registration) {
|
|
46
|
-
registered.
|
|
47
|
+
const earlier = registered.get(registration.module);
|
|
48
|
+
if (!earlier) {
|
|
49
|
+
registered.set(registration.module, registration);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const names = new Set(registration.doors.map(door => door.name));
|
|
53
|
+
registered.set(registration.module, {
|
|
54
|
+
...earlier,
|
|
55
|
+
...registration,
|
|
56
|
+
doors: [...earlier.doors.filter(door => !names.has(door.name)), ...registration.doors],
|
|
57
|
+
seats: [...new Set([...(earlier.seats ?? []), ...(registration.seats ?? [])])]
|
|
58
|
+
});
|
|
47
59
|
}
|
|
48
60
|
/** Every registration in this installation, in registration order. */
|
|
49
61
|
function registeredWorkDoors() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-door-declaration.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-declaration.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;AAoFH,8CAEC;AAGD,kDAEC;AAGD,sCAEC;AAGD,4CAEC;AAGD,oCAUC;AAgBD,gEAEC;AAzDD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAA;AAE1D;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAAC,YAAkC;IAClE,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;AACnD,CAAC;AAED,sEAAsE;AACtE,SAAgB,mBAAmB;IACjC,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAA;AACjC,CAAC;AAED,6DAA6D;AAC7D,SAAgB,aAAa;IAC3B,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;AAChE,CAAC;AAED,6EAA6E;AAC7E,SAAgB,gBAAgB;IAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACtF,CAAC;AAED,2DAA2D;AAC3D,SAAgB,YAAY,CAAC,IAAY;IACvC,KAAK,MAAM,YAAY,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;QAEjE,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,0BAA0B,CAAC,IAAyB;IAClE,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5F,CAAC","sourcesContent":["/**\n * **What an application declares about its own work doors** (ADR-0069 decision 3, ADR-0077).\n *\n * ═══════════════════════════════════════════════════════════════════════════\n * ── Who says what ─────────────────────────────────────────────────────────\n * The form is installed by the product at boot, and the plant fills in who approves it. Filling it\n * in is the declaration that this factory uses that step. So two facts have two owners:\n *\n * ```\n * the list of doors, and what each one is the application - it declares them here\n * whether a door stands in this domain the worklist - it reads the activity and its line\n * ```\n *\n * An application registers its list; the screens and the judgement live here. Without that split the\n * worklist would have to know operato-plant's activities, and every application would carry its own\n * copy of the same screen (operato-warehouse asked for it second, which is what moved this).\n *\n * ── Registration happens at module import ─────────────────────────────────\n * Not on a bootstrap hook. A hook runs after the schema is built, which is too late for anything the\n * schema or a boot-time install reads - `declareAxes` in auth-base carries the same warning.\n *\n * ── Nobody declares a label ───────────────────────────────────────────────\n * The screen's label key is computed from `name` (`activityTKey(name, 'label')`), the same key the\n * activity catalog reads. A declared key used to ride here, and operato-plant built it from the\n * PascalCase name while its translations are kebab-cased - the door screen printed twenty-four raw\n * keys (:4000, 2026-09-24). A key nobody picks is a key nobody can pick wrong.\n * ═══════════════════════════════════════════════════════════════════════════\n */\n\n/**\n * What happens when the approval line is empty. **This records what each door already does** - it is\n * not a new policy (ADR-0077 decision 1).\n *\n * - `run` - the work happens and the approval step is skipped. The worklist writes a line saying so;\n * until that record existed there was no way to tell it from a factory that approved it.\n * - `refuse` - the caller is refused and told why the line does not stand.\n * - `as-established` - the branch depends on **the row's own history**: a period declared through\n * approval is withdrawn through approval, and one that stood without approval is simply removed.\n * Only a door whose branch turns on the row may use this, and both branches are tested. The\n * judgement stays with the door; the worklist asks it which way this row goes.\n */\nexport type WhenNoLine = 'refuse' | 'run' | 'as-established'\n\n/**\n * Why a door refuses rather than running. Two doors that both refuse can refuse for different\n * reasons, and an administrator reads the reason to know whether filling the line is the fix.\n *\n * - `irreversible` - what the door does cannot be taken back (`mutation-reversibility`).\n * - `approval-is-the-act` - the door's whole work **is** the approval. Letting it through with no\n * line would put an unsigned controlled document on the floor.\n * - `lowers-a-control` - the door lowers a control that stands: turning document control off, or\n * moving a maintenance due date. Such a door refuses whatever its reversibility says, because the\n * time that passed under the lowered control does not come back.\n */\nexport type WhenNoLineBecause = 'irreversible' | 'approval-is-the-act' | 'lowers-a-control'\n\ninterface DoorBase {\n /** The form name - the same key the callback is found by. Labels change; this does not. */\n name: string\n /**\n * @deprecated **Not read.** The label key is computed from `name`. Kept optional only so a\n * declaration built against the previous release still compiles; operato-plant and\n * operato-warehouse drop it, and then this line goes (worklist-ux-handoff, 2026-09-24).\n */\n labelKey?: string\n /**\n * This door borrows another door's approval line. Written once, in one place: two doors carrying\n * the same line as a value drift, and then turning a control on and off are approved by different\n * people (ADR-0047 ⑨).\n */\n lineFollows?: string\n}\n\ntype ApprovalDoor = DoorBase & { kind: 'approval' } & (\n | { whenNoLine: 'run'; because?: never }\n | { whenNoLine: 'refuse' | 'as-established'; because: WhenNoLineBecause }\n )\n\n/**\n * `whenNoLine?: never` is the point of this type: an assignment door has no approval line, so the\n * field cannot be written here at all. Left optional it would be filled in one day with a value that\n * reads true and means nothing.\n */\ntype AssignmentDoor = DoorBase & { kind: 'assignment'; whenNoLine?: never; because?: never }\n\nexport type WorkDoorDeclaration = ApprovalDoor | AssignmentDoor\n\nexport interface WorkDoorRegistration {\n /** The declaring module, as its package's short name. It groups the screen and names the source. */\n module: string\n doors: readonly WorkDoorDeclaration[]\n /**\n * The role seats this module offers, by name.\n *\n * An approval line points at roles, so a domain with none of them cannot build one - and today\n * that is found out on the form screen, too late. The door screen counts how many of these stand\n * here and says what to do first. A domain's own roles are not counted: this number answers \"of\n * what the product offered\", and a line built from other roles works just as well.\n */\n seats?: readonly string[]\n}\n\nconst registered = new Map<string, WorkDoorRegistration>()\n\n/**\n * An application declares its doors. Called at module import time, once per module.\n *\n * Re-registering the same module replaces it rather than appending: a module imported twice under a\n * watch rebuild would otherwise show every door twice, and a screen that double-counts the doors\n * that need attention is one nobody trusts.\n */\nexport function registerWorkDoors(registration: WorkDoorRegistration): void {\n registered.set(registration.module, registration)\n}\n\n/** Every registration in this installation, in registration order. */\nexport function registeredWorkDoors(): WorkDoorRegistration[] {\n return [...registered.values()]\n}\n\n/** Every declared door, flattened, in registration order. */\nexport function declaredDoors(): WorkDoorDeclaration[] {\n return [...registered.values()].flatMap(one => [...one.doors])\n}\n\n/** Every role seat the declaring modules offer, by name, without repeats. */\nexport function offeredSeatNames(): string[] {\n return [...new Set([...registered.values()].flatMap(one => [...(one.seats ?? [])]))]\n}\n\n/** One door by form name, whichever module declared it. */\nexport function declaredDoor(name: string): WorkDoorDeclaration | undefined {\n for (const registration of registered.values()) {\n const found = registration.doors.find(door => door.name === name)\n\n if (found) {\n return found\n }\n }\n\n return undefined\n}\n\n/**\n * **Can this door be declared unused?** Not when it refuses on an empty line (ADR-0077 decision 3).\n *\n * \"We do not use this door\" means the work runs with no approval step (`ran-not-used`). `refuse`\n * means the work cannot stand without an approval line. The two cannot hold for one door, and each of\n * the three reasons says why: what an `irreversible` door does cannot be taken back, an\n * `approval-is-the-act` door's work is the approval, and a `lowers-a-control` door lowers a control\n * that stands. Accepting the declaration would leave the door screen showing the door as off while\n * the product still demands approval - or, if the product honoured it, run those three kinds of work\n * unapproved.\n *\n * Answers the reason, so the refusal can say which one. `run`, `as-established` and assignment doors\n * answer nothing - they can be declared unused as before.\n */\nexport function whyNotUsedCannotBeDeclared(door: WorkDoorDeclaration): WhenNoLineBecause | undefined {\n return door.kind === 'approval' && door.whenNoLine === 'refuse' ? door.because : undefined\n}\n"]}
|
|
1
|
+
{"version":3,"file":"work-door-declaration.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-declaration.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;AAqFH,8CAaC;AAGD,kDAEC;AAGD,sCAEC;AAGD,4CAEC;AAGD,oCAUC;AAgBD,gEAEC;AArED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAA;AAE1D;;;;;;;GAOG;AACH,SAAgB,iBAAiB,CAAC,YAAkC;IAClE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;IACnD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;QACjD,OAAM;IACR,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAChE,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE;QAClC,GAAG,OAAO;QACV,GAAG,YAAY;QACf,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;QACtF,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;KAC/E,CAAC,CAAA;AACJ,CAAC;AAED,sEAAsE;AACtE,SAAgB,mBAAmB;IACjC,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAA;AACjC,CAAC;AAED,6DAA6D;AAC7D,SAAgB,aAAa;IAC3B,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;AAChE,CAAC;AAED,6EAA6E;AAC7E,SAAgB,gBAAgB;IAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACtF,CAAC;AAED,2DAA2D;AAC3D,SAAgB,YAAY,CAAC,IAAY;IACvC,KAAK,MAAM,YAAY,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;QAEjE,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,0BAA0B,CAAC,IAAyB;IAClE,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5F,CAAC","sourcesContent":["/**\n * **What an application declares about its own work doors** (ADR-0069 decision 3, ADR-0077).\n *\n * ═══════════════════════════════════════════════════════════════════════════\n * ── Who says what ─────────────────────────────────────────────────────────\n * The form is installed by the product at boot, and the plant fills in who approves it. Filling it\n * in is the declaration that this factory uses that step. So two facts have two owners:\n *\n * ```\n * the list of doors, and what each one is the application - it declares them here\n * whether a door stands in this domain the worklist - it reads the activity and its line\n * ```\n *\n * An application registers its list; the screens and the judgement live here. Without that split the\n * worklist would have to know operato-plant's activities, and every application would carry its own\n * copy of the same screen (operato-warehouse asked for it second, which is what moved this).\n *\n * ── Registration happens at module import ─────────────────────────────────\n * Not on a bootstrap hook. A hook runs after the schema is built, which is too late for anything the\n * schema or a boot-time install reads - `declareAxes` in auth-base carries the same warning.\n *\n * ── Nobody declares a label ───────────────────────────────────────────────\n * The screen's label key is computed from `name` (`activityTKey(name, 'label')`), the same key the\n * activity catalog reads. A declared key used to ride here, and operato-plant built it from the\n * PascalCase name while its translations are kebab-cased - the door screen printed twenty-four raw\n * keys (:4000, 2026-09-24). A key nobody picks is a key nobody can pick wrong.\n * ═══════════════════════════════════════════════════════════════════════════\n */\n\n/**\n * What happens when the approval line is empty. **This records what each door already does** - it is\n * not a new policy (ADR-0077 decision 1).\n *\n * - `run` - the work happens and the approval step is skipped. The worklist writes a line saying so;\n * until that record existed there was no way to tell it from a factory that approved it.\n * - `refuse` - the caller is refused and told why the line does not stand.\n * - `as-established` - the branch depends on **the row's own history**: a period declared through\n * approval is withdrawn through approval, and one that stood without approval is simply removed.\n * Only a door whose branch turns on the row may use this, and both branches are tested. The\n * judgement stays with the door; the worklist asks it which way this row goes.\n */\nexport type WhenNoLine = 'refuse' | 'run' | 'as-established'\n\n/**\n * Why a door refuses rather than running. Two doors that both refuse can refuse for different\n * reasons, and an administrator reads the reason to know whether filling the line is the fix.\n *\n * - `irreversible` - what the door does cannot be taken back (`mutation-reversibility`).\n * - `approval-is-the-act` - the door's whole work **is** the approval. Letting it through with no\n * line would put an unsigned controlled document on the floor.\n * - `lowers-a-control` - the door lowers a control that stands: turning document control off, or\n * moving a maintenance due date. Such a door refuses whatever its reversibility says, because the\n * time that passed under the lowered control does not come back.\n */\nexport type WhenNoLineBecause = 'irreversible' | 'approval-is-the-act' | 'lowers-a-control'\n\ninterface DoorBase {\n /** The form name - the same key the callback is found by. Labels change; this does not. */\n name: string\n /**\n * @deprecated **Not read.** The label key is computed from `name`. Kept optional only so a\n * declaration built against the previous release still compiles; operato-plant and\n * operato-warehouse drop it, and then this line goes (worklist-ux-handoff, 2026-09-24).\n */\n labelKey?: string\n /**\n * This door borrows another door's approval line. Written once, in one place: two doors carrying\n * the same line as a value drift, and then turning a control on and off are approved by different\n * people (ADR-0047 ⑨).\n */\n lineFollows?: string\n}\n\ntype ApprovalDoor = DoorBase & { kind: 'approval' } & (\n | { whenNoLine: 'run'; because?: never }\n | { whenNoLine: 'refuse' | 'as-established'; because: WhenNoLineBecause }\n )\n\n/**\n * `whenNoLine?: never` is the point of this type: an assignment door has no approval line, so the\n * field cannot be written here at all. Left optional it would be filled in one day with a value that\n * reads true and means nothing.\n */\ntype AssignmentDoor = DoorBase & { kind: 'assignment'; whenNoLine?: never; because?: never }\n\nexport type WorkDoorDeclaration = ApprovalDoor | AssignmentDoor\n\nexport interface WorkDoorRegistration {\n /** The declaring module, as its package's short name. It groups the screen and names the source. */\n module: string\n doors: readonly WorkDoorDeclaration[]\n /**\n * The role seats this module offers, by name.\n *\n * An approval line points at roles, so a domain with none of them cannot build one - and today\n * that is found out on the form screen, too late. The door screen counts how many of these stand\n * here and says what to do first. A domain's own roles are not counted: this number answers \"of\n * what the product offered\", and a line built from other roles works just as well.\n */\n seats?: readonly string[]\n}\n\nconst registered = new Map<string, WorkDoorRegistration>()\n\n/**\n * An application declares its doors. Called at module import time.\n *\n * A module registered again keeps one door per name, the later declaration of a name winning: a module imported twice\n * under a watch rebuild would otherwise show every door twice, and a screen that double-counts the doors that need\n * attention is one nobody trusts. A module that declares its doors in more than one call keeps all of them - replacing\n * the whole registration dropped the earlier call's doors without a word.\n */\nexport function registerWorkDoors(registration: WorkDoorRegistration): void {\n const earlier = registered.get(registration.module)\n if (!earlier) {\n registered.set(registration.module, registration)\n return\n }\n const names = new Set(registration.doors.map(door => door.name))\n registered.set(registration.module, {\n ...earlier,\n ...registration,\n doors: [...earlier.doors.filter(door => !names.has(door.name)), ...registration.doors],\n seats: [...new Set([...(earlier.seats ?? []), ...(registration.seats ?? [])])]\n })\n}\n\n/** Every registration in this installation, in registration order. */\nexport function registeredWorkDoors(): WorkDoorRegistration[] {\n return [...registered.values()]\n}\n\n/** Every declared door, flattened, in registration order. */\nexport function declaredDoors(): WorkDoorDeclaration[] {\n return [...registered.values()].flatMap(one => [...one.doors])\n}\n\n/** Every role seat the declaring modules offer, by name, without repeats. */\nexport function offeredSeatNames(): string[] {\n return [...new Set([...registered.values()].flatMap(one => [...(one.seats ?? [])]))]\n}\n\n/** One door by form name, whichever module declared it. */\nexport function declaredDoor(name: string): WorkDoorDeclaration | undefined {\n for (const registration of registered.values()) {\n const found = registration.doors.find(door => door.name === name)\n\n if (found) {\n return found\n }\n }\n\n return undefined\n}\n\n/**\n * **Can this door be declared unused?** Not when it refuses on an empty line (ADR-0077 decision 3).\n *\n * \"We do not use this door\" means the work runs with no approval step (`ran-not-used`). `refuse`\n * means the work cannot stand without an approval line. The two cannot hold for one door, and each of\n * the three reasons says why: what an `irreversible` door does cannot be taken back, an\n * `approval-is-the-act` door's work is the approval, and a `lowers-a-control` door lowers a control\n * that stands. Accepting the declaration would leave the door screen showing the door as off while\n * the product still demands approval - or, if the product honoured it, run those three kinds of work\n * unapproved.\n *\n * Answers the reason, so the refusal can say which one. `run`, `as-established` and assignment doors\n * answer nothing - they can be declared unused as before.\n */\nexport function whyNotUsedCannotBeDeclared(door: WorkDoorDeclaration): WhenNoLineBecause | undefined {\n return door.kind === 'approval' && door.whenNoLine === 'refuse' ? door.because : undefined\n}\n"]}
|