create-cmp-cli 0.23.0 → 0.25.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/bin/create-cmp.mjs +33 -3
- package/package.json +10 -4
- package/packages/harness/package.json +18 -8
- package/packages/harness/src/approve.mjs +46 -18
- package/packages/harness/src/console/console-data.mjs +117 -0
- package/packages/harness/src/console/console-evidence.mjs +122 -0
- package/packages/harness/src/console/console-overview.mjs +642 -0
- package/packages/harness/src/console/console-shell.mjs +1139 -0
- package/packages/harness/src/console/console-tabs.mjs +2828 -0
- package/packages/harness/src/console/contrast.mjs +74 -0
- package/packages/harness/src/console/preview-service.mjs +1384 -0
- package/packages/harness/src/framework-check.mjs +747 -0
- package/packages/harness/src/lib/a11y.mjs +1 -1
- package/packages/harness/src/lib/affected-tests.mjs +99 -44
- package/packages/harness/src/lib/agent-hold.mjs +234 -0
- package/packages/harness/src/lib/approvals.mjs +177 -350
- package/packages/harness/src/lib/audit-cadence.mjs +1 -1
- package/packages/harness/src/lib/comments.mjs +18 -4
- package/packages/harness/src/lib/determinism.mjs +275 -14
- package/packages/harness/src/lib/evidence-badge.mjs +38 -6
- package/packages/harness/src/lib/evidence-ladder.mjs +202 -0
- package/packages/harness/src/lib/evidence-level.mjs +144 -59
- package/packages/harness/src/lib/feature-brief.mjs +53 -16
- package/packages/harness/src/lib/flight-recorder.mjs +72 -8
- package/packages/harness/src/lib/framework-check.mjs +778 -0
- package/packages/harness/src/lib/harness-lock.mjs +87 -19
- package/packages/harness/src/lib/harness-manifest.mjs +208 -0
- package/packages/harness/src/lib/harness-region.mjs +106 -2
- package/packages/harness/src/lib/harness-source.mjs +142 -0
- package/packages/harness/src/lib/inputs-hash.mjs +180 -22
- package/packages/harness/src/lib/lane-markers.mjs +78 -0
- package/packages/harness/src/lib/lane-narrator.mjs +4 -2
- package/packages/harness/src/lib/lane-runner.mjs +72 -6
- package/packages/harness/src/lib/plan.mjs +44 -11
- package/packages/harness/src/lib/plant-calibration.mjs +135 -0
- package/packages/harness/src/lib/profile-loader.mjs +323 -0
- package/packages/harness/src/lib/profiles/cmp/affected.mjs +70 -0
- package/packages/harness/src/lib/profiles/cmp/android-checks.mjs +56 -0
- package/packages/harness/src/lib/profiles/cmp/artifacts.mjs +381 -0
- package/packages/harness/src/lib/{component-stories.mjs → profiles/cmp/component-stories.mjs} +5 -2
- package/packages/harness/src/lib/profiles/cmp/console-copy.mjs +29 -0
- package/packages/harness/src/lib/profiles/cmp/declarations.mjs +181 -0
- package/{template/qa/lib → packages/harness/src/lib/profiles/cmp}/e2e-coverage.mjs +13 -3
- package/packages/harness/src/lib/profiles/cmp/index.mjs +47 -0
- package/packages/harness/src/lib/profiles/cmp/ladder.mjs +67 -0
- package/packages/harness/src/lib/profiles/cmp/maestro.mjs +113 -0
- package/packages/harness/src/lib/profiles/cmp/plants.mjs +95 -0
- package/{template/qa/lib → packages/harness/src/lib/profiles/cmp}/reachability.mjs +1 -1
- package/packages/harness/src/lib/{steps-cmp.mjs → profiles/cmp/steps-cmp.mjs} +230 -28
- package/packages/harness/src/lib/receipt-validate.mjs +84 -16
- package/packages/harness/src/lib/spec-coverage.mjs +179 -92
- package/packages/harness/src/lib/spec-model.mjs +262 -0
- package/packages/harness/src/lib/step-cache.mjs +11 -2
- package/packages/harness/src/lib/step-outcomes.mjs +84 -151
- package/packages/harness/src/lib/walk.mjs +1 -1
- package/packages/harness/src/plan.mjs +30 -1
- package/packages/harness/src/preview-gallery.mjs +1 -1
- package/packages/harness/src/receipt-check.mjs +95 -26
- package/packages/harness/src/record-audit.mjs +1 -1
- package/packages/harness/src/scaffold-feature.mjs +10 -2
- package/packages/harness/src/verify.mjs +222 -142
- package/packages/harness/src/watch.mjs +146 -33
- package/packages/receipts/package.json +1 -1
- package/packages/receipts/src/index.mjs +2 -2
- package/packages/receipts/src/inputs-hash.mjs +180 -22
- package/packages/receipts/src/receipt-validate.mjs +84 -16
- package/src/commands/attach.mjs +128 -4
- package/src/commands/harden.mjs +7 -1
- package/src/commands/upgrade.mjs +7 -0
- package/src/lib/minimal.mjs +23 -1
- package/src/scaffold.mjs +8 -0
- package/template/.claude/settings.json +2 -2
- package/template/.claude/skills/add-feature/SKILL.md +7 -3
- package/template/.claude/skills/add-repository/SKILL.md +2 -2
- package/template/.claude/skills/add-screen/SKILL.md +8 -4
- package/template/.githooks/pre-push +9 -0
- package/template/CLAUDE.md +55 -186
- package/template/docs/TESTING.md +1 -1
- package/template/gitignore +4 -0
- package/template/qa/approve.mjs +46 -18
- package/template/qa/comments.json +1 -1
- package/template/qa/evidence/schema.json +258 -34
- package/template/qa/framework-check.mjs +747 -0
- package/template/qa/harness-manifest.json +10 -0
- package/template/qa/lib/a11y.mjs +1 -1
- package/template/qa/lib/affected-tests.mjs +99 -44
- package/template/qa/lib/agent-hold.mjs +234 -0
- package/template/qa/lib/approvals.mjs +177 -350
- package/template/qa/lib/audit-cadence.mjs +1 -1
- package/template/qa/lib/comments.mjs +18 -4
- package/template/qa/lib/determinism.mjs +275 -14
- package/template/qa/lib/evidence-badge.mjs +38 -6
- package/template/qa/lib/evidence-ladder.mjs +202 -0
- package/template/qa/lib/evidence-level.mjs +144 -59
- package/template/qa/lib/feature-brief.mjs +53 -16
- package/template/qa/lib/flight-recorder.mjs +72 -8
- package/template/qa/lib/framework-check.mjs +778 -0
- package/template/qa/lib/harness-lock.mjs +87 -19
- package/template/qa/lib/harness-manifest.mjs +208 -0
- package/template/qa/lib/harness-region.mjs +106 -2
- package/template/qa/lib/harness-source.mjs +142 -0
- package/template/qa/lib/inputs-hash.mjs +180 -22
- package/template/qa/lib/lane-markers.mjs +78 -0
- package/template/qa/lib/lane-narrator.mjs +4 -2
- package/template/qa/lib/lane-runner.mjs +72 -6
- package/template/qa/lib/plan.mjs +44 -11
- package/template/qa/lib/plant-calibration.mjs +135 -0
- package/template/qa/lib/profile-loader.mjs +323 -0
- package/template/qa/lib/profiles/cmp/affected.mjs +70 -0
- package/template/qa/lib/profiles/cmp/android-checks.mjs +56 -0
- package/template/qa/lib/profiles/cmp/artifacts.mjs +381 -0
- package/template/qa/lib/{component-stories.mjs → profiles/cmp/component-stories.mjs} +5 -2
- package/template/qa/lib/profiles/cmp/console-copy.mjs +29 -0
- package/template/qa/lib/profiles/cmp/declarations.mjs +181 -0
- package/{packages/harness/src/lib → template/qa/lib/profiles/cmp}/e2e-coverage.mjs +13 -3
- package/template/qa/lib/profiles/cmp/index.mjs +47 -0
- package/template/qa/lib/profiles/cmp/ladder.mjs +67 -0
- package/template/qa/lib/profiles/cmp/maestro.mjs +113 -0
- package/template/qa/lib/profiles/cmp/plants.mjs +95 -0
- package/{packages/harness/src/lib → template/qa/lib/profiles/cmp}/reachability.mjs +1 -1
- package/template/qa/lib/{steps-cmp.mjs → profiles/cmp/steps-cmp.mjs} +230 -28
- package/template/qa/lib/receipt-validate.mjs +84 -16
- package/template/qa/lib/spec-coverage.mjs +179 -92
- package/template/qa/lib/spec-model.mjs +262 -0
- package/template/qa/lib/step-cache.mjs +11 -2
- package/template/qa/lib/step-outcomes.mjs +84 -151
- package/template/qa/lib/walk.mjs +1 -1
- package/template/qa/plan.mjs +30 -1
- package/template/qa/preview-gallery.mjs +1 -1
- package/template/qa/receipt-check.mjs +95 -26
- package/template/qa/record-audit.mjs +1 -1
- package/template/qa/scaffold-feature.mjs +10 -2
- package/template/qa/verified-surface.json +17 -0
- package/template/qa/verify.mjs +222 -142
- package/template/qa/watch.mjs +146 -33
- /package/packages/harness/src/lib/{device-lease.mjs → profiles/cmp/device-lease.mjs} +0 -0
- /package/packages/harness/src/lib/{device-provider.mjs → profiles/cmp/device-provider.mjs} +0 -0
- /package/packages/harness/src/lib/{render.mjs → profiles/cmp/render.mjs} +0 -0
- /package/packages/harness/src/lib/{token-drift.mjs → profiles/cmp/token-drift.mjs} +0 -0
- /package/packages/harness/src/lib/{tree.mjs → profiles/cmp/tree.mjs} +0 -0
- /package/template/qa/lib/{device-lease.mjs → profiles/cmp/device-lease.mjs} +0 -0
- /package/template/qa/lib/{device-provider.mjs → profiles/cmp/device-provider.mjs} +0 -0
- /package/template/qa/lib/{render.mjs → profiles/cmp/render.mjs} +0 -0
- /package/template/qa/lib/{token-drift.mjs → profiles/cmp/token-drift.mjs} +0 -0
- /package/template/qa/lib/{tree.mjs → profiles/cmp/tree.mjs} +0 -0
|
@@ -21,6 +21,11 @@ import { fileURLToPath } from "node:url";
|
|
|
21
21
|
|
|
22
22
|
import { computeInputsHash } from "./lib/inputs-hash.mjs";
|
|
23
23
|
import { evaluateReceipt, readReceipt } from "./lib/receipt-validate.mjs";
|
|
24
|
+
import { readHold, assessHold, describeHold, holdExplains } from "./lib/agent-hold.mjs";
|
|
25
|
+
import { LANE_MARKER_STALE_MS, laneMarkerPath } from "./lib/lane-markers.mjs";
|
|
26
|
+
import { resolveHarnessManifest } from "./lib/harness-manifest.mjs";
|
|
27
|
+
import { loadProfileSync } from "./lib/profile-loader.mjs";
|
|
28
|
+
import { evidenceLadderFor } from "./lib/evidence-ladder.mjs";
|
|
24
29
|
|
|
25
30
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
26
31
|
|
|
@@ -29,9 +34,8 @@ const asHook = args.includes("--hook");
|
|
|
29
34
|
const asJson = args.includes("--json");
|
|
30
35
|
|
|
31
36
|
// The lane's own in-flight marker (verify.mjs stamps it, rewriting it at each
|
|
32
|
-
// step start with the step name and index)
|
|
33
|
-
|
|
34
|
-
const LANE_MARKER_STALE_MS = 30 * 60 * 1000;
|
|
37
|
+
// step start with the step name and index) — qa/lib/lane-markers.mjs, one
|
|
38
|
+
// path and one bound for every reader.
|
|
35
39
|
|
|
36
40
|
/**
|
|
37
41
|
* The full check running RIGHT NOW, or null. The gate must still refuse — a
|
|
@@ -43,7 +47,7 @@ const LANE_MARKER_STALE_MS = 30 * 60 * 1000;
|
|
|
43
47
|
*/
|
|
44
48
|
function laneInFlight() {
|
|
45
49
|
try {
|
|
46
|
-
const p =
|
|
50
|
+
const p = laneMarkerPath(ROOT);
|
|
47
51
|
const st = fs.statSync(p);
|
|
48
52
|
if (Date.now() - st.mtimeMs >= LANE_MARKER_STALE_MS) return null;
|
|
49
53
|
// Content is a bonus, never a requirement: legacy markers hold "pid iso".
|
|
@@ -72,7 +76,7 @@ function readStdinJson() {
|
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
// The predicate itself lives in qa/lib/receipt-validate.mjs (vendored from the
|
|
75
|
-
//
|
|
79
|
+
// prooflane-receipts package — one definition everywhere a receipt is judged); this
|
|
76
80
|
// CLI only reads the receipt and frames the exit codes.
|
|
77
81
|
function evaluate() {
|
|
78
82
|
const receipt = readReceipt(ROOT);
|
|
@@ -108,28 +112,61 @@ function evaluate() {
|
|
|
108
112
|
profile: receipt.profile,
|
|
109
113
|
};
|
|
110
114
|
}
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
115
|
+
// A step that COULD have run and did not is a gap a human can close, and a
|
|
116
|
+
// change is not done while it stands (2026-09-03). The lane boots its own
|
|
117
|
+
// device, so an environment SKIP — no device, a tool not installed, a lease
|
|
118
|
+
// held elsewhere — is never the project's honest structure; a `structure`
|
|
119
|
+
// SKIP (this project has no such tier at all) is, and is allowed.
|
|
120
|
+
//
|
|
121
|
+
// Stage 0 PR 6c: this used to test `["e2eSmoke", "androidChecks"]` by name
|
|
122
|
+
// and match Android reason text. On any other stack it therefore checked
|
|
123
|
+
// nothing — the one gate that refuses "done" over a tier that never ran,
|
|
124
|
+
// silently inert. `skipKind` is the stack-free signal and every current
|
|
125
|
+
// receipt carries it, so the rule is now: ANY step that skipped for an
|
|
126
|
+
// environmental reason blocks done, whatever it is called.
|
|
127
|
+
//
|
|
128
|
+
// Receipts predating `skipKind` (0.19.0 and earlier) are still read by their
|
|
129
|
+
// reason text, and THAT list is the profile's — read from the ladder's
|
|
130
|
+
// execution tier when the profile is loadable, and simply not applied when
|
|
131
|
+
// it is not. A legacy fallback that guessed would be worse than none.
|
|
132
|
+
//
|
|
133
|
+
// THE LADDER IS RESOLVED, NOT SPELLED. This used to read `profile.ladder`
|
|
134
|
+
// directly, which is one of the two places a profile may declare its rungs;
|
|
135
|
+
// qa/verify.mjs read the other, and nothing reconciled them. It goes
|
|
136
|
+
// through qa/lib/evidence-ladder.mjs now, so this reader and the lane can
|
|
137
|
+
// never be looking at different declarations of the same thing.
|
|
138
|
+
//
|
|
139
|
+
// NO PACK IS PASSED, AND THAT IS THE POINT. Getting the pack's spelling means
|
|
140
|
+
// calling `steps(ctx)`, and this file is the Stop hook: a done-gate that
|
|
141
|
+
// starts a lane to answer a legacy-compat question is not a gate, it is a
|
|
142
|
+
// second lane. So a profile that declares its ladder ONLY on the pack gives
|
|
143
|
+
// this reader nothing and gets no legacy fallback — the same honest silence
|
|
144
|
+
// as a profile with no ladder at all, and the reason the top-level spelling
|
|
145
|
+
// is the one `harness init` seeds and the one the resolver prefers.
|
|
146
|
+
const legacyPatterns = /no Android device|maestro CLI not installed|is held by|devices attached|CMP_DEVICE=none/;
|
|
147
|
+
let legacyNames = null;
|
|
148
|
+
try {
|
|
149
|
+
const manifest = resolveHarnessManifest(ROOT);
|
|
150
|
+
if (manifest.ok) {
|
|
151
|
+
const loaded = loadProfileSync(ROOT, manifest.manifest.profile);
|
|
152
|
+
const resolved = evidenceLadderFor(loaded.ok ? loaded.profile : null);
|
|
153
|
+
const ladder = resolved.ok ? resolved.ladder : null;
|
|
154
|
+
if (ladder && Array.isArray(ladder.deviceExecution)) legacyNames = ladder.deviceExecution;
|
|
155
|
+
}
|
|
156
|
+
} catch {
|
|
157
|
+
// The Stop hook never crashes over a legacy-compat lookup.
|
|
158
|
+
}
|
|
159
|
+
const envSkipped = (Array.isArray(receipt.steps) ? receipt.steps : []).filter((s) => {
|
|
160
|
+
if (!s || s.verdict !== "SKIP") return false;
|
|
161
|
+
if (s.skipKind) return s.skipKind === "environment";
|
|
162
|
+
return Boolean(legacyNames && legacyNames.includes(s.name) && legacyPatterns.test(String(s.reason ?? "")));
|
|
163
|
+
});
|
|
127
164
|
if (envSkipped.length) {
|
|
128
165
|
return {
|
|
129
166
|
valid: false,
|
|
130
167
|
reason:
|
|
131
|
-
`
|
|
132
|
-
"
|
|
168
|
+
`a tier did not run — ${envSkipped.map((s) => `${s.name}: ${String(s.reason ?? "").split("\n")[0]}`).join("; ")}. ` +
|
|
169
|
+
"Those steps skipped for an environmental reason, not because this project lacks them; fix the cause and run `node qa/verify.mjs` again before finishing",
|
|
133
170
|
profile: receipt.profile,
|
|
134
171
|
};
|
|
135
172
|
}
|
|
@@ -151,9 +188,21 @@ function evaluate() {
|
|
|
151
188
|
// Surface the receipt's evidence rung (the ladder — qa/lib/evidence-level.mjs)
|
|
152
189
|
// alongside the verdict: the rung is the receipt's own derived field, read
|
|
153
190
|
// verbatim, never recomputed here. Older receipts without it stay valid.
|
|
191
|
+
//
|
|
192
|
+
// AND THE PACK WITH IT, ALWAYS — the two are set in the same breath because
|
|
193
|
+
// NORTH-STAR.md §6.5 requires that every surface showing a rung shows the
|
|
194
|
+
// pack, and §8.9 is why: one pack's L2 and another pack's L2 are different
|
|
195
|
+
// claims. This CLI printed the rung alone, which left every reader of the
|
|
196
|
+
// done-gate exactly where that rule says they must not be. Only the pack's
|
|
197
|
+
// ID is carried: it is the part that carries the meaning, and `pack.version`
|
|
198
|
+
// on a receipt is today the harness lock's number rather than the profile's
|
|
199
|
+
// (docs/adr/0008), so a surface that leaned on it would be repeating a
|
|
200
|
+
// borrowed fact.
|
|
154
201
|
const level = receipt.evidenceLevel;
|
|
155
202
|
if (level && typeof level === "object" && typeof level.rung === "string") {
|
|
156
203
|
result.evidenceLevel = level;
|
|
204
|
+
const id = receipt.pack && typeof receipt.pack.id === "string" ? receipt.pack.id.trim() : "";
|
|
205
|
+
result.packId = id || null;
|
|
157
206
|
}
|
|
158
207
|
return result;
|
|
159
208
|
}
|
|
@@ -175,12 +224,24 @@ if (asHook) {
|
|
|
175
224
|
// INSTRUCTION: "run the lane" is wrong advice when one is already running,
|
|
176
225
|
// and a gate that tells you to do the thing you are doing trains you to
|
|
177
226
|
// stop reading it.
|
|
227
|
+
//
|
|
228
|
+
// An agent HOLDING the tree is the same shape of correction one level out:
|
|
229
|
+
// a lane in flight explains a receipt that is about to arrive, a hold
|
|
230
|
+
// explains a tree that is mid-edit and would not compile if you ran one.
|
|
231
|
+
// Reported ~15 false alarms in one evening at payment-blueprint, every one
|
|
232
|
+
// of which should have said "wait". It only ever changes the instruction —
|
|
233
|
+
// and only for the two refusals a working agent legitimately causes
|
|
234
|
+
// (holdExplains), never for a FAIL, a forgery or a skipped device tier,
|
|
235
|
+
// where the hold is not the cause and offering it would misdirect.
|
|
178
236
|
const flight = laneInFlight();
|
|
237
|
+
const hold = holdExplains(result, readReceipt(ROOT)) ? assessHold(readHold(ROOT)) : null;
|
|
179
238
|
const act = flight
|
|
180
239
|
? `A full check is ALREADY RUNNING${flight.step ? ` (${flight.step}${flight.index && flight.total ? `, step ${flight.index} of ${flight.total}` : ""})` : ""} — ` +
|
|
181
240
|
`wait for it to finish and commit its receipt. Do NOT start a second one; two lanes fight over the same build directory.`
|
|
182
|
-
:
|
|
183
|
-
|
|
241
|
+
: hold?.held
|
|
242
|
+
? describeHold(hold)
|
|
243
|
+
: "Run `node qa/verify.mjs` (it checks every promise and writes the receipt), " +
|
|
244
|
+
"commit the receipt, or see README §Verification enforcement to bypass.";
|
|
184
245
|
process.stderr.write(
|
|
185
246
|
`■ Prove — not done: the promises are not yet checked against this tree. ${result.reason}. ${act}\n`,
|
|
186
247
|
);
|
|
@@ -189,7 +250,15 @@ if (asHook) {
|
|
|
189
250
|
process.exit(0);
|
|
190
251
|
}
|
|
191
252
|
|
|
192
|
-
|
|
253
|
+
// The rung NEVER travels alone (see evaluate() above): a rung is a claim in one
|
|
254
|
+
// pack's vocabulary, so the pack is named beside it, and a receipt that names no
|
|
255
|
+
// pack is SAID to name none rather than being rendered as if the omission did
|
|
256
|
+
// not matter. A rung whose pack is unknown is comparable to nothing, and that is
|
|
257
|
+
// a fact about the evidence, not a formatting detail to be tidied away.
|
|
258
|
+
const rungSuffix = result.evidenceLevel
|
|
259
|
+
? ` — evidence ${result.evidenceLevel.rung} · ${result.evidenceLevel.name}` +
|
|
260
|
+
(result.packId ? ` · pack ${result.packId}` : " · pack UNNAMED (this rung is comparable to nothing)")
|
|
261
|
+
: "";
|
|
193
262
|
|
|
194
263
|
if (asJson) {
|
|
195
264
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -29,7 +29,7 @@ const USAGE = `node qa/record-audit.mjs <subsystem> [--by <who-or-what>]
|
|
|
29
29
|
Appends one audit record (subsystem, HEAD sha, ISO timestamp, recorder) to
|
|
30
30
|
${AUDITS_REL_PATH}. The verify lane's release profile reports which
|
|
31
31
|
subsystems changed since their last record. Subsystems are derived from the
|
|
32
|
-
tree: the immediate package directories under the
|
|
32
|
+
tree: the immediate package directories under the platform source set
|
|
33
33
|
root ("${ROOT_SUBSYSTEM}" for files directly at the package root).
|
|
34
34
|
|
|
35
35
|
--list print the derived subsystems and their audit status
|
|
@@ -181,10 +181,18 @@ try {
|
|
|
181
181
|
} catch {
|
|
182
182
|
approvalsLib = null;
|
|
183
183
|
}
|
|
184
|
+
// The exemplar's shape and names are the cmp profile's (Stage 0 PR 5 —
|
|
185
|
+
// qa/lib/profiles/cmp/artifacts.mjs); this stamper is that profile's tool.
|
|
186
|
+
let profileLib = null;
|
|
187
|
+
try {
|
|
188
|
+
profileLib = await import("./lib/profiles/cmp/artifacts.mjs");
|
|
189
|
+
} catch {
|
|
190
|
+
profileLib = null;
|
|
191
|
+
}
|
|
184
192
|
|
|
185
193
|
function resolveSourceNames() {
|
|
186
|
-
if (
|
|
187
|
-
return
|
|
194
|
+
if (profileLib && typeof profileLib.resolveExemplarNames === "function") {
|
|
195
|
+
return profileLib.resolveExemplarNames(ROOT);
|
|
188
196
|
}
|
|
189
197
|
return { f: "home", F: "Home", F_UPPER: "HOME", E: "Item" };
|
|
190
198
|
}
|