@clossys/writer 0.3.9 → 0.5.0
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/README.md +647 -6
- package/dist/addressability.d.ts +11 -1
- package/dist/addressability.d.ts.map +1 -1
- package/dist/addressability.js +169 -3
- package/dist/addressability.js.map +1 -1
- package/dist/approval-bypass.d.ts +120 -0
- package/dist/approval-bypass.d.ts.map +1 -0
- package/dist/approval-bypass.js +2318 -0
- package/dist/approval-bypass.js.map +1 -0
- package/dist/approval.d.ts +62 -0
- package/dist/approval.d.ts.map +1 -0
- package/dist/approval.js +421 -0
- package/dist/approval.js.map +1 -0
- package/dist/approve-cli.d.ts +82 -0
- package/dist/approve-cli.d.ts.map +1 -0
- package/dist/approve-cli.js +430 -0
- package/dist/approve-cli.js.map +1 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +264 -22
- package/dist/cli.js.map +1 -1
- package/dist/field-options.d.ts +59 -0
- package/dist/field-options.d.ts.map +1 -0
- package/dist/field-options.js +109 -0
- package/dist/field-options.js.map +1 -0
- package/dist/fold-wallpaper-gate.d.ts +7 -0
- package/dist/fold-wallpaper-gate.d.ts.map +1 -0
- package/dist/fold-wallpaper-gate.js +29 -0
- package/dist/fold-wallpaper-gate.js.map +1 -0
- package/dist/front-door.check.d.ts +2 -0
- package/dist/front-door.check.d.ts.map +1 -0
- package/dist/front-door.check.js +8 -0
- package/dist/front-door.check.js.map +1 -0
- package/dist/front-door.d.ts +82 -0
- package/dist/front-door.d.ts.map +1 -0
- package/dist/front-door.js +271 -0
- package/dist/front-door.js.map +1 -0
- package/dist/generated/advisor-plan-contract.generated.d.ts +3 -0
- package/dist/generated/advisor-plan-contract.generated.d.ts.map +1 -0
- package/dist/generated/advisor-plan-contract.generated.js +430 -0
- package/dist/generated/advisor-plan-contract.generated.js.map +1 -0
- package/dist/generated/contract-schema.generated.d.ts +97 -0
- package/dist/generated/contract-schema.generated.d.ts.map +1 -0
- package/dist/generated/contract-schema.generated.js +496 -0
- package/dist/generated/contract-schema.generated.js.map +1 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -1
- package/dist/live-copy-gate.d.ts +16 -0
- package/dist/live-copy-gate.d.ts.map +1 -0
- package/dist/live-copy-gate.js +135 -0
- package/dist/live-copy-gate.js.map +1 -0
- package/dist/messaging-kit.d.ts +113 -0
- package/dist/messaging-kit.d.ts.map +1 -0
- package/dist/messaging-kit.js +121 -0
- package/dist/messaging-kit.js.map +1 -0
- package/dist/passage.d.ts +2 -1
- package/dist/passage.d.ts.map +1 -1
- package/dist/passage.js +2 -1
- package/dist/passage.js.map +1 -1
- package/dist/plan-authority.d.ts +73 -0
- package/dist/plan-authority.d.ts.map +1 -0
- package/dist/plan-authority.js +126 -0
- package/dist/plan-authority.js.map +1 -0
- package/dist/plan-contract.d.ts +16 -0
- package/dist/plan-contract.d.ts.map +1 -0
- package/dist/plan-contract.js +33 -0
- package/dist/plan-contract.js.map +1 -0
- package/dist/plan-digest.d.ts +23 -0
- package/dist/plan-digest.d.ts.map +1 -0
- package/dist/plan-digest.js +82 -0
- package/dist/plan-digest.js.map +1 -0
- package/dist/plan-rules.d.ts +54 -0
- package/dist/plan-rules.d.ts.map +1 -0
- package/dist/plan-rules.js +145 -0
- package/dist/plan-rules.js.map +1 -0
- package/dist/render-registry-parity.d.ts +20 -0
- package/dist/render-registry-parity.d.ts.map +1 -0
- package/dist/render-registry-parity.js +45 -0
- package/dist/render-registry-parity.js.map +1 -0
- package/dist/resolve.d.ts +40 -6
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +144 -18
- package/dist/resolve.js.map +1 -1
- package/dist/scan.d.ts +32 -0
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +67 -6
- package/dist/scan.js.map +1 -1
- package/dist/schema.d.ts +1 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +231 -5
- package/dist/schema.js.map +1 -1
- package/dist/site-identity.d.ts +88 -0
- package/dist/site-identity.d.ts.map +1 -0
- package/dist/site-identity.js +82 -0
- package/dist/site-identity.js.map +1 -0
- package/dist/treatment-word-budget.d.ts +31 -0
- package/dist/treatment-word-budget.d.ts.map +1 -0
- package/dist/treatment-word-budget.js +80 -0
- package/dist/treatment-word-budget.js.map +1 -0
- package/dist/types.d.ts +76 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -7
- package/dist/types.js.map +1 -1
- package/fit-signals.json +11 -0
- package/package.json +201 -11
- package/skill/SKILL.md +49 -0
- package/src/addressability.ts +186 -4
- package/src/approval-bypass.ts +2263 -0
- package/src/approval.ts +491 -0
- package/src/approve-cli.ts +474 -0
- package/src/cli.ts +274 -22
- package/src/field-options.ts +134 -0
- package/src/fold-wallpaper-gate.ts +29 -0
- package/src/front-door.check.ts +10 -0
- package/src/front-door.ts +312 -0
- package/src/generated/advisor-plan-contract.generated.ts +430 -0
- package/src/generated/contract-schema.generated.ts +520 -0
- package/src/index.ts +107 -1
- package/src/live-copy-gate.ts +150 -0
- package/src/messaging-kit.ts +195 -0
- package/src/passage.ts +2 -1
- package/src/plan-authority.ts +160 -0
- package/src/plan-contract.ts +45 -0
- package/src/plan-digest.ts +81 -0
- package/src/plan-rules.ts +179 -0
- package/src/render-registry-parity.ts +65 -0
- package/src/resolve.ts +185 -19
- package/src/scan.ts +97 -6
- package/src/schema.ts +247 -5
- package/src/site-identity.ts +125 -0
- package/src/treatment-word-budget.ts +100 -0
- package/src/types.ts +83 -7
- package/templates/front-door.en.json +426 -0
- package/CHANGELOG.md +0 -330
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The site-identity copy kind: a site's name and tagline, resolved from a
|
|
3
|
+
* `CopyRegistry` under two reserved entry ids.
|
|
4
|
+
*
|
|
5
|
+
* A page-metadata consumer needs exactly two short strings — what the site
|
|
6
|
+
* is called and one line about it — and needs them to carry the same
|
|
7
|
+
* approval evidence as any other rendered copy. This module does not add a
|
|
8
|
+
* second approval path for them. It asks `resolveCopyRef` for
|
|
9
|
+
* `"site.name"` and `"site.tagline"`, so whatever that resolver refuses
|
|
10
|
+
* (a draft entry, an approval record that no longer matches its text, an
|
|
11
|
+
* expired delegate approval, a delegate approval on `"production"` without
|
|
12
|
+
* the caller's opt-in, a locale mismatch, an unknown id, an invalid
|
|
13
|
+
* registry or options object) is refused here for the same reason.
|
|
14
|
+
*
|
|
15
|
+
* On top of that resolver this module adds two refusals of its own,
|
|
16
|
+
* because a name and a tagline are literal text rather than templates: an
|
|
17
|
+
* entry that declares placeholders (or whose text the resolver would
|
|
18
|
+
* rewrite), and a resolved text that is blank after trimming.
|
|
19
|
+
*
|
|
20
|
+
* The result is all-or-nothing. Both fields are always attempted so a
|
|
21
|
+
* caller sees every problem at once, but `identity` and `resolutions` are
|
|
22
|
+
* present only when both fields resolved — there is no partial identity.
|
|
23
|
+
* Nothing here throws for any input; malformed input yields a result with
|
|
24
|
+
* `complete: false` and an issue. Nothing here reads a brand-facts record
|
|
25
|
+
* or consumes the result; wiring it into a page-metadata builder is a
|
|
26
|
+
* separate change.
|
|
27
|
+
*
|
|
28
|
+
* No real copy ships here. The ids are reserved names; the words are the
|
|
29
|
+
* consumer's own.
|
|
30
|
+
*/
|
|
31
|
+
import type { CopyResolveIssue, CopyResolveIssueReason, CopyResolveOptions } from "./resolve.js";
|
|
32
|
+
import type { CopyRegistry, CopyResolution } from "./types.js";
|
|
33
|
+
/** Reserved copy id for the site's name. */
|
|
34
|
+
export declare const SITE_NAME_COPY_ID = "site.name";
|
|
35
|
+
/** Reserved copy id for the site's tagline. */
|
|
36
|
+
export declare const SITE_TAGLINE_COPY_ID = "site.tagline";
|
|
37
|
+
/** Both reserved site-identity copy ids, name first. */
|
|
38
|
+
export declare const SITE_IDENTITY_COPY_IDS: readonly ["site.name", "site.tagline"];
|
|
39
|
+
/** Which half of the site identity an issue is about. */
|
|
40
|
+
export type SiteIdentityField = "name" | "tagline";
|
|
41
|
+
/**
|
|
42
|
+
* Every reason `resolveSiteIdentity` can report: whatever `resolveCopyRef`
|
|
43
|
+
* refuses, plus the two refusals specific to site identity.
|
|
44
|
+
* `"site-identity-blank"` means the resolved text was empty after trimming;
|
|
45
|
+
* `"site-identity-placeholder"` means the entry declares placeholders or
|
|
46
|
+
* its text is one the resolver would rewrite.
|
|
47
|
+
*/
|
|
48
|
+
export type SiteIdentityIssueReason = CopyResolveIssueReason | "site-identity-blank" | "site-identity-placeholder";
|
|
49
|
+
/** One reason a site identity could not be resolved, tagged with its field. */
|
|
50
|
+
export interface SiteIdentityIssue extends Omit<CopyResolveIssue, "reason"> {
|
|
51
|
+
reason: SiteIdentityIssueReason;
|
|
52
|
+
field: SiteIdentityField;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The outcome of `resolveSiteIdentity`. `identity` and `resolutions` are
|
|
56
|
+
* present only when `complete` is `true`; `issues` is empty exactly then.
|
|
57
|
+
*/
|
|
58
|
+
export interface SiteIdentityResolution {
|
|
59
|
+
complete: boolean;
|
|
60
|
+
identity?: {
|
|
61
|
+
name: string;
|
|
62
|
+
tagline: string;
|
|
63
|
+
};
|
|
64
|
+
resolutions?: {
|
|
65
|
+
name: CopyResolution;
|
|
66
|
+
tagline: CopyResolution;
|
|
67
|
+
};
|
|
68
|
+
issues: SiteIdentityIssue[];
|
|
69
|
+
}
|
|
70
|
+
/** `CopyResolveOptions` plus the requested locale, which is a ref field for the underlying resolver. */
|
|
71
|
+
export type SiteIdentityOptions = CopyResolveOptions & {
|
|
72
|
+
locale?: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Resolves the site's name and tagline from `registry`, under
|
|
76
|
+
* `"site.name"` and `"site.tagline"`. Both are attempted on every call and
|
|
77
|
+
* every issue is reported, tagged with its `field`; `identity` and
|
|
78
|
+
* `resolutions` are returned only when both resolved.
|
|
79
|
+
*
|
|
80
|
+
* `options` are `resolveCopyRef`'s (`target`, `acceptDelegateInProduction`,
|
|
81
|
+
* `now`) plus an optional `locale`, which is forwarded as the ref's locale
|
|
82
|
+
* rather than as an option. Malformed options (including a blank or
|
|
83
|
+
* non-string `locale`) produce an `"invalid-options"` issue per field. Pure
|
|
84
|
+
* apart from the clock read that `now` defaults to; the registry is not
|
|
85
|
+
* modified and no input makes this throw.
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveSiteIdentity(registry: CopyRegistry | unknown, options?: SiteIdentityOptions | unknown): SiteIdentityResolution;
|
|
88
|
+
//# sourceMappingURL=site-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site-identity.d.ts","sourceRoot":"","sources":["../src/site-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACjG,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D,4CAA4C;AAC5C,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C,+CAA+C;AAC/C,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AAEnD,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,wCAAqD,CAAC;AAEzF,yDAAyD;AACzD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,GAAG,qBAAqB,GAAG,2BAA2B,CAAC;AAEnH,+EAA+E;AAC/E,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC;IACzE,MAAM,EAAE,uBAAuB,CAAC;IAChC,KAAK,EAAE,iBAAiB,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,OAAO,EAAE,cAAc,CAAA;KAAE,CAAC;IAChE,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,wGAAwG;AACxG,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAc3E;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,YAAY,GAAG,OAAO,EAChC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,GACtC,sBAAsB,CAmBxB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The site-identity copy kind: a site's name and tagline, resolved from a
|
|
3
|
+
* `CopyRegistry` under two reserved entry ids.
|
|
4
|
+
*
|
|
5
|
+
* A page-metadata consumer needs exactly two short strings — what the site
|
|
6
|
+
* is called and one line about it — and needs them to carry the same
|
|
7
|
+
* approval evidence as any other rendered copy. This module does not add a
|
|
8
|
+
* second approval path for them. It asks `resolveCopyRef` for
|
|
9
|
+
* `"site.name"` and `"site.tagline"`, so whatever that resolver refuses
|
|
10
|
+
* (a draft entry, an approval record that no longer matches its text, an
|
|
11
|
+
* expired delegate approval, a delegate approval on `"production"` without
|
|
12
|
+
* the caller's opt-in, a locale mismatch, an unknown id, an invalid
|
|
13
|
+
* registry or options object) is refused here for the same reason.
|
|
14
|
+
*
|
|
15
|
+
* On top of that resolver this module adds two refusals of its own,
|
|
16
|
+
* because a name and a tagline are literal text rather than templates: an
|
|
17
|
+
* entry that declares placeholders (or whose text the resolver would
|
|
18
|
+
* rewrite), and a resolved text that is blank after trimming.
|
|
19
|
+
*
|
|
20
|
+
* The result is all-or-nothing. Both fields are always attempted so a
|
|
21
|
+
* caller sees every problem at once, but `identity` and `resolutions` are
|
|
22
|
+
* present only when both fields resolved — there is no partial identity.
|
|
23
|
+
* Nothing here throws for any input; malformed input yields a result with
|
|
24
|
+
* `complete: false` and an issue. Nothing here reads a brand-facts record
|
|
25
|
+
* or consumes the result; wiring it into a page-metadata builder is a
|
|
26
|
+
* separate change.
|
|
27
|
+
*
|
|
28
|
+
* No real copy ships here. The ids are reserved names; the words are the
|
|
29
|
+
* consumer's own.
|
|
30
|
+
*/
|
|
31
|
+
import { prepareOptions, resolveField } from "./field-options.js";
|
|
32
|
+
/** Reserved copy id for the site's name. */
|
|
33
|
+
export const SITE_NAME_COPY_ID = "site.name";
|
|
34
|
+
/** Reserved copy id for the site's tagline. */
|
|
35
|
+
export const SITE_TAGLINE_COPY_ID = "site.tagline";
|
|
36
|
+
/** Both reserved site-identity copy ids, name first. */
|
|
37
|
+
export const SITE_IDENTITY_COPY_IDS = [SITE_NAME_COPY_ID, SITE_TAGLINE_COPY_ID];
|
|
38
|
+
const FIELDS = [
|
|
39
|
+
{ field: "name", id: SITE_NAME_COPY_ID },
|
|
40
|
+
{ field: "tagline", id: SITE_TAGLINE_COPY_ID },
|
|
41
|
+
];
|
|
42
|
+
const LABELS = {
|
|
43
|
+
optionsSubject: "Site identity",
|
|
44
|
+
entrySubject: (id) => `Site identity "${id}"`,
|
|
45
|
+
placeholderReason: "site-identity-placeholder",
|
|
46
|
+
blankReason: "site-identity-blank",
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Resolves the site's name and tagline from `registry`, under
|
|
50
|
+
* `"site.name"` and `"site.tagline"`. Both are attempted on every call and
|
|
51
|
+
* every issue is reported, tagged with its `field`; `identity` and
|
|
52
|
+
* `resolutions` are returned only when both resolved.
|
|
53
|
+
*
|
|
54
|
+
* `options` are `resolveCopyRef`'s (`target`, `acceptDelegateInProduction`,
|
|
55
|
+
* `now`) plus an optional `locale`, which is forwarded as the ref's locale
|
|
56
|
+
* rather than as an option. Malformed options (including a blank or
|
|
57
|
+
* non-string `locale`) produce an `"invalid-options"` issue per field. Pure
|
|
58
|
+
* apart from the clock read that `now` defaults to; the registry is not
|
|
59
|
+
* modified and no input makes this throw.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveSiteIdentity(registry, options) {
|
|
62
|
+
const prepared = prepareOptions(options);
|
|
63
|
+
const issues = [];
|
|
64
|
+
const resolved = {};
|
|
65
|
+
for (const { field, id } of FIELDS) {
|
|
66
|
+
const outcome = resolveField(registry, field, id, prepared, LABELS);
|
|
67
|
+
issues.push(...outcome.issues);
|
|
68
|
+
if (outcome.resolution)
|
|
69
|
+
resolved[field] = outcome.resolution;
|
|
70
|
+
}
|
|
71
|
+
const name = resolved.name;
|
|
72
|
+
const tagline = resolved.tagline;
|
|
73
|
+
if (issues.length > 0 || !name || !tagline)
|
|
74
|
+
return { complete: false, issues };
|
|
75
|
+
return {
|
|
76
|
+
complete: true,
|
|
77
|
+
identity: { name: name.text, tagline: tagline.text },
|
|
78
|
+
resolutions: { name, tagline },
|
|
79
|
+
issues: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=site-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site-identity.js","sourceRoot":"","sources":["../src/site-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKlE,4CAA4C;AAC5C,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE7C,+CAA+C;AAC/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAEnD,wDAAwD;AACxD,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,iBAAiB,EAAE,oBAAoB,CAAU,CAAC;AAkCzF,MAAM,MAAM,GAAwD;IAClE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,iBAAiB,EAAE;IACxC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,oBAAoB,EAAE;CAC/C,CAAC;AAEF,MAAM,MAAM,GAAqE;IAC/E,cAAc,EAAE,eAAe;IAC/B,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,kBAAkB,EAAE,GAAG;IAC7C,iBAAiB,EAAE,2BAA2B;IAC9C,WAAW,EAAE,qBAAqB;CACnC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgC,EAChC,OAAuC;IAEvC,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,MAAM,GAAwB,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAuD,EAAE,CAAC;IACxE,KAAK,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,MAAM,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,OAAO,CAAC,UAAU;YAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IAC/D,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;IACjC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC/E,OAAO;QACL,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE;QACpD,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;QAC9B,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Treatment-level word budgets for registry entries — display headings,
|
|
3
|
+
* eyebrows, button labels, and other short treatments that are not body
|
|
4
|
+
* measure. Pure gate: takes an already-validated `CopyRegistry`, never I/O.
|
|
5
|
+
*/
|
|
6
|
+
import type { CopyEntryId, CopyRegistry } from "./types.js";
|
|
7
|
+
/** Known slot treatments with a default maximum word count when the entry omits `maxWords`. */
|
|
8
|
+
export declare const DEFAULT_TREATMENT_WORD_BUDGETS: Readonly<Record<string, number>>;
|
|
9
|
+
export type TreatmentWordBudgetRule = "word-budget-exceeded" | "unknown-treatment";
|
|
10
|
+
export interface TreatmentWordBudgetFinding {
|
|
11
|
+
rule: TreatmentWordBudgetRule;
|
|
12
|
+
severity: "error";
|
|
13
|
+
entryId: CopyEntryId;
|
|
14
|
+
treatment: string;
|
|
15
|
+
maxWords: number;
|
|
16
|
+
actualWords: number;
|
|
17
|
+
message: string;
|
|
18
|
+
}
|
|
19
|
+
export interface TreatmentWordBudgetResult {
|
|
20
|
+
entriesChecked: number;
|
|
21
|
+
findings: TreatmentWordBudgetFinding[];
|
|
22
|
+
}
|
|
23
|
+
/** Counts words in resolved copy text (whitespace-separated tokens). */
|
|
24
|
+
export declare function countCopyWords(text: string): number;
|
|
25
|
+
/**
|
|
26
|
+
* Fails when an approved entry declares a `treatment` (or `maxWords`) and
|
|
27
|
+
* its `text` exceeds the applicable budget. Draft and retired entries are
|
|
28
|
+
* skipped — only copy that can resolve at render is measured.
|
|
29
|
+
*/
|
|
30
|
+
export declare function checkTreatmentWordBudgets(registry: CopyRegistry): TreatmentWordBudgetResult;
|
|
31
|
+
//# sourceMappingURL=treatment-word-budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treatment-word-budget.d.ts","sourceRoot":"","sources":["../src/treatment-word-budget.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAqB,MAAM,YAAY,CAAC;AAE/E,+FAA+F;AAC/F,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAI3E,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,GAAG,mBAAmB,CAAC;AAEnF,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,0BAA0B,EAAE,CAAC;CACxC;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAInD;AAiBD;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,YAAY,GAAG,yBAAyB,CAwC3F"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Treatment-level word budgets for registry entries — display headings,
|
|
3
|
+
* eyebrows, button labels, and other short treatments that are not body
|
|
4
|
+
* measure. Pure gate: takes an already-validated `CopyRegistry`, never I/O.
|
|
5
|
+
*/
|
|
6
|
+
/** Known slot treatments with a default maximum word count when the entry omits `maxWords`. */
|
|
7
|
+
export const DEFAULT_TREATMENT_WORD_BUDGETS = {
|
|
8
|
+
"display-heading": 12,
|
|
9
|
+
eyebrow: 8,
|
|
10
|
+
button: 6,
|
|
11
|
+
};
|
|
12
|
+
/** Counts words in resolved copy text (whitespace-separated tokens). */
|
|
13
|
+
export function countCopyWords(text) {
|
|
14
|
+
const trimmed = text.trim();
|
|
15
|
+
if (trimmed.length === 0)
|
|
16
|
+
return 0;
|
|
17
|
+
return trimmed.split(/\s+/u).length;
|
|
18
|
+
}
|
|
19
|
+
function budgetForEntry(entry) {
|
|
20
|
+
const treatment = entry.treatment;
|
|
21
|
+
if (typeof treatment !== "string" || treatment.trim().length === 0)
|
|
22
|
+
return undefined;
|
|
23
|
+
const normalized = treatment.trim();
|
|
24
|
+
if (entry.maxWords !== undefined) {
|
|
25
|
+
if (typeof entry.maxWords !== "number" || !Number.isFinite(entry.maxWords) || entry.maxWords < 1) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return { treatment: normalized, maxWords: Math.floor(entry.maxWords) };
|
|
29
|
+
}
|
|
30
|
+
const defaultMax = DEFAULT_TREATMENT_WORD_BUDGETS[normalized];
|
|
31
|
+
if (defaultMax === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
return { treatment: normalized, maxWords: defaultMax };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Fails when an approved entry declares a `treatment` (or `maxWords`) and
|
|
37
|
+
* its `text` exceeds the applicable budget. Draft and retired entries are
|
|
38
|
+
* skipped — only copy that can resolve at render is measured.
|
|
39
|
+
*/
|
|
40
|
+
export function checkTreatmentWordBudgets(registry) {
|
|
41
|
+
const findings = [];
|
|
42
|
+
let entriesChecked = 0;
|
|
43
|
+
for (const entry of registry.entries) {
|
|
44
|
+
if (entry.status !== "approved")
|
|
45
|
+
continue;
|
|
46
|
+
const budget = budgetForEntry(entry);
|
|
47
|
+
if (!budget) {
|
|
48
|
+
if (typeof entry.treatment === "string" && entry.treatment.trim().length > 0) {
|
|
49
|
+
const normalized = entry.treatment.trim();
|
|
50
|
+
if (entry.maxWords === undefined && DEFAULT_TREATMENT_WORD_BUDGETS[normalized] === undefined) {
|
|
51
|
+
findings.push({
|
|
52
|
+
rule: "unknown-treatment",
|
|
53
|
+
severity: "error",
|
|
54
|
+
entryId: entry.id,
|
|
55
|
+
treatment: normalized,
|
|
56
|
+
maxWords: 0,
|
|
57
|
+
actualWords: countCopyWords(entry.text),
|
|
58
|
+
message: `Entry "${entry.id}" declares treatment "${normalized}" with no maxWords and no built-in default — add maxWords or use a known treatment (${Object.keys(DEFAULT_TREATMENT_WORD_BUDGETS).join(", ")}).`,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
entriesChecked++;
|
|
65
|
+
const actualWords = countCopyWords(entry.text);
|
|
66
|
+
if (actualWords > budget.maxWords) {
|
|
67
|
+
findings.push({
|
|
68
|
+
rule: "word-budget-exceeded",
|
|
69
|
+
severity: "error",
|
|
70
|
+
entryId: entry.id,
|
|
71
|
+
treatment: budget.treatment,
|
|
72
|
+
maxWords: budget.maxWords,
|
|
73
|
+
actualWords,
|
|
74
|
+
message: `Entry "${entry.id}" (${budget.treatment}) has ${actualWords} word(s) but the budget is ${budget.maxWords}.`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { entriesChecked, findings };
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=treatment-word-budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treatment-word-budget.js","sourceRoot":"","sources":["../src/treatment-word-budget.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -28,13 +28,15 @@
|
|
|
28
28
|
* This file ships no example content of anyone's real copy. Every field
|
|
29
29
|
* here is either required-and-generic or a structural placeholder —
|
|
30
30
|
* filling in an actual product's actual sentences is a consumer's job.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
31
|
+
* The one exemption is the shipped US English front-door defaults
|
|
32
|
+
* (`front-door.ts`, `FRONT_DOOR_COPY_EN`, and the README's "Front-door
|
|
33
|
+
* copy" section): a closed, reserved set of ids, owned by this package, whose
|
|
34
|
+
* words ship as data so every sign-in surface need not carry its own. Outside
|
|
35
|
+
* that set this package is to `@clossys/writer/voice` what `@example/ui` is
|
|
36
|
+
* to `@example/ui/tokens` — a vocabulary layer over a contract layer, never a
|
|
37
|
+
* source of real words. If a doc comment, a test fixture, or a README example
|
|
38
|
+
* outside the front-door set ever reads like something a product would
|
|
39
|
+
* actually show a user, that is a bug in this package, not a feature of it.
|
|
38
40
|
*/
|
|
39
41
|
/**
|
|
40
42
|
* A stable address for one `CopyEntry`, unique within its `CopyRecord`.
|
|
@@ -147,6 +149,17 @@ export interface CopyEntry {
|
|
|
147
149
|
* same seam, one layer over).
|
|
148
150
|
*/
|
|
149
151
|
factRef?: string;
|
|
152
|
+
/**
|
|
153
|
+
* Named slot treatment for word-budget governance — e.g. `display-heading`,
|
|
154
|
+
* `eyebrow`, `button`. When set on an approved registry entry, `writer-check`
|
|
155
|
+
* applies `maxWords` or the built-in default for that treatment.
|
|
156
|
+
*/
|
|
157
|
+
treatment?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Maximum word count for this entry's `text` when `treatment` is set.
|
|
160
|
+
* Overrides the built-in default table when present.
|
|
161
|
+
*/
|
|
162
|
+
maxWords?: number;
|
|
150
163
|
}
|
|
151
164
|
/**
|
|
152
165
|
* Content-derived provenance for one target-locale translation. Present only
|
|
@@ -190,6 +203,40 @@ export interface CopyTranslationProvenance {
|
|
|
190
203
|
/** Opaque reviewer identifier, mirroring `translatedBy` — never a personal name. */
|
|
191
204
|
reviewedBy?: string;
|
|
192
205
|
}
|
|
206
|
+
/** Who recorded an approval: the copy owner, or a delegate acting for them. */
|
|
207
|
+
export type CopyApprover = "owner" | "delegate";
|
|
208
|
+
/**
|
|
209
|
+
* The delegate an approval was recorded by, and the entry-id namespaces they
|
|
210
|
+
* may approve. `id` is an opaque identifier, never a personal name. Each
|
|
211
|
+
* `scope` item is a dot-separated namespace with no wildcard; an entry is in
|
|
212
|
+
* scope when its id equals an item or starts with `item + "."`.
|
|
213
|
+
*/
|
|
214
|
+
export interface CopyDelegateScope {
|
|
215
|
+
id: string;
|
|
216
|
+
scope: string[];
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* The recorded approval of one registry entry, written by
|
|
220
|
+
* `writer-check approve` rather than by hand. `textFingerprint` pins the
|
|
221
|
+
* approval to the exact text that was approved: once `text` changes, the
|
|
222
|
+
* record no longer matches and the resolver refuses the entry
|
|
223
|
+
* (`approval-stale`) until it is approved again.
|
|
224
|
+
*/
|
|
225
|
+
export interface CopyApproval {
|
|
226
|
+
approvedBy: CopyApprover;
|
|
227
|
+
/** ISO 8601 UTC timestamp of the approval. */
|
|
228
|
+
approvedAt: string;
|
|
229
|
+
/** `computeCopyFingerprint(entry.text)` at the moment of approval. */
|
|
230
|
+
textFingerprint: string;
|
|
231
|
+
/** The algorithm `textFingerprint` was computed with — `COPY_FINGERPRINT_ALGORITHM`. */
|
|
232
|
+
fingerprintAlgorithm: string;
|
|
233
|
+
/** Required when `approvedBy` is `"delegate"`; forbidden for `"owner"`. */
|
|
234
|
+
delegate?: CopyDelegateScope;
|
|
235
|
+
/** Required when `approvedBy` is `"delegate"`; forbidden for `"owner"`. */
|
|
236
|
+
pendingOwnerReview?: boolean;
|
|
237
|
+
/** Delegate records only: ISO 8601 UTC expiry, strictly after `approvedAt`. */
|
|
238
|
+
expiresAt?: string;
|
|
239
|
+
}
|
|
193
240
|
/** A `CopyEntry` that is eligible to participate in a rendered registry. */
|
|
194
241
|
export interface CopyRegistryEntry extends CopyEntry {
|
|
195
242
|
status: CopyEntryStatus;
|
|
@@ -206,6 +253,12 @@ export interface CopyRegistryEntry extends CopyEntry {
|
|
|
206
253
|
* never collapsed into one signal.
|
|
207
254
|
*/
|
|
208
255
|
translation?: CopyTranslationProvenance;
|
|
256
|
+
/**
|
|
257
|
+
* The approval record, present only on an `approved` entry that has one.
|
|
258
|
+
* Optional: an `approved` entry without a record keeps resolving exactly
|
|
259
|
+
* as it did before this field existed. See `CopyApproval`.
|
|
260
|
+
*/
|
|
261
|
+
approval?: CopyApproval;
|
|
209
262
|
}
|
|
210
263
|
/**
|
|
211
264
|
* One consumer's complete, registered set of copy entries. This is the
|
|
@@ -229,6 +282,20 @@ export interface CopyRegistry extends CopyRecord {
|
|
|
229
282
|
source: CopySource;
|
|
230
283
|
entries: CopyRegistryEntry[];
|
|
231
284
|
}
|
|
285
|
+
/** The approval facts a resolution carries (`CopyResolution.approval`). */
|
|
286
|
+
export type CopyResolutionApproval = {
|
|
287
|
+
approvedBy: "owner";
|
|
288
|
+
pendingOwnerReview: false;
|
|
289
|
+
} | {
|
|
290
|
+
approvedBy: "delegate";
|
|
291
|
+
pendingOwnerReview: boolean;
|
|
292
|
+
/**
|
|
293
|
+
* Present only when this delegate-approved entry resolved on "production"
|
|
294
|
+
* because the `approvalPlan` authorized it: that plan's canonical digest.
|
|
295
|
+
* Absent when `acceptDelegateInProduction` authorized it, and on "preview".
|
|
296
|
+
*/
|
|
297
|
+
authorizingPlanDigest?: string;
|
|
298
|
+
};
|
|
232
299
|
/** A successful, fully traced resolution of one copy reference. */
|
|
233
300
|
export interface CopyResolution {
|
|
234
301
|
ref: CopyRef;
|
|
@@ -238,6 +305,8 @@ export interface CopyResolution {
|
|
|
238
305
|
locale: CopyLocale;
|
|
239
306
|
source: CopySource;
|
|
240
307
|
entryId: CopyEntryId;
|
|
308
|
+
/** Present only when the resolved entry carries an approval record. */
|
|
309
|
+
approval?: CopyResolutionApproval;
|
|
241
310
|
}
|
|
242
311
|
/** Resolver shape for callers that need rendered audience text. */
|
|
243
312
|
export type CopyResolver = (ref: CopyRef) => CopyResolution | undefined;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -28,13 +28,15 @@
|
|
|
28
28
|
* This file ships no example content of anyone's real copy. Every field
|
|
29
29
|
* here is either required-and-generic or a structural placeholder —
|
|
30
30
|
* filling in an actual product's actual sentences is a consumer's job.
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
31
|
+
* The one exemption is the shipped US English front-door defaults
|
|
32
|
+
* (`front-door.ts`, `FRONT_DOOR_COPY_EN`, and the README's "Front-door
|
|
33
|
+
* copy" section): a closed, reserved set of ids, owned by this package, whose
|
|
34
|
+
* words ship as data so every sign-in surface need not carry its own. Outside
|
|
35
|
+
* that set this package is to `@clossys/writer/voice` what `@example/ui` is
|
|
36
|
+
* to `@example/ui/tokens` — a vocabulary layer over a contract layer, never a
|
|
37
|
+
* source of real words. If a doc comment, a test fixture, or a README example
|
|
38
|
+
* outside the front-door set ever reads like something a product would
|
|
39
|
+
* actually show a user, that is a bug in this package, not a feature of it.
|
|
38
40
|
*/
|
|
39
41
|
export {};
|
|
40
42
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG"}
|
package/fit-signals.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"role": "@clossys/writer",
|
|
4
|
+
"signals": [
|
|
5
|
+
{
|
|
6
|
+
"id": "ships-audience-facing-copy",
|
|
7
|
+
"prompt": "The repository ships text a person outside the team reads: interface strings, page copy, or other audience-facing prose in its source.",
|
|
8
|
+
"evidenceKind": "repository-structure"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|