lazycodex-ai 5.1.38 → 5.1.41
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/cli/index.js +229 -187
- package/dist/cli-node/index.js +229 -187
- package/package.json +1 -1
- package/packages/lsp-daemon/dist/cli.js +10 -0
- package/packages/lsp-daemon/dist/client.js +10 -0
- package/packages/lsp-daemon/dist/index.js +10 -0
- package/packages/lsp-tools-mcp/dist/cli.js +10 -0
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +10 -0
- package/packages/lsp-tools-mcp/dist/mcp.js +10 -0
- package/packages/lsp-tools-mcp/dist/tools.js +10 -0
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +24 -2
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +10 -0
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +157 -151
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +157 -151
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +5 -4
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +6 -6
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/references/perfection/README.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/accent-stripes/declarations.ts +22 -13
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/accent-stripes/findings.ts +7 -6
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/accent-stripes/lint.ts +18 -24
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/accent-stripes/markup.ts +14 -7
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/accent-stripes/selector.ts +5 -1
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/accent-stripes/tailwind.ts +32 -14
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/check-accent-stripes.ts +1 -1
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/inline-ok.tsx +1 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/neutral-and-flat.css +1 -1
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/tailwind-ok.tsx +5 -2
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/uniform-and-rings.css +2 -2
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/accent-outlines.css +4 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/accent-outlines.tsx +8 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/{negative → positive}/flat-stripe-side.tsx +3 -1
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/report-callouts.html +8 -0
- package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/square-surfaces.css +8 -0
- package/packages/omo-codex/plugin/skills/git-master/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +5 -4
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +10 -2
- package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +10 -0
- package/packages/omo-codex/plugin/skills/ulw-research/references/report-visualization.md +23 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +195 -168
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/frontend/SKILL.md +6 -6
- package/packages/shared-skills/skills/frontend/references/design/README.md +2 -2
- package/packages/shared-skills/skills/frontend/references/perfection/README.md +2 -2
- package/packages/shared-skills/skills/frontend/scripts/perfection/accent-stripes/declarations.ts +22 -13
- package/packages/shared-skills/skills/frontend/scripts/perfection/accent-stripes/findings.ts +7 -6
- package/packages/shared-skills/skills/frontend/scripts/perfection/accent-stripes/lint.ts +18 -24
- package/packages/shared-skills/skills/frontend/scripts/perfection/accent-stripes/markup.ts +14 -7
- package/packages/shared-skills/skills/frontend/scripts/perfection/accent-stripes/selector.ts +5 -1
- package/packages/shared-skills/skills/frontend/scripts/perfection/accent-stripes/tailwind.ts +32 -14
- package/packages/shared-skills/skills/frontend/scripts/perfection/check-accent-stripes.test.ts +15 -6
- package/packages/shared-skills/skills/frontend/scripts/perfection/check-accent-stripes.ts +1 -1
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/inline-ok.tsx +1 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/neutral-and-flat.css +1 -1
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/tailwind-ok.tsx +5 -2
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/negative/uniform-and-rings.css +2 -2
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/accent-outlines.css +4 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/accent-outlines.tsx +8 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/{negative → positive}/flat-stripe-side.tsx +3 -1
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/report-callouts.html +8 -0
- package/packages/shared-skills/skills/frontend/scripts/perfection/fixtures/accent-stripes/positive/square-surfaces.css +8 -0
- package/packages/shared-skills/skills/git-master/SKILL.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +5 -4
- package/packages/shared-skills/skills/ulw-research/SKILL.md +10 -2
- package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +10 -0
- package/packages/shared-skills/skills/ulw-research/references/report-visualization.md +23 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// omo-codex-install:
|
|
2
|
+
// omo-codex-install:b93c8a23ccfb735feb527d0eb908268e037e0bf2991d36923501d67a335c7f6e:6062641acd173ed604879322dfb8008ad35f96a8286ebc8dfecd7cc90bd35467
|
|
3
3
|
var __esm = (fn, res, err) => () => {
|
|
4
4
|
if (fn)
|
|
5
5
|
try {
|
|
@@ -450,6 +450,163 @@ var init_event_id = __esm(() => {
|
|
|
450
450
|
fallbackEventId = createUuidV7Generator();
|
|
451
451
|
});
|
|
452
452
|
|
|
453
|
+
// packages/telemetry-core/src/machine-id.ts
|
|
454
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
455
|
+
import os2 from "node:os";
|
|
456
|
+
function getDefaultTelemetryOsProvider() {
|
|
457
|
+
return os2;
|
|
458
|
+
}
|
|
459
|
+
function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
|
|
460
|
+
return createHash4("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
|
|
461
|
+
}
|
|
462
|
+
var init_machine_id = () => {};
|
|
463
|
+
|
|
464
|
+
// packages/telemetry-core/src/injected-client.ts
|
|
465
|
+
function isTelemetryClientEnabled(input) {
|
|
466
|
+
const env = input.env ?? process.env;
|
|
467
|
+
return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) && hasTelemetryApiKey(env, input.product.defaultApiKey);
|
|
468
|
+
}
|
|
469
|
+
function createTelemetryClient(input) {
|
|
470
|
+
if (!isTelemetryClientEnabled(input)) {
|
|
471
|
+
return NO_OP_CLIENT;
|
|
472
|
+
}
|
|
473
|
+
const transport = createTransport(input);
|
|
474
|
+
if (transport === null) {
|
|
475
|
+
return NO_OP_CLIENT;
|
|
476
|
+
}
|
|
477
|
+
const sharedProperties = getSharedProperties(input);
|
|
478
|
+
return {
|
|
479
|
+
enabled: true,
|
|
480
|
+
trackActive: ({ dayUTC, distinctId, reason }) => {
|
|
481
|
+
try {
|
|
482
|
+
transport.capture({
|
|
483
|
+
distinctId,
|
|
484
|
+
event: input.product.eventName,
|
|
485
|
+
properties: {
|
|
486
|
+
...sharedProperties,
|
|
487
|
+
$process_person_profile: false,
|
|
488
|
+
day_utc: dayUTC,
|
|
489
|
+
reason
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
} catch (error) {
|
|
493
|
+
input.diagnostics?.({
|
|
494
|
+
event: "telemetry_capture_failed",
|
|
495
|
+
source: input.source,
|
|
496
|
+
error,
|
|
497
|
+
errorKind: error instanceof Error ? "error" : "non_error"
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
flush: async () => {
|
|
502
|
+
if (transport.flush === undefined) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
await transport.flush();
|
|
506
|
+
},
|
|
507
|
+
shutdown: async () => {
|
|
508
|
+
try {
|
|
509
|
+
await transport.shutdown();
|
|
510
|
+
} catch (error) {
|
|
511
|
+
input.diagnostics?.({
|
|
512
|
+
event: "telemetry_shutdown_failed",
|
|
513
|
+
source: input.source,
|
|
514
|
+
error,
|
|
515
|
+
errorKind: error instanceof Error ? "error" : "non_error"
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function createTransport(input) {
|
|
522
|
+
const env = input.env ?? process.env;
|
|
523
|
+
const factory = input.transportFactory;
|
|
524
|
+
try {
|
|
525
|
+
return factory(getTelemetryApiKey(env, input.product.defaultApiKey), {
|
|
526
|
+
enableExceptionAutocapture: false,
|
|
527
|
+
enableLocalEvaluation: false,
|
|
528
|
+
strictLocalEvaluation: true,
|
|
529
|
+
disableRemoteConfig: true,
|
|
530
|
+
flushAt: 1,
|
|
531
|
+
flushInterval: 0,
|
|
532
|
+
host: getTelemetryHost(env, input.product.defaultHost),
|
|
533
|
+
disableGeoip: input.product.disableGeoip ?? false,
|
|
534
|
+
...input.product.transportOptions
|
|
535
|
+
});
|
|
536
|
+
} catch (error) {
|
|
537
|
+
input.diagnostics?.({
|
|
538
|
+
event: "telemetry_posthog_init_failed",
|
|
539
|
+
source: input.source,
|
|
540
|
+
error,
|
|
541
|
+
errorKind: error instanceof Error ? "error" : "non_error"
|
|
542
|
+
});
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function getSharedProperties(input) {
|
|
547
|
+
const osProvider = input.osProvider ?? getDefaultTelemetryOsProvider();
|
|
548
|
+
const cpuInfo = getSafeCpuInfo(osProvider, input);
|
|
549
|
+
return {
|
|
550
|
+
platform: input.product.platform,
|
|
551
|
+
product_name: input.product.productName,
|
|
552
|
+
package_name: input.product.packageName,
|
|
553
|
+
package_version: input.product.packageVersion,
|
|
554
|
+
runtime: "bun",
|
|
555
|
+
runtime_version: process.versions.bun ?? process.version,
|
|
556
|
+
source: input.source,
|
|
557
|
+
$os: osProvider.platform(),
|
|
558
|
+
$os_version: osProvider.release(),
|
|
559
|
+
os_arch: osProvider.arch(),
|
|
560
|
+
os_type: osProvider.type(),
|
|
561
|
+
cpu_count: cpuInfo.count,
|
|
562
|
+
cpu_model: cpuInfo.model,
|
|
563
|
+
total_memory_gb: Math.round(osProvider.totalmem() / 1024 / 1024 / 1024),
|
|
564
|
+
locale: Intl.DateTimeFormat().resolvedOptions().locale,
|
|
565
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
566
|
+
shell: process.env.SHELL,
|
|
567
|
+
ci: Boolean(process.env.CI),
|
|
568
|
+
terminal: process.env.TERM_PROGRAM,
|
|
569
|
+
...input.product.additionalProperties
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function getSafeCpuInfo(osProvider, input) {
|
|
573
|
+
try {
|
|
574
|
+
const cpuInfo = osProvider.cpus();
|
|
575
|
+
return {
|
|
576
|
+
count: cpuInfo.length,
|
|
577
|
+
model: cpuInfo[0]?.model
|
|
578
|
+
};
|
|
579
|
+
} catch (error) {
|
|
580
|
+
input.diagnostics?.({
|
|
581
|
+
event: "telemetry_cpu_info_unavailable",
|
|
582
|
+
source: "shared",
|
|
583
|
+
error,
|
|
584
|
+
errorKind: error instanceof Error ? "error" : "non_error"
|
|
585
|
+
});
|
|
586
|
+
return {
|
|
587
|
+
count: 0,
|
|
588
|
+
model: undefined
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
var NO_OP_CLIENT;
|
|
593
|
+
var init_injected_client = __esm(() => {
|
|
594
|
+
init_env();
|
|
595
|
+
init_machine_id();
|
|
596
|
+
NO_OP_CLIENT = {
|
|
597
|
+
enabled: false,
|
|
598
|
+
trackActive: () => {
|
|
599
|
+
return;
|
|
600
|
+
},
|
|
601
|
+
flush: async () => {
|
|
602
|
+
return;
|
|
603
|
+
},
|
|
604
|
+
shutdown: async () => {
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
});
|
|
609
|
+
|
|
453
610
|
// node_modules/.bun/posthog-node@5.52.4/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
|
|
454
611
|
import { dirname as dirname11, posix as posix3, sep as sep7 } from "node:path";
|
|
455
612
|
function createModulerModifier() {
|
|
@@ -9823,18 +9980,7 @@ var init_index_node = __esm(() => {
|
|
|
9823
9980
|
};
|
|
9824
9981
|
});
|
|
9825
9982
|
|
|
9826
|
-
// packages/telemetry-core/src/
|
|
9827
|
-
import { createHash as createHash4 } from "node:crypto";
|
|
9828
|
-
import os2 from "node:os";
|
|
9829
|
-
function getDefaultTelemetryOsProvider() {
|
|
9830
|
-
return os2;
|
|
9831
|
-
}
|
|
9832
|
-
function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
|
|
9833
|
-
return createHash4("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
|
|
9834
|
-
}
|
|
9835
|
-
var init_machine_id = () => {};
|
|
9836
|
-
|
|
9837
|
-
// packages/telemetry-core/src/posthog-client.ts
|
|
9983
|
+
// packages/telemetry-core/src/posthog-transport.ts
|
|
9838
9984
|
class PostHogTelemetryTransport {
|
|
9839
9985
|
#client;
|
|
9840
9986
|
constructor(apiKey, options) {
|
|
@@ -9853,161 +9999,20 @@ class PostHogTelemetryTransport {
|
|
|
9853
9999
|
function createDefaultPostHogTransport(apiKey, options) {
|
|
9854
10000
|
return new PostHogTelemetryTransport(apiKey, options);
|
|
9855
10001
|
}
|
|
9856
|
-
|
|
9857
|
-
const env = input.env ?? process.env;
|
|
9858
|
-
return !shouldDisableTelemetry({ env, productEnvPrefix: input.product.productEnvPrefix }) && hasTelemetryApiKey(env, input.product.defaultApiKey);
|
|
9859
|
-
}
|
|
9860
|
-
function createTelemetryClient(input) {
|
|
9861
|
-
if (!isTelemetryClientEnabled(input)) {
|
|
9862
|
-
return NO_OP_CLIENT;
|
|
9863
|
-
}
|
|
9864
|
-
const transport = createTransport(input);
|
|
9865
|
-
if (transport === null) {
|
|
9866
|
-
return NO_OP_CLIENT;
|
|
9867
|
-
}
|
|
9868
|
-
const sharedProperties = getSharedProperties(input);
|
|
9869
|
-
return {
|
|
9870
|
-
enabled: true,
|
|
9871
|
-
trackActive: ({ dayUTC, distinctId, reason }) => {
|
|
9872
|
-
try {
|
|
9873
|
-
transport.capture({
|
|
9874
|
-
distinctId,
|
|
9875
|
-
event: input.product.eventName,
|
|
9876
|
-
properties: {
|
|
9877
|
-
...sharedProperties,
|
|
9878
|
-
$process_person_profile: false,
|
|
9879
|
-
day_utc: dayUTC,
|
|
9880
|
-
reason
|
|
9881
|
-
}
|
|
9882
|
-
});
|
|
9883
|
-
} catch (error) {
|
|
9884
|
-
input.diagnostics?.({
|
|
9885
|
-
event: "telemetry_capture_failed",
|
|
9886
|
-
source: input.source,
|
|
9887
|
-
error,
|
|
9888
|
-
errorKind: error instanceof Error ? "error" : "non_error"
|
|
9889
|
-
});
|
|
9890
|
-
}
|
|
9891
|
-
},
|
|
9892
|
-
flush: async () => {
|
|
9893
|
-
if (transport.flush === undefined) {
|
|
9894
|
-
return;
|
|
9895
|
-
}
|
|
9896
|
-
await transport.flush();
|
|
9897
|
-
},
|
|
9898
|
-
shutdown: async () => {
|
|
9899
|
-
try {
|
|
9900
|
-
await transport.shutdown();
|
|
9901
|
-
} catch (error) {
|
|
9902
|
-
input.diagnostics?.({
|
|
9903
|
-
event: "telemetry_shutdown_failed",
|
|
9904
|
-
source: input.source,
|
|
9905
|
-
error,
|
|
9906
|
-
errorKind: error instanceof Error ? "error" : "non_error"
|
|
9907
|
-
});
|
|
9908
|
-
}
|
|
9909
|
-
}
|
|
9910
|
-
};
|
|
9911
|
-
}
|
|
9912
|
-
function createTransport(input) {
|
|
9913
|
-
const env = input.env ?? process.env;
|
|
9914
|
-
const factory = input.transportFactory ?? createDefaultPostHogTransport;
|
|
9915
|
-
try {
|
|
9916
|
-
return factory(getTelemetryApiKey(env, input.product.defaultApiKey), {
|
|
9917
|
-
enableExceptionAutocapture: false,
|
|
9918
|
-
enableLocalEvaluation: false,
|
|
9919
|
-
strictLocalEvaluation: true,
|
|
9920
|
-
disableRemoteConfig: true,
|
|
9921
|
-
flushAt: 1,
|
|
9922
|
-
flushInterval: 0,
|
|
9923
|
-
host: getTelemetryHost(env, input.product.defaultHost),
|
|
9924
|
-
disableGeoip: input.product.disableGeoip ?? false,
|
|
9925
|
-
...input.product.transportOptions
|
|
9926
|
-
});
|
|
9927
|
-
} catch (error) {
|
|
9928
|
-
input.diagnostics?.({
|
|
9929
|
-
event: "telemetry_posthog_init_failed",
|
|
9930
|
-
source: input.source,
|
|
9931
|
-
error,
|
|
9932
|
-
errorKind: error instanceof Error ? "error" : "non_error"
|
|
9933
|
-
});
|
|
9934
|
-
return null;
|
|
9935
|
-
}
|
|
9936
|
-
}
|
|
9937
|
-
function getSharedProperties(input) {
|
|
9938
|
-
const osProvider = input.osProvider ?? getDefaultTelemetryOsProvider();
|
|
9939
|
-
const cpuInfo = getSafeCpuInfo(osProvider, input);
|
|
9940
|
-
return {
|
|
9941
|
-
platform: input.product.platform,
|
|
9942
|
-
product_name: input.product.productName,
|
|
9943
|
-
package_name: input.product.packageName,
|
|
9944
|
-
package_version: input.product.packageVersion,
|
|
9945
|
-
runtime: "bun",
|
|
9946
|
-
runtime_version: process.versions.bun ?? process.version,
|
|
9947
|
-
source: input.source,
|
|
9948
|
-
$os: osProvider.platform(),
|
|
9949
|
-
$os_version: osProvider.release(),
|
|
9950
|
-
os_arch: osProvider.arch(),
|
|
9951
|
-
os_type: osProvider.type(),
|
|
9952
|
-
cpu_count: cpuInfo.count,
|
|
9953
|
-
cpu_model: cpuInfo.model,
|
|
9954
|
-
total_memory_gb: Math.round(osProvider.totalmem() / 1024 / 1024 / 1024),
|
|
9955
|
-
locale: Intl.DateTimeFormat().resolvedOptions().locale,
|
|
9956
|
-
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
9957
|
-
shell: process.env.SHELL,
|
|
9958
|
-
ci: Boolean(process.env.CI),
|
|
9959
|
-
terminal: process.env.TERM_PROGRAM,
|
|
9960
|
-
...input.product.additionalProperties
|
|
9961
|
-
};
|
|
9962
|
-
}
|
|
9963
|
-
function getSafeCpuInfo(osProvider, input) {
|
|
9964
|
-
try {
|
|
9965
|
-
const cpuInfo = osProvider.cpus();
|
|
9966
|
-
return {
|
|
9967
|
-
count: cpuInfo.length,
|
|
9968
|
-
model: cpuInfo[0]?.model
|
|
9969
|
-
};
|
|
9970
|
-
} catch (error) {
|
|
9971
|
-
input.diagnostics?.({
|
|
9972
|
-
event: "telemetry_cpu_info_unavailable",
|
|
9973
|
-
source: "shared",
|
|
9974
|
-
error,
|
|
9975
|
-
errorKind: error instanceof Error ? "error" : "non_error"
|
|
9976
|
-
});
|
|
9977
|
-
return {
|
|
9978
|
-
count: 0,
|
|
9979
|
-
model: undefined
|
|
9980
|
-
};
|
|
9981
|
-
}
|
|
9982
|
-
}
|
|
9983
|
-
var NO_OP_CLIENT;
|
|
9984
|
-
var init_posthog_client = __esm(() => {
|
|
10002
|
+
var init_posthog_transport = __esm(() => {
|
|
9985
10003
|
init_index_node();
|
|
9986
|
-
init_env();
|
|
9987
|
-
init_machine_id();
|
|
9988
|
-
NO_OP_CLIENT = {
|
|
9989
|
-
enabled: false,
|
|
9990
|
-
trackActive: () => {
|
|
9991
|
-
return;
|
|
9992
|
-
},
|
|
9993
|
-
flush: async () => {
|
|
9994
|
-
return;
|
|
9995
|
-
},
|
|
9996
|
-
shutdown: async () => {
|
|
9997
|
-
return;
|
|
9998
|
-
}
|
|
9999
|
-
};
|
|
10000
10004
|
});
|
|
10001
10005
|
|
|
10002
10006
|
// packages/telemetry-core/src/events.ts
|
|
10003
|
-
var
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10007
|
+
var init_events = () => {};
|
|
10008
|
+
|
|
10009
|
+
// packages/telemetry-core/src/posthog-client.ts
|
|
10010
|
+
function createTelemetryClient2(input) {
|
|
10011
|
+
return createTelemetryClient({ ...input, transportFactory: input.transportFactory ?? createDefaultPostHogTransport });
|
|
10012
|
+
}
|
|
10013
|
+
var init_posthog_client = __esm(() => {
|
|
10014
|
+
init_injected_client();
|
|
10015
|
+
init_posthog_transport();
|
|
10011
10016
|
});
|
|
10012
10017
|
|
|
10013
10018
|
// packages/telemetry-core/src/record-daily-active.ts
|
|
@@ -10031,7 +10036,7 @@ var package_default;
|
|
|
10031
10036
|
var init_package = __esm(() => {
|
|
10032
10037
|
package_default = {
|
|
10033
10038
|
name: "@oh-my-opencode/omo-codex",
|
|
10034
|
-
version: "5.1.
|
|
10039
|
+
version: "5.1.41",
|
|
10035
10040
|
type: "module",
|
|
10036
10041
|
private: true,
|
|
10037
10042
|
description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
|
|
@@ -10161,7 +10166,7 @@ function resolveActivityStateProvider(options) {
|
|
|
10161
10166
|
return () => getPostHogActivityCaptureState(options.now ?? new Date);
|
|
10162
10167
|
}
|
|
10163
10168
|
function createPostHogClient(source, options = {}) {
|
|
10164
|
-
const client =
|
|
10169
|
+
const client = createTelemetryClient2({
|
|
10165
10170
|
diagnostics: writeTelemetryDiagnostic2,
|
|
10166
10171
|
env: options.env ?? process.env,
|
|
10167
10172
|
osProvider: options.osProvider ?? resolveOsProvider(),
|
|
@@ -19458,14 +19463,20 @@ var OmoComputerSettingsLayerSchema = object({
|
|
|
19458
19463
|
var OmoComputerSettingsSchema = OmoComputerSettingsLayerSchema;
|
|
19459
19464
|
|
|
19460
19465
|
// packages/omo-config-core/src/schema/git-master.ts
|
|
19466
|
+
var GIT_ENV_ASSIGNMENT_PATTERN = /^(?:[A-Za-z_][A-Za-z0-9_]*=[A-Za-z0-9_-]*)(?: [A-Za-z_][A-Za-z0-9_]*=[A-Za-z0-9_-]*)*$/;
|
|
19467
|
+
var GitEnvPrefixSchema = string2().refine((value) => value === "" || GIT_ENV_ASSIGNMENT_PATTERN.test(value), {
|
|
19468
|
+
message: 'git_env_prefix must be empty or use shell-safe env assignments like "GIT_MASTER=1"'
|
|
19469
|
+
});
|
|
19461
19470
|
var OmoGitMasterSettingsShape = {
|
|
19462
19471
|
commit_footer: union([boolean2(), string2()]),
|
|
19463
|
-
include_co_authored_by: boolean2()
|
|
19472
|
+
include_co_authored_by: boolean2(),
|
|
19473
|
+
git_env_prefix: GitEnvPrefixSchema
|
|
19464
19474
|
};
|
|
19465
19475
|
var OmoGitMasterSettingsLayerSchema = object(OmoGitMasterSettingsShape).partial().strict();
|
|
19466
19476
|
var OmoGitMasterSettingsSchema = OmoGitMasterSettingsLayerSchema.extend({
|
|
19467
19477
|
commit_footer: union([boolean2(), string2()]).default(false),
|
|
19468
|
-
include_co_authored_by: boolean2().default(false)
|
|
19478
|
+
include_co_authored_by: boolean2().default(false),
|
|
19479
|
+
git_env_prefix: GitEnvPrefixSchema.default("GIT_MASTER=1")
|
|
19469
19480
|
}).strict();
|
|
19470
19481
|
|
|
19471
19482
|
// packages/omo-config-core/src/schema/harness.ts
|
|
@@ -19475,6 +19486,19 @@ var OmoHarnessIdSchema = _enum(OMO_CONFIG_HARNESS_IDS);
|
|
|
19475
19486
|
var OMO_CONFIG_LEGACY_HARNESS_ALIASES = { senpi: "native" };
|
|
19476
19487
|
var OMO_CONFIG_LEGACY_HARNESS_IDS = Object.keys(OMO_CONFIG_LEGACY_HARNESS_ALIASES);
|
|
19477
19488
|
|
|
19489
|
+
// packages/omo-config-core/src/schema/memory-agreements.ts
|
|
19490
|
+
var OMO_MEMORY_AGREEMENTS_DEFAULTS = { enabled: true, needs_human_threshold: 3, max_items: 64 };
|
|
19491
|
+
var OmoMemoryAgreementsSchema = object({
|
|
19492
|
+
enabled: boolean2().default(OMO_MEMORY_AGREEMENTS_DEFAULTS.enabled),
|
|
19493
|
+
needs_human_threshold: number2().int().min(1).default(OMO_MEMORY_AGREEMENTS_DEFAULTS.needs_human_threshold),
|
|
19494
|
+
max_items: number2().int().min(8).max(256).default(OMO_MEMORY_AGREEMENTS_DEFAULTS.max_items)
|
|
19495
|
+
}).strict();
|
|
19496
|
+
var OmoMemoryAgreementsLayerSchema = object({
|
|
19497
|
+
enabled: boolean2().optional(),
|
|
19498
|
+
needs_human_threshold: number2().int().min(1).optional(),
|
|
19499
|
+
max_items: number2().int().min(8).max(256).optional()
|
|
19500
|
+
}).strict();
|
|
19501
|
+
|
|
19478
19502
|
// packages/omo-config-core/src/schema/memory.ts
|
|
19479
19503
|
var OmoMemoryReflectionTriggerSchema = object({
|
|
19480
19504
|
step_count: number2().int().nonnegative().default(25),
|
|
@@ -19618,6 +19642,7 @@ var OmoMemoryAgentOverridesSchema = object({
|
|
|
19618
19642
|
facts: OmoMemoryFactsLayerSchema.optional(),
|
|
19619
19643
|
dream: OmoMemoryDreamLayerSchema.optional(),
|
|
19620
19644
|
people: OmoMemoryPeopleLayerSchema.optional(),
|
|
19645
|
+
agreements: OmoMemoryAgreementsLayerSchema.optional(),
|
|
19621
19646
|
soul: OmoMemorySoulLayerSchema.optional(),
|
|
19622
19647
|
write_notice: OmoMemoryWriteNoticeLayerSchema.optional(),
|
|
19623
19648
|
sync: OmoMemorySyncLayerSchema.optional(),
|
|
@@ -19648,6 +19673,7 @@ var OmoMemorySettingsSchema = object({
|
|
|
19648
19673
|
auto_select_max_chars: 150000
|
|
19649
19674
|
}),
|
|
19650
19675
|
people: OmoMemoryPeopleSchema.default({ enabled: true, max_entries: 40, max_entry_chars: 200 }),
|
|
19676
|
+
agreements: OmoMemoryAgreementsSchema.default(OMO_MEMORY_AGREEMENTS_DEFAULTS),
|
|
19651
19677
|
soul: OmoMemorySoulSchema.default({ edit_notice: true }),
|
|
19652
19678
|
write_notice: OmoMemoryWriteNoticeSchema.default({ enabled: true }),
|
|
19653
19679
|
sync: OmoMemorySyncSchema.default({ enabled: true }),
|
|
@@ -19674,6 +19700,7 @@ var OmoMemorySettingsLayerSchema = object({
|
|
|
19674
19700
|
facts: OmoMemoryFactsLayerSchema.optional(),
|
|
19675
19701
|
dream: OmoMemoryDreamLayerSchema.optional(),
|
|
19676
19702
|
people: OmoMemoryPeopleLayerSchema.optional(),
|
|
19703
|
+
agreements: OmoMemoryAgreementsLayerSchema.optional(),
|
|
19677
19704
|
soul: OmoMemorySoulLayerSchema.optional(),
|
|
19678
19705
|
write_notice: OmoMemoryWriteNoticeLayerSchema.optional(),
|
|
19679
19706
|
sync: OmoMemorySyncLayerSchema.optional(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: frontend
|
|
3
|
-
description: "Builds, styles, and polishes web UI
|
|
3
|
+
description: "Builds, styles, and polishes anything drawn with HTML, CSS, or SVG: web UI, pages, components, HTML reports rendered to PDF or print, figures, PNG/SVG diagrams, slides, and images for Notion or Slack. Use for any styling, layout, animation, or visual-quality task, or when asked to make something look or feel a certain way."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Frontend
|
|
@@ -25,12 +25,12 @@ This file is a router, not a rulebook. The rules live in four rulesets under `re
|
|
|
25
25
|
|
|
26
26
|
**For implementation work, design + perfection load together.** Beauty with a 2 MB bundle fails; Lighthouse 100 that looks like AI slop fails. Both win or neither does.
|
|
27
27
|
|
|
28
|
-
## Draft guard — read before the first line of
|
|
28
|
+
## Draft guard — read before the first line of HTML or CSS
|
|
29
29
|
|
|
30
30
|
Some tells regenerate by default, so they are kept out of the first draft rather than left for QA to find.
|
|
31
31
|
|
|
32
|
-
- **No coloured
|
|
33
|
-
- **Lint before visual QA.** Run `bun $SKILL_DIR/scripts/perfection/check-accent-stripes.ts <changed files or dirs>` on every stylesheet and
|
|
32
|
+
- **No coloured bar on one side of a box, rounded or square, and no accent outline on a rounded card, decorative or state.** A card, callout, warning, cover block, stat tile, testimonial, alert, or list row never carries a coloured stripe on one side: `border-left: 4px solid <accent>` or `border-l-4 border-indigo-500`, a coloured `::before`/`::after` bar inside it, an inset `box-shadow` stripe, or a hard-stop gradient band or gradient `border-image` along one edge. A rounded card never wears a 2px-or-wider accent outline either (`border: 2px solid var(--primary)`, `ring-2 ring-indigo-500`, an inset ring). Both read as generated whether they decorate the box or mark it selected, focused, or active, and an accent underline under a heading, tab, or link counts too: use a neutral 1px rule, or set the text itself in the accent ink. Give the card its identity another way: a tonal surface (one ink at a low alpha, or the next step of the surface ramp), an eyebrow or heading set in the accent ink, a leading glyph, or more space between groups. Encode state with one ink at many alphas (hover/selected/active washes), a check glyph for selection, and tonal layering for focus. The coloured edges that stay allowed: keyboard `focus-visible` rings, validation states on form inputs, neutral 1px hairlines and dividers between rows or sections, table rules, and a blockquote's neutral rule. This covers pre-existing instances on any surface you touch.
|
|
33
|
+
- **Lint before visual QA.** Run `bun $SKILL_DIR/scripts/perfection/check-accent-stripes.ts <changed files or dirs>` on every stylesheet, component, and HTML file you wrote, including a report or figure you will print, screenshot, or render to an image. It reads CSS/SCSS/Less, HTML, JSX/TSX, Vue, Svelte, Astro, Tailwind classes (including `@apply` and `cva`/`cn` strings), inline styles, and styled-components. Exit 1 means a stripe is in the draft: remove the stripe, do not argue with the finding.
|
|
34
34
|
|
|
35
35
|
## Design System and Component Workflow
|
|
36
36
|
|
|
@@ -145,7 +145,7 @@ Domains: `product` `style` `typography` `color` `landing` `chart` `ux` `react` `
|
|
|
145
145
|
- **Concrete reference = contract.** When a screenshot, mockup, or annotated reference exists, match its pixels, copy, component structure, and responsive intent unless the user accepts a deviation.
|
|
146
146
|
- **Never weaken UX OR flatten the surface to buy points.** No dropping animations, hiding content, simplifying interactions, or replacing rendered/lit material with flat fills and flat geometric primitives for a Lighthouse score or a deadline. Hit 100 AND keep the surface dimensional — both, or neither.
|
|
147
147
|
- **No emojis as icons.** SVG icon sets only (Lucide, Heroicons, Radix, Phosphor).
|
|
148
|
-
- **No coloured
|
|
148
|
+
- **No coloured edge bars, no accent outlines on cards.** A decorative accent stripe on a callout, rounded or square, and a `border-l-2 border-primary` stripe on a selected row are the same tell, and so is a primary-tinted outline on a focused card. The Draft guard above carries the replacements and the allowed exceptions; `check-accent-stripes.ts` must exit 0 before `/visual-qa`. Applies to code you write AND to pre-existing instances on any surface you touch — sweep them out.
|
|
149
149
|
- **GPU-composited animation only** — `transform`, `opacity`, `filter`; never animate layout properties.
|
|
150
150
|
- **Slop animation is forbidden — motion serves meaning.** Every animation or hover must map to a real interaction, state change, or affordance. A hover that changes nothing, motion on a non-interactive element, or a decorative micro-animation with no informational purpose is slop — do not add it.
|
|
151
151
|
- **Done is the `/visual-qa` gate, not your own glance.** A frontend design task is verified through `/visual-qa` - its HIG-based checklist, its capture matrix (every page and every sibling surface, phone and desktop, light and dark, scrolled-end, motion driven and inspected) and its dual-oracle completion gate on fresh evidence. This skill does not keep its own list of visual checks; the verifier owns it.
|
|
@@ -160,4 +160,4 @@ Domains: `product` `style` `typography` `color` `landing` `chart` `ux` `react` `
|
|
|
160
160
|
|
|
161
161
|
## Activation
|
|
162
162
|
|
|
163
|
-
Use for any frontend, web UI, UX, visual, design, styling, layout, animation, performance, accessibility, or SEO work — building, redesigning, auditing, or generating mockups. Not for backend, CLI, or pure-logic tasks with no visual surface.
|
|
163
|
+
Use for any frontend, web UI, UX, visual, design, styling, layout, animation, performance, accessibility, or SEO work, and for every HTML/CSS/SVG artifact that ends up as a PDF, print page, report, figure, diagram, slide, or image — building, redesigning, auditing, or generating mockups. Not for backend, CLI, or pure-logic tasks with no visual surface.
|
|
@@ -202,7 +202,7 @@ Triggers: an animated, shader, particle, or grid background; a hero that must fe
|
|
|
202
202
|
## Anti-patterns — do not do these
|
|
203
203
|
|
|
204
204
|
- **Don't load nothing and just freestyle.** That produces the exact "generic AI SaaS slop" — purple-blue gradient backgrounds, rounded-2xl-on-everything, three feature cards in a grid, generic Inter font, lorem ipsum. The skills exist precisely to prevent this.
|
|
205
|
-
- **Don't put a coloured
|
|
205
|
+
- **Don't put a coloured bar on one side of a box, rounded or square, or an accent outline on a rounded card, for decoration or for state.** A feature card with `border-top: 4px solid` accent, a callout or cover block with `border-l-4 border-indigo-500`, a stat tile with a coloured `::before` bar, `border-l-2 border-primary` on the selected row, a 2px primary outline on the focused card: each is the generic AI tell. Identity comes from a tonal surface, an eyebrow or heading in the accent ink, a glyph, or spacing; state is ink-alpha washes, a glyph for selection, tonal layering for focus. `focus-visible` rings, input validation states, neutral hairlines, table rules, and a blockquote's neutral rule are the only coloured or ruled edges allowed. Includes pre-existing instances on surfaces you touch.
|
|
206
206
|
- **Don't ignore the user's named brand.** If they say "Linear-style" and you build something that doesn't match Linear's actual aesthetic (purple, ultra-tight spacing, mono accents, etc.), you have failed the routing.
|
|
207
207
|
- **Don't apply a Layer B brand verbatim if the project is not that brand.** The DESIGN.md captures *inspiration* — extract the tokens (palette, type scale, component patterns) and apply them to the project's own content. Do not copy logos or trademarked imagery.
|
|
208
208
|
- **Don't use imagegen skills to write code.** They are explicitly image-only. The agent has been observed trying to "describe" the image as React code — that is the wrong skill, switch to `image-to-code-skill.md` instead.
|
|
@@ -222,7 +222,7 @@ Once references are loaded, before writing any UI code:
|
|
|
222
222
|
8. **All tokens trace back to `DESIGN.md`.** No orphan hex codes, no magic px values. If you need a new token, update `DESIGN.md` first.
|
|
223
223
|
9. **New reusable patterns (used 2+ times) get documented back into `DESIGN.md` Section 5.**
|
|
224
224
|
10. **No generic-default drift (expressive briefs).** The shipped CSS must use the `DESIGN.md` material, not the model's priors. Load the declared fonts (do not silently fall back to Inter or system fonts), build elevated surfaces from the declared multi-layer recipe (not a lone `backdrop-filter: blur`), and color from the ramp stops (not one tint at varied opacity). Grep your styles before QA: finding `Inter`, a single blur on "glass", or one brand hex reused everywhere means you regressed to priors — fix it before declaring done.
|
|
225
|
-
11. **No coloured edge stripes.** Run `bun ../../scripts/perfection/check-accent-stripes.ts <changed files or dirs>` (from this directory; `$SKILL_DIR/scripts/perfection/check-accent-stripes.ts` from anywhere). It must exit 0 before Phase Final; every finding is a decorative or state stripe
|
|
225
|
+
11. **No coloured edge stripes.** Run `bun ../../scripts/perfection/check-accent-stripes.ts <changed files or dirs>` (from this directory; `$SKILL_DIR/scripts/perfection/check-accent-stripes.ts` from anywhere). It must exit 0 before Phase Final; every finding is a decorative or state stripe, or an accent outline, to replace, per the anti-pattern above.
|
|
226
226
|
|
|
227
227
|
## Quick lookup table — most common requests
|
|
228
228
|
|
|
@@ -67,7 +67,7 @@ During the audit loop, after Lighthouse scores pass, run a Design System Complia
|
|
|
67
67
|
- **Spacing**: every margin/padding/gap value must be a multiple of the base unit (4px) and ideally use a declared token.
|
|
68
68
|
- **Components**: any component used 2+ times must be documented in `DESIGN.md` Section 5. If it isn't, add it.
|
|
69
69
|
- **Depth**: if `DESIGN.md` says "borders-only", there must be zero `box-shadow` declarations. If "tonal-shift", zero borders for surface separation.
|
|
70
|
-
- **Accent stripes**: run `bun ../../scripts/perfection/check-accent-stripes.ts <src dirs>`. It flags a coloured one-side border (including a gradient `border-image`), a coloured `::before`/`::after` bar, an inset `box-shadow` stripe, or a hard-stop gradient band along one edge of a rounded
|
|
70
|
+
- **Accent stripes**: run `bun ../../scripts/perfection/check-accent-stripes.ts <src dirs>`. It flags a coloured one-side border (including a gradient `border-image`), a coloured `::before`/`::after` bar, an inset `box-shadow` stripe, or a hard-stop gradient band along one edge of any box, rounded or square, and a 2px-or-wider accent outline (border or inset ring) on a rounded card, in CSS, Tailwind, inline styles, and styled-components, whether the stripe is decorative or marks selected/focused/active. Each finding is a violation — identity belongs to tonal surfaces, headings, glyphs, and spacing; state belongs to ink-alpha washes and glyphs. Keyboard `focus-visible` rings, input validation states, neutral hairlines, table rules, and a blockquote's neutral rule are exempt, and the script already skips them.
|
|
71
71
|
|
|
72
72
|
A page that scores Lighthouse 100 but uses 14 undeclared hex codes and 8 magic spacing values is **NOT DONE**. The design system is the architecture — Lighthouse measures the performance of that architecture.
|
|
73
73
|
|
|
@@ -92,7 +92,7 @@ Quick audit via the cross-platform Python CLI (macOS, Linux, Windows):
|
|
|
92
92
|
uv run $SKILL_DIR/scripts/perfection/lighthouse-audit.py https://localhost:3000
|
|
93
93
|
uv run $SKILL_DIR/scripts/perfection/lighthouse-audit.py https://localhost:3000 --threshold 95
|
|
94
94
|
uv run $SKILL_DIR/scripts/perfection/lighthouse-audit.py https://localhost:3000 --desktop-only
|
|
95
|
-
bun $SKILL_DIR/scripts/perfection/check-accent-stripes.ts src/ # exit 1 = coloured
|
|
95
|
+
bun $SKILL_DIR/scripts/perfection/check-accent-stripes.ts src/ # exit 1 = coloured one-side bar, or accent outline on a rounded card
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
Or use the TypeScript approach directly in your test suite:
|
package/packages/shared-skills/skills/frontend/scripts/perfection/accent-stripes/declarations.ts
CHANGED
|
@@ -72,10 +72,6 @@ function collectEdges(declarations: readonly Declaration[]): Map<Side, Edge> {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export type Corner = "tl" | "tr" | "br" | "bl"
|
|
75
|
-
export const ALL_CORNERS: ReadonlySet<Corner> = new Set(["tl", "tr", "br", "bl"])
|
|
76
|
-
export const SIDE_CORNERS: Readonly<Record<Side, readonly [Corner, Corner]>> = {
|
|
77
|
-
top: ["tl", "tr"], right: ["tr", "br"], bottom: ["br", "bl"], left: ["tl", "bl"],
|
|
78
|
-
}
|
|
79
75
|
const CORNER_LONGHAND: Readonly<Record<string, Corner>> = {
|
|
80
76
|
"top-left": "tl", "top-right": "tr", "bottom-right": "br", "bottom-left": "bl",
|
|
81
77
|
"start-start": "tl", "start-end": "tr", "end-end": "br", "end-start": "bl",
|
|
@@ -104,20 +100,33 @@ export function roundedCorners(declarations: readonly Declaration[]): Set<Corner
|
|
|
104
100
|
return corners
|
|
105
101
|
}
|
|
106
102
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
const edge = bySide.get(s)
|
|
113
|
-
return edge !== undefined && isStripe(edge) && SIDE_CORNERS[s].some((c) => corners.has(c))
|
|
114
|
-
})
|
|
115
|
-
if (!bent) return false
|
|
103
|
+
const isStripe = (e: Edge) => !e.hidden && (e.width ?? 0) >= MIN_STRIPE_PX && e.color === "chromatic"
|
|
104
|
+
|
|
105
|
+
export function hasEdgeStripe(declarations: readonly Declaration[]): boolean {
|
|
106
|
+
const edges = [...collectEdges(declarations).values()]
|
|
107
|
+
if (!edges.some(isStripe)) return false
|
|
116
108
|
const first = edges[0]
|
|
117
109
|
const uniform = edges.every((e) => e.width === first?.width && e.color === first?.color && e.hidden === first?.hidden)
|
|
118
110
|
return !uniform
|
|
119
111
|
}
|
|
120
112
|
|
|
113
|
+
function isInsetRing(value: string): boolean {
|
|
114
|
+
return splitTopLevel(value, ",").some((layer) => {
|
|
115
|
+
const tokens = splitTopLevel(layer, " ")
|
|
116
|
+
if (!tokens.some((t) => t.toLowerCase() === "inset")) return false
|
|
117
|
+
const [x = 0, y = 0, blur = 0, spread = 0] = tokens.map(parseLength).filter((n): n is number => n !== undefined)
|
|
118
|
+
return x === 0 && y === 0 && blur === 0 && spread >= MIN_STRIPE_PX && tokens.some((t) => looksLikeColor(t) && classifyColor(t) === "chromatic")
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** A uniform accent border (not a gradient border-image) or inset ring of MIN_STRIPE_PX or more. */
|
|
123
|
+
export function hasAccentOutline(declarations: readonly Declaration[]): boolean {
|
|
124
|
+
const image = declarations.some(({ prop }) => prop === "border-image" || prop === "border-image-source")
|
|
125
|
+
const edges = [...collectEdges(declarations).values()]
|
|
126
|
+
const frame = !image && edges.every((e) => isStripe(e) && e.width === edges[0]?.width)
|
|
127
|
+
return frame || declarations.some(({ prop, value }) => prop === "box-shadow" && isInsetRing(value))
|
|
128
|
+
}
|
|
129
|
+
|
|
121
130
|
export function hasRadius(declarations: readonly Declaration[]): boolean {
|
|
122
131
|
return roundedCorners(declarations).size > 0
|
|
123
132
|
}
|
package/packages/shared-skills/skills/frontend/scripts/perfection/accent-stripes/findings.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type RuleId = "edge-stripe" | "pseudo-bar" | "inset-shadow-stripe" | "gradient-stripe"
|
|
1
|
+
export type RuleId = "edge-stripe" | "pseudo-bar" | "inset-shadow-stripe" | "gradient-stripe" | "accent-outline"
|
|
2
2
|
|
|
3
3
|
export type Finding = {
|
|
4
4
|
readonly file: string
|
|
@@ -9,14 +9,15 @@ export type Finding = {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const RULE_MESSAGES: Readonly<Record<RuleId, string>> = {
|
|
12
|
-
"edge-stripe": "coloured one-side border on a rounded
|
|
13
|
-
"pseudo-bar": "coloured ::before/::after bar
|
|
14
|
-
"inset-shadow-stripe": "inset box-shadow stripe
|
|
15
|
-
"gradient-stripe": "hard-stop gradient band along one edge of a
|
|
12
|
+
"edge-stripe": "coloured one-side border on a box, rounded or square",
|
|
13
|
+
"pseudo-bar": "coloured ::before/::after bar along one side of a box",
|
|
14
|
+
"inset-shadow-stripe": "inset box-shadow stripe along one side of a box",
|
|
15
|
+
"gradient-stripe": "hard-stop gradient band along one edge of a box",
|
|
16
|
+
"accent-outline": "accent-tinted full outline on a rounded card",
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export const FIX_HINT =
|
|
19
|
-
"drop the stripe: separate with a tonal surface (one ink at a low alpha), an eyebrow or heading, a leading glyph, or spacing"
|
|
20
|
+
"drop the stripe or outline: separate with a tonal surface (one ink at a low alpha), an eyebrow or heading, a leading glyph, or spacing"
|
|
20
21
|
|
|
21
22
|
export function lineLocator(text: string): (offset: number) => { line: number; column: number } {
|
|
22
23
|
const starts = [0]
|