@event4u/agent-config 14.18.0 → 14.20.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +120 -129
- package/README.md +71 -149
- package/dist/agent-src/README.md +1 -1
- package/dist/agent-src/commands/agent-handoff.md +44 -43
- package/dist/agent-src/commands/review/changes.md +19 -19
- package/dist/agent-src/commands/review.md +2 -2
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +37 -4
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/git-history-discipline.md +2 -2
- package/dist/agent-src/rules/guidelines.md +1 -1
- package/dist/agent-src/rules/session-canary.md +2 -2
- package/dist/agent-src/rules/token-efficiency.md +1 -1
- package/dist/agent-src/rules/untrusted-input-defense.md +0 -2
- package/dist/agent-src/skills/adversarial-review/SKILL.md +0 -8
- package/dist/agent-src/skills/canvas-design/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/data/app-interface.csv +1 -1
- package/dist/agent-src/skills/design-intelligence/data/motion.csv +17 -17
- package/dist/agent-src/skills/design-intelligence/data/ux-guidelines.csv +2 -2
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +17 -0
- package/dist/agent-src/skills/design-intelligence/references/design-rules-checklist.md +4 -4
- package/dist/agent-src/skills/design-review/SKILL.md +1 -1
- package/dist/agent-src/skills/design-variations/SKILL.md +1 -1
- package/dist/agent-src/skills/evaluate-llm-feature/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/SKILL.md +32 -5
- package/dist/agent-src/skills/fe-design/references/craft-floor.md +7 -0
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +47 -2
- package/dist/agent-src/skills/laravel-scheduling/SKILL.md +3 -1
- package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analyzer/SKILL.md +0 -6
- package/dist/agent-src/skills/react-native-setup/SKILL.md +3 -3
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/sequential-thinking/SKILL.md +18 -8
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +28 -6
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -3
- package/dist/agent-src/skills/ui-apply-generic/SKILL.md +1 -1
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +1 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +17 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +14 -1
- package/dist/agent-src/templates/scripts/telemetry/mcp_lite.ts +213 -0
- package/dist/agent-src/templates/scripts/telemetry/report_renderer.ts +16 -0
- package/dist/agent-src/templates/scripts/telemetry_report.ts +22 -2
- package/dist/cli/commands/recordTriggerEval.js +2 -2
- package/dist/cli/main.js +1 -1
- package/dist/cli/mcp/dispatch.js +10 -0
- package/dist/cli/mcp/stdio.js +33 -2
- package/dist/cli/mcp/telemetry.js +227 -0
- package/dist/cli-delegate/{chunk-AKJGUQNO.js → chunk-C6IPZRDA.js} +484 -353
- package/dist/cli-delegate/{chunk-CYH5SP6M.js → chunk-I6RHFQEG.js} +151 -16
- package/dist/cli-delegate/{chunk-7RXIKF62.js → chunk-NUMQHLS5.js} +304 -136
- package/dist/cli-delegate/{chunk-PMEKGDED.js → chunk-PI2GU3DP.js} +163 -1
- package/dist/cli-delegate/{chunk-7PRE6ZV2.js → chunk-YS6XTLEK.js} +199 -4
- package/dist/cli-delegate/chunk-ZVBOHSVF.js +1109 -0
- package/dist/cli-delegate/cmd_adr_effective.js +318 -81
- package/dist/cli-delegate/cmd_conformance.js +489 -121
- package/dist/cli-delegate/cmd_doctor.js +2 -2
- package/dist/cli-delegate/cmd_export.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +42 -12
- package/dist/cli-delegate/cmd_memory_get.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +2 -2
- package/dist/cli-delegate/cmd_route_audit.js +2 -2
- package/dist/cli-delegate/cmd_session_recycle.js +59 -902
- package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
- package/dist/cli-delegate/cmd_sync.js +2 -2
- package/dist/cli-delegate/cmd_uninstall.js +2 -2
- package/dist/cli-delegate/cmd_validate.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +34 -33
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +4455 -3025
- package/dist/install/install.mjs +975 -689
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +2087 -1134
- package/dist/scripts/_lib/model_tier.js +1 -1
- package/dist/scripts/mcp_server/telemetry.js +148 -0
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/naming.md +1 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/security-lint-containment.md +46 -6
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +4 -4
- package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +1 -1
- package/docs/guidelines/design-antipatterns.md +87 -64
- package/docs/guidelines/redundancy-taxonomy.md +28 -0
- package/package.json +1 -1
- package/src/agent-src/README.md +1 -1
- package/src/agent-src/templates/scripts/telemetry/mcp_lite.ts +213 -0
- package/src/agent-src/templates/scripts/telemetry/report_renderer.ts +16 -0
- package/src/agent-src/templates/scripts/telemetry_report.ts +22 -2
- package/src/config/assurance-capability-registry.json +9 -0
- package/src/config/ci-local-parity.yml +6 -0
- package/src/config/gate-coverage.yml +225 -0
- package/src/config/gate-violation-baselines.json +18 -6
- package/src/config/release-gate-locality.yml +12 -0
- package/src/scripts/_cli/cmd_doctor.ts +2 -2
- package/src/scripts/_cli/cmd_handoff.ts +1 -1
- package/src/scripts/_cli/cmd_session_recycle.ts +51 -3
- package/src/scripts/_cli/cmd_update.ts +1 -1
- package/src/scripts/_cli/cmd_versions.ts +1 -1
- package/src/scripts/_lib/adr_frontmatter.ts +44 -0
- package/src/scripts/_lib/audit_field_provenance.ts +44 -3
- package/src/scripts/_lib/consequence_objects.ts +152 -0
- package/src/scripts/_lib/exec_evidence.ts +7 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +2 -2
- package/src/scripts/_lib/host_capability.ts +38 -0
- package/src/scripts/_lib/host_permission_checks.ts +251 -0
- package/src/scripts/_lib/install_reach_checks.ts +33 -1
- package/src/scripts/_lib/mcp_bridge.ts +222 -10
- package/src/scripts/_lib/mcp_consent_residual.ts +173 -0
- package/src/scripts/_lib/model_tier.ts +1 -1
- package/src/scripts/_lib/obligation_frequency.ts +2 -2
- package/src/scripts/_lib/orchestration_record.ts +23 -1
- package/src/scripts/_lib/recycle_envelope_paths.ts +190 -0
- package/src/scripts/_lib/release_highlights.ts +93 -0
- package/src/scripts/_lib/release_material.ts +64 -1
- package/src/scripts/_lib/release_position.ts +96 -0
- package/src/scripts/_lib/review_skipped_record.ts +17 -1
- package/src/scripts/_lib/runtime_journal.ts +26 -3
- package/src/scripts/_lib/runtime_wiring_checks.ts +12 -1
- package/src/scripts/_lib/security_lint.ts +179 -7
- package/src/scripts/_lib/self_repair.ts +141 -6
- package/src/scripts/_lib/self_repair_store.ts +273 -7
- package/src/scripts/_lib/session_register.ts +11 -6
- package/src/scripts/_lib/sqlite_schema.ts +22 -0
- package/src/scripts/_lib/subagent_capsule.ts +155 -3
- package/src/scripts/_lib/surface.ts +86 -0
- package/src/scripts/_lib/ui_authority.ts +116 -0
- package/src/scripts/adr/regenerate_index.ts +54 -1
- package/src/scripts/adr_cite_check.ts +71 -15
- package/src/scripts/ai_council/clients.ts +1 -1
- package/src/scripts/autonomy_friction_corpus.ts +229 -0
- package/src/scripts/build_proof.ts +15 -2
- package/src/scripts/build_rule_trigger_matrix.ts +5 -0
- package/src/scripts/check_beta_review_markers.ts +141 -17
- package/src/scripts/check_enforcement_coverage.ts +1 -1
- package/src/scripts/check_enforcement_denominator.ts +121 -11
- package/src/scripts/check_finding_dispositions.ts +66 -9
- package/src/scripts/check_gate_coverage.ts +96 -0
- package/src/scripts/check_mcp_doc_drift.ts +217 -0
- package/src/scripts/check_pack_size.ts +321 -3
- package/src/scripts/check_release_highlights.ts +74 -1
- package/src/scripts/check_skill_activation_claim.ts +179 -0
- package/src/scripts/check_trigger_evals.ts +1 -1
- package/src/scripts/conformance_scan.ts +44 -3
- package/src/scripts/explain_run.ts +1 -1
- package/src/scripts/generate_capability_matrix.ts +1 -1
- package/src/scripts/git_authorization_hook.ts +75 -1
- package/src/scripts/handoff_context_hook.ts +54 -7
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +14 -11
- package/src/scripts/hooks/augment-dispatcher.sh +1 -1
- package/src/scripts/hooks/category_a.ts +291 -0
- package/src/scripts/hooks/cline-dispatcher.sh +1 -1
- package/src/scripts/hooks/cursor-dispatcher.sh +11 -5
- package/src/scripts/hooks/dispatch_hook.ts +17 -22
- package/src/scripts/hooks/git_command_classifier.ts +156 -1
- package/src/scripts/hooks/host_lowering.ts +215 -0
- package/src/scripts/hooks/host_lowering.yaml +185 -0
- package/src/scripts/hooks/host_semantics.ts +105 -37
- package/src/scripts/hooks/journal_record_hook.ts +10 -0
- package/src/scripts/hooks/permission_gate.ts +117 -0
- package/src/scripts/hooks/session_eol_hook.ts +18 -7
- package/src/scripts/hooks_status.ts +12 -10
- package/src/scripts/install.ts +57 -86
- package/src/scripts/install_anthropic_key.sh +2 -2
- package/src/scripts/lint_agent_security.ts +316 -25
- package/src/scripts/lint_confusables.ts +42 -6
- package/src/scripts/lint_design_antipattern_parity.ts +80 -0
- package/src/scripts/lint_evidence_artifacts.ts +45 -1
- package/src/scripts/lint_handoffs.ts +0 -132
- package/src/scripts/lint_hidden_unicode.ts +49 -7
- package/src/scripts/lint_hook_manifest.ts +87 -3
- package/src/scripts/lint_instruction_smuggling.ts +42 -6
- package/src/scripts/lint_mcp_config_security.ts +42 -6
- package/src/scripts/lint_motion_authority_drift.ts +731 -0
- package/src/scripts/lint_readme_size.ts +158 -12
- package/src/scripts/lint_reasoning_fixtures.ts +216 -0
- package/src/scripts/lint_roadmap_later_disposition.ts +217 -27
- package/src/scripts/lint_skill_frontmatter_safety.ts +43 -7
- package/src/scripts/lint_skill_trigger_contradiction.ts +161 -0
- package/src/scripts/mcp_server/resources.ts +41 -0
- package/src/scripts/mcp_server/telemetry.ts +19 -4
- package/src/scripts/measure_sibling_naming.ts +150 -0
- package/src/scripts/orchestration_record.ts +12 -1
- package/src/scripts/redact_hook_capture.ts +1 -1
- package/src/scripts/release.ts +24 -24
- package/src/scripts/release_publication.ts +6 -2
- package/src/scripts/report_skill_activation.ts +319 -7
- package/src/scripts/schemas/review-findings.schema.json +5 -0
- package/src/scripts/schemas/skill.schema.json +2 -2
- package/src/scripts/self_repair_cli.ts +31 -1
- package/src/scripts/session_canary_hook.ts +1 -1
- package/src/scripts/session_register_hook.ts +4 -3
- package/src/scripts/skill_scout.ts +69 -0
- package/src/scripts/trigger_eval_grandfather.json +5 -1
- package/src/scripts/validate_agent_settings.ts +1 -1
- package/dist/cli-delegate/chunk-2GNWGMAL.js +0 -172
- package/dist/cli-delegate/chunk-LPPWO5CE.js +0 -161
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* - the repo generator (`condense.py generate_claude_skills`), which
|
|
12
12
|
* builds the package's own `.claude/skills/` tree, and
|
|
13
13
|
* - the consumer install finalizer
|
|
14
|
-
* (`
|
|
14
|
+
* (the installer's `finalize_claude_model_tiers`), which rewrites the
|
|
15
15
|
* installed `.claude/skills/` tree so Claude Code performs the
|
|
16
16
|
* per-turn model switch on a consumer with `model.auto_switch: auto`.
|
|
17
17
|
*
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// MCP telemetry sink — Phase 1 J4 instrumentation.
|
|
2
|
+
//
|
|
3
|
+
// Per `agents/roadmaps/archive/road-to-mcp-full-coverage.md` §Phase 1 J4 +
|
|
4
|
+
// `docs/contracts/mcp-tool-stub-envelope.md`, both transports log every
|
|
5
|
+
// `tools/call` with `{tool_name, client_id_hash, ts, transport,
|
|
6
|
+
// outcome}`. The stdio-lite surface (`src/cli/mcp/`) appends a sixth,
|
|
7
|
+
// optional `host` field; callers that do not know their client omit it and
|
|
8
|
+
// their records stay byte-identical to the frozen five-field envelope. Payload bodies are never logged; the client identifier is
|
|
9
|
+
// hashed at the server boundary so the queryable store never sees raw
|
|
10
|
+
// identity.
|
|
11
|
+
//
|
|
12
|
+
// Outcomes:
|
|
13
|
+
//
|
|
14
|
+
// - `implemented` — real handler ran (no envelope returned).
|
|
15
|
+
// - `stub` — catalog entry missing this transport; `not_implemented`
|
|
16
|
+
// envelope returned.
|
|
17
|
+
// - `latent_demand` — caller asked for a tool not in the catalog.
|
|
18
|
+
//
|
|
19
|
+
// The sink writes JSONL to `agents/runtime/mcp-telemetry/calls.jsonl` under the
|
|
20
|
+
// consumer root. Failure to write must not break the wire surface: the
|
|
21
|
+
// `record_call` helper swallows OSError + ValueError and emits a single
|
|
22
|
+
// warning to stderr.
|
|
23
|
+
//
|
|
24
|
+
// TS port of the retired Python telemetry.py (ADR-200). Preserves the full public surface:
|
|
25
|
+
// - Outcome type, TELEMETRY_REL_DIR, TELEMETRY_FILENAME, hash_client_id,
|
|
26
|
+
// build_record, record_call.
|
|
27
|
+
import * as crypto from 'node:crypto';
|
|
28
|
+
import * as fs from 'node:fs';
|
|
29
|
+
import * as os from 'node:os';
|
|
30
|
+
import * as path from 'node:path';
|
|
31
|
+
// Stable file location relative to consumer_root. Phase 2 K1 routes
|
|
32
|
+
// this into a queryable store; Phase 1 only needs the file to exist.
|
|
33
|
+
export const TELEMETRY_REL_DIR = 'agents/runtime/mcp-telemetry';
|
|
34
|
+
export const TELEMETRY_FILENAME = 'calls.jsonl';
|
|
35
|
+
// Truncation length for the client_id hash. 12 hex chars = 48 bits of
|
|
36
|
+
// entropy — enough to distinguish hundreds of consumers without
|
|
37
|
+
// becoming a re-identification vector.
|
|
38
|
+
const _HASH_LEN = 12;
|
|
39
|
+
/**
|
|
40
|
+
* Identity components that together pin a consumer install.
|
|
41
|
+
*
|
|
42
|
+
* USER + machine hostname + repo path is a stable triple that survives
|
|
43
|
+
* sessions without leaking PII into the log. The hash never reverses.
|
|
44
|
+
*/
|
|
45
|
+
function _client_id_seed() {
|
|
46
|
+
const user = process.env.USER || process.env.USERNAME || 'unknown';
|
|
47
|
+
let host = process.env.HOSTNAME;
|
|
48
|
+
if (!host) {
|
|
49
|
+
// Mirrors Python `os.uname().nodename` (POSIX) — Node exposes
|
|
50
|
+
// `os.hostname()`. Guarded so an empty value falls through to "unknown".
|
|
51
|
+
try {
|
|
52
|
+
host = os.hostname();
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
host = undefined;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
host = host || 'unknown';
|
|
59
|
+
const cwd = _resolvePath(process.cwd());
|
|
60
|
+
return `${user}|${host}|${cwd}`;
|
|
61
|
+
}
|
|
62
|
+
/** SHA-256(seed) truncated to 12 hex chars. Boundary-only call. */
|
|
63
|
+
export function hash_client_id(seed) {
|
|
64
|
+
const raw = seed !== undefined ? seed : _client_id_seed();
|
|
65
|
+
const digest = crypto.createHash('sha256').update(Buffer.from(raw, 'utf-8')).digest('hex');
|
|
66
|
+
return digest.slice(0, _HASH_LEN);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve a path like Python `Path(...).resolve()` — absolutize + realpath
|
|
70
|
+
* the existing prefix, tolerating a non-existent tail (Python resolve does
|
|
71
|
+
* not require the path to exist; `fs.realpathSync` does, so fall back to a
|
|
72
|
+
* plain absolute path on ENOENT).
|
|
73
|
+
*/
|
|
74
|
+
function _resolvePath(p) {
|
|
75
|
+
try {
|
|
76
|
+
return fs.realpathSync(p);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return path.resolve(p);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Pick the JSONL location. Defaults to CWD when no override given. */
|
|
83
|
+
function _resolve_log_path(consumer_root) {
|
|
84
|
+
const root = _resolvePath(consumer_root ?? process.cwd());
|
|
85
|
+
return path.join(root, TELEMETRY_REL_DIR, TELEMETRY_FILENAME);
|
|
86
|
+
}
|
|
87
|
+
/** ISO-8601 UTC timestamp, seconds precision. */
|
|
88
|
+
function _now_iso() {
|
|
89
|
+
// Mirrors Python `time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())`.
|
|
90
|
+
return new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Pure helper — assemble the record without touching the filesystem.
|
|
94
|
+
*
|
|
95
|
+
* Field insertion order matches the Python dict literal so the
|
|
96
|
+
* compact-JSON serialization is byte-identical.
|
|
97
|
+
*/
|
|
98
|
+
export function build_record(options) {
|
|
99
|
+
const { tool_name, outcome, transport, client_id_hash_value, ts, host } = options;
|
|
100
|
+
const record = {
|
|
101
|
+
tool_name,
|
|
102
|
+
client_id_hash: client_id_hash_value || hash_client_id(),
|
|
103
|
+
ts: ts || _now_iso(),
|
|
104
|
+
transport,
|
|
105
|
+
outcome,
|
|
106
|
+
};
|
|
107
|
+
// `host` is APPENDED, and only when a caller supplies one, so a record
|
|
108
|
+
// written by a caller that does not know its client stays byte-identical
|
|
109
|
+
// to the five-field envelope the stub contract froze. It is a closed
|
|
110
|
+
// vocabulary resolved at the boundary (see `src/cli/mcp/telemetry.ts`),
|
|
111
|
+
// never a free-form string: a record type that cannot hold arbitrary text
|
|
112
|
+
// has no scrubber to fail.
|
|
113
|
+
if (typeof host === 'string' && host !== '') {
|
|
114
|
+
record.host = host;
|
|
115
|
+
}
|
|
116
|
+
return record;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Append one JSONL record. Returns the record or null on failure.
|
|
120
|
+
*
|
|
121
|
+
* Failures are swallowed: telemetry must never break the wire surface.
|
|
122
|
+
* A single `mcp-server: warn: telemetry` line is emitted to stderr
|
|
123
|
+
* so silent-failure windows show up in the boot log and the J6
|
|
124
|
+
* healthcheck can detect them.
|
|
125
|
+
*/
|
|
126
|
+
export function record_call(options) {
|
|
127
|
+
const { tool_name, outcome, transport, consumer_root, client_id_hash_value, host } = options;
|
|
128
|
+
const record = build_record({
|
|
129
|
+
tool_name,
|
|
130
|
+
outcome,
|
|
131
|
+
transport,
|
|
132
|
+
client_id_hash_value,
|
|
133
|
+
host,
|
|
134
|
+
});
|
|
135
|
+
const target = _resolve_log_path(consumer_root ?? undefined);
|
|
136
|
+
try {
|
|
137
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
138
|
+
// json.dumps(record, separators=(",", ":")) — compact, no spaces.
|
|
139
|
+
fs.appendFileSync(target, JSON.stringify(record) + '\n', { encoding: 'utf-8' });
|
|
140
|
+
}
|
|
141
|
+
catch (exc) {
|
|
142
|
+
const message = exc instanceof Error ? exc.message : String(exc);
|
|
143
|
+
process.stderr.write(`mcp-server: warn: telemetry write failed: ${message}\n`);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return record;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -51,7 +51,7 @@ drew.** It said `pre_tool_use` "exists on three hosts" and that the guard has
|
|
|
51
51
|
tree. **Downward:** the manifest's own `native_event_aliases` table already maps
|
|
52
52
|
`preToolUse` (cursor), `PreToolUse` (cline) and `BeforeTool` (gemini) onto
|
|
53
53
|
`pre_tool_use`, so there the guard is **unbound, not unbindable**; only windsurf
|
|
54
|
-
and copilot carry no pre-tool
|
|
54
|
+
and copilot carry no pre-tool alias row at all. **Upward, and worse:**
|
|
55
55
|
`host_semantics.ts` certifies **claude alone**, and the augment and cowork
|
|
56
56
|
trampolines discard dispatcher output and `exit 0` unconditionally — so on two
|
|
57
57
|
of the three "enforcing" hosts this guard runs and is then ignored. Nor may the
|
|
@@ -34,7 +34,7 @@ source: package
|
|
|
34
34
|
|---|---|---|
|
|
35
35
|
| `{concern}` | Behavioral constraint | `scope-control`, `ask-when-uncertain` |
|
|
36
36
|
| `{domain}-{concern}` | Domain-specific rule | `php-coding`, `e2e-testing` |
|
|
37
|
-
| `{action}-{target}` | Trigger-based auto rule | `
|
|
37
|
+
| `{action}-{target}` | Trigger-based auto rule | `invite-challenge`, `downstream-changes` |
|
|
38
38
|
|
|
39
39
|
### Commands
|
|
40
40
|
|
|
@@ -19,7 +19,7 @@ _Origin: migrated from `.agent-src.uncondensed/rules/roadmap-progress-sync.md` p
|
|
|
19
19
|
> stale dashboard even if local hooks were bypassed.
|
|
20
20
|
>
|
|
21
21
|
> Hook is primary; the prose below is the specification the hook
|
|
22
|
-
> implements and the fallback
|
|
22
|
+
> implements and the fallback where no hook is bound on the platform.
|
|
23
23
|
|
|
24
24
|
## Iron Law — dashboard sync
|
|
25
25
|
|
|
@@ -45,18 +45,51 @@ are *expected* to contain illustrative patterns. Only a full-weight (1.0×)
|
|
|
45
45
|
**HIGH** finding in a real artifact fails the build. (`is_example_path()` in the
|
|
46
46
|
shared lib defines the path set.)
|
|
47
47
|
|
|
48
|
-
### 3.
|
|
48
|
+
### 3. Bound pragma
|
|
49
49
|
|
|
50
|
-
A single check can be suppressed for one file with an
|
|
51
|
-
marker placed anywhere in the file:
|
|
50
|
+
A single check can be suppressed for **specific evidence** in one file with an
|
|
51
|
+
auditable, reasoned, content-bound marker placed anywhere in the file:
|
|
52
52
|
|
|
53
53
|
```
|
|
54
|
-
<!-- security-lint: allow instruction-smuggling "teaching example: quotes a prompt-injection string" -->
|
|
54
|
+
<!-- security-lint: allow instruction-smuggling "teaching example: quotes a prompt-injection string" sha256:<hex> -->
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
- The `<check>` token is the linter's check id (`hidden-unicode`,
|
|
58
|
-
`instruction-smuggling`, `mcp-config-security`,
|
|
58
|
+
`mixed-script-confusable`, `instruction-smuggling`, `mcp-config-security`,
|
|
59
|
+
`dangerous-frontmatter`).
|
|
59
60
|
- The `"<reason>"` is **mandatory** — an empty reason does not parse.
|
|
61
|
+
- Each `sha256:<hex>` **binds the suppression to one accepted match**. Repeat the
|
|
62
|
+
token once per accepted match; a file with three accepted matches carries three
|
|
63
|
+
hashes. Anything the check finds that is not in that set is still reported.
|
|
64
|
+
- The fingerprint covers the **check id**, the artifact's **source identity**, and
|
|
65
|
+
the **normalized text of the matched line** — ASCII whitespace runs collapse so
|
|
66
|
+
a reflow does not break the binding, and nothing else is stripped, because the
|
|
67
|
+
zero-width characters this suite hunts are exactly what a wider normalizer
|
|
68
|
+
would erase. It is deliberately NOT the line number (an unrelated insert above
|
|
69
|
+
would break every pragma in the file) and NOT the whole file (every unrelated
|
|
70
|
+
edit would re-fire it, which is how blanket suppressions get written).
|
|
71
|
+
A `dist/agent-src/` path folds to its `src/` original first: the projection is
|
|
72
|
+
byte-exact by contract, so an artifact and its copy are one identity.
|
|
73
|
+
- **A pair pinned equal by a parity test carries ONE HASH PER IDENTITY.** The
|
|
74
|
+
fold above covers `dist/agent-src/` and nothing else, so where a second
|
|
75
|
+
hand-maintained copy exists and a test asserts the two are byte-identical —
|
|
76
|
+
`src/subagents/<stem>.md` and `docs/wedge/<stem>/<stem>.md`, pinned by
|
|
77
|
+
`tests/scripts/subagent_distribution.test.ts` — one hash cannot satisfy both:
|
|
78
|
+
giving each file its own makes the lines differ and reds the parity test,
|
|
79
|
+
which is exactly how this was found. Put BOTH hashes in BOTH files. That is
|
|
80
|
+
what the repeatable token is for, and it is why the grammar has one. A purely
|
|
81
|
+
GENERATED third copy (`.claude/agents/<stem>.md`) needs no hash of its own:
|
|
82
|
+
nothing scans it and nobody edits it, so binding it would be a fingerprint
|
|
83
|
+
for an identity no finding can arise at.
|
|
84
|
+
- Compute one with the linter itself, never by hand — a hash typed from memory
|
|
85
|
+
is a suppression nobody audited.
|
|
86
|
+
|
|
87
|
+
**The unbound form still parses**, suppresses the whole file as it always did,
|
|
88
|
+
and reports itself as a `legacy-pragma` LOW finding. That is a migration signal,
|
|
89
|
+
not a mode to choose: a key lookup with no content binding accepts whatever the
|
|
90
|
+
matched text is later changed to say, which is the defect the hash exists to
|
|
91
|
+
close. There are zero unbound pragmas in the tree.
|
|
92
|
+
|
|
60
93
|
- Pragmas are **counted and capped**: crossing **20** across the repo means the
|
|
61
94
|
linter is mis-scoped. Stop adding pragmas; redesign or narrow the check
|
|
62
95
|
(escalate per `autonomous-execution` — the allowlist-growth antipattern).
|
|
@@ -72,7 +105,14 @@ marker placed anywhere in the file:
|
|
|
72
105
|
|
|
73
106
|
`security-example` fence → confidence weight → pragma. A HIGH finding survives
|
|
74
107
|
to fail the build only when it is full-weight (not in an example path), not
|
|
75
|
-
inside a `security-example` fence, and not covered by a
|
|
108
|
+
inside a `security-example` fence, and not covered by a pragma whose fingerprint
|
|
109
|
+
set contains that match.
|
|
110
|
+
|
|
111
|
+
One consumer deliberately departs from the weighting rung: `skill_scout`'s
|
|
112
|
+
`security_licence` gate refuses a quarantined candidate on **any** HIGH finding,
|
|
113
|
+
whatever its weight. Path-based confidence is a false-positive containment device
|
|
114
|
+
for a corpus whose provenance is known; a third-party candidate has none, and a
|
|
115
|
+
directory named `examples/` in it is the submitter's word for it.
|
|
76
116
|
|
|
77
117
|
## See also
|
|
78
118
|
|
|
@@ -4,10 +4,10 @@ Five-stage flow that turns real project experience into reviewed
|
|
|
4
4
|
rule / skill / command / guideline changes. No autonomous self-edits;
|
|
5
5
|
every upstream change ships via a human-reviewed PR.
|
|
6
6
|
|
|
7
|
-
Referenced by `road-to-curated-self-improvement.md`. Consumed by the
|
|
8
|
-
|
|
9
|
-
`skill-improvement-pipeline`, and
|
|
10
|
-
a stage, not a standalone invocation.
|
|
7
|
+
Referenced by `road-to-curated-self-improvement.md`. Consumed by the live
|
|
8
|
+
artifacts — the `skill-improvement-trigger` rule and the existing skills
|
|
9
|
+
`learning-to-rule-or-skill`, `skill-improvement-pipeline`, and
|
|
10
|
+
`upstream-contribute` — each becomes a stage, not a standalone invocation.
|
|
11
11
|
|
|
12
12
|
## The five stages
|
|
13
13
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- security-lint: allow instruction-smuggling "defense guideline: quotes role-takeover phrases (ignore previous instructions, you are now, <IMPORTANT>) to teach refusal" -->
|
|
1
|
+
<!-- security-lint: allow instruction-smuggling "defense guideline: quotes role-takeover phrases (ignore previous instructions, you are now, <IMPORTANT>) to teach refusal" sha256:d84759534e0fd3ebc5a66533b4a9f52364ef5286eaf3674a611c9c2adf89b969 sha256:f08c68182232149c7ecd881e88ca81dc98a9313c06ba6d010b065f9feef2c149 sha256:4f5936bb0a57de8ff3ce590fb12607cdcb046a31262b5e4d40377c6e6184f494 -->
|
|
2
2
|
|
|
3
3
|
# untrusted-input spotlighting + least-agency mapping
|
|
4
4
|
|
|
@@ -68,105 +68,128 @@ generation ships a visibly different default aesthetic. It is a *when-does-it-
|
|
|
68
68
|
rotate* note, not a new pattern — never add a tell here that lacks a catalog
|
|
69
69
|
entry in the sections below.
|
|
70
70
|
|
|
71
|
+
### The three census columns — class, remediation, verification
|
|
72
|
+
|
|
73
|
+
`Class` says what KIND of rule an entry is; **status** (§ Detector status) says
|
|
74
|
+
how its enforcement is wired. The two axes are independent, and a reader who
|
|
75
|
+
conflates them draws the wrong conclusion in both directions: a `floor` may be
|
|
76
|
+
`judgment-only` because nothing can detect it yet, and a `style-preference` may
|
|
77
|
+
be `backed` because it happens to be trivially greppable. Detectability is not
|
|
78
|
+
authority.
|
|
79
|
+
|
|
80
|
+
- **Class** — one of `floor` (an objective threshold, accessibility or
|
|
81
|
+
correctness) · `invariant` (a structural rule that must hold) ·
|
|
82
|
+
`craft-presumption` (a default a competent designer usually follows,
|
|
83
|
+
overridable on evidence) · `style-preference` (taste) ·
|
|
84
|
+
`reference-constraint` (bound to a supplied reference, brand, or `DESIGN.md`).
|
|
85
|
+
The two soft classes lose to a supplied reference artifact, a coherent
|
|
86
|
+
incumbent, and a project `DESIGN.md` — asserted on the resolver in
|
|
87
|
+
`src/scripts/_lib/ui_authority.ts` rather than stated here as prose.
|
|
88
|
+
- **Remediation** — the order to try, worst-first: `delete` before `reduce`
|
|
89
|
+
before `retune`, with `replace` where the pattern has a direct substitute.
|
|
90
|
+
- **Verification** — how a fix is checked: `static` (readable from the source)
|
|
91
|
+
· `render` (needs the rendered surface) · `feel` (perceptual, per the `feel`
|
|
92
|
+
evidence type in `docs/contracts/evidence-artifact-types.md`) · `judgment`.
|
|
93
|
+
|
|
71
94
|
### Consistency Locks & layout caps (taste-dials roadmap)
|
|
72
95
|
|
|
73
96
|
Within-project invariants + repetition caps. Override = declare the value in
|
|
74
97
|
`DESIGN.md` (`## Consistency Locks` / a brutalist or uniform-grid style note).
|
|
75
98
|
|
|
76
|
-
| # | Pattern | Why it reads as AI-generated | Override condition |
|
|
77
|
-
|
|
78
|
-
| V8 | Shape Lock — ≥ 4 distinct corner-radius scales in one surface | A fragmented radius system reads as no shape decision | Declare the radius scale in `DESIGN.md`; a genuine multi-tier scale documents each tier |
|
|
79
|
-
| C6 | Colour Lock — ≥ 3 distinct saturated accent hue families | No single accent identity; reads as default-palette sprawl | Brand genuinely uses a multi-accent system, declared in `DESIGN.md` / `brand-to-tokens` |
|
|
80
|
-
| C7 | Theme inversion — a light island mid-dark surface (or vice versa) not driven by the theme system | Mid-surface inversion breaks the theme rhythm | Intentional inverted callout with a documented reason — **judgment-only**, design-review calls it (deterministic detection is unreliable) |
|
|
81
|
-
| L9 | Section monotony — ≥ 8 sections, < 4 distinct layout families | Uniform section rhythm collapses scannability | Deliberately uniform grid (e.g. a gallery), declared as such |
|
|
82
|
-
| L10 | Zigzag — > 2 consecutive image-left/text-right two-column sections | The alternating-zigzag landing-page tell | A genuinely sequenced walkthrough where alternation aids comprehension |
|
|
99
|
+
| # | Pattern | Why it reads as AI-generated | Override condition | Class | Remediation | Verification |
|
|
100
|
+
|---|---|---|---|---|---|---|
|
|
101
|
+
| V8 | Shape Lock — ≥ 4 distinct corner-radius scales in one surface | A fragmented radius system reads as no shape decision | Declare the radius scale in `DESIGN.md`; a genuine multi-tier scale documents each tier | invariant | reduce → retune | static |
|
|
102
|
+
| C6 | Colour Lock — ≥ 3 distinct saturated accent hue families | No single accent identity; reads as default-palette sprawl | Brand genuinely uses a multi-accent system, declared in `DESIGN.md` / `brand-to-tokens` | invariant | reduce → retune | static |
|
|
103
|
+
| C7 | Theme inversion — a light island mid-dark surface (or vice versa) not driven by the theme system | Mid-surface inversion breaks the theme rhythm | Intentional inverted callout with a documented reason — **judgment-only**, design-review calls it (deterministic detection is unreliable) | craft-presumption | delete → retune | judgment |
|
|
104
|
+
| L9 | Section monotony — ≥ 8 sections, < 4 distinct layout families | Uniform section rhythm collapses scannability | Deliberately uniform grid (e.g. a gallery), declared as such | craft-presumption | retune | render |
|
|
105
|
+
| L10 | Zigzag — > 2 consecutive image-left/text-right two-column sections | The alternating-zigzag landing-page tell | A genuinely sequenced walkthrough where alternation aids comprehension | craft-presumption | delete → retune | static |
|
|
83
106
|
|
|
84
107
|
---
|
|
85
108
|
|
|
86
109
|
## Visual
|
|
87
110
|
|
|
88
|
-
| # | Pattern | Why it reads as AI-generated | Override condition |
|
|
89
|
-
|
|
90
|
-
| V1 | A colored accent border above 1px — the side stripe (`border-left` / `border-right`), a fully colored border on all four sides, or a gradient `border-image` | The single most recognizable AI-UI signature; every scaffold-default card uses it. Widened 2026-09-03: the side stripe was the 2024 form, the four-sided colored or gradient card border is the current one, and the entry as written reached only the first | Brand token explicitly defines the accent border; document the decision in the design brief. A 1px neutral border, a `border-color`-only focus treatment, and `transparent` / `currentColor` at any width are not accents and do not flag |
|
|
91
|
-
| V2 | Glassmorphism as decoration (`backdrop-blur` + `bg-white/10`) with no functional depth hierarchy | Model defaults to it for "premium feel"; result looks like 2021 Material You clip-art | Element genuinely sits above a complex, blurred background layer; use sparingly and only for top-level floating surfaces |
|
|
92
|
-
| V3 | Ghost card: `border: 1px solid` + box-shadow ≥ 16px spread together | The combination creates visual noise — the ghost card signals no confident decision about depth | Choose either border OR shadow to indicate depth; never both on the same surface |
|
|
93
|
-
| V4 | Over-rounded small cards or badges: `border-radius` > 16px on elements < 200px wide | Excessive rounding on small surfaces looks toy-ish; standard cap is 12–16px | Pill shape (`border-radius: 9999px`) is intentional on single-line tags/chips only |
|
|
94
|
-
| V5 | Hand-drawn or illustrated SVG icons mixed with crisp icon-system icons | Visual register collision; instantly reads as "generated asset" | Intentional illustrative section (hero illustration, empty-state art); isolate from the icon system |
|
|
95
|
-
| V6 | Repeating diagonal stripes as a background texture | A cliché background default; reads as generated CSS art | Brand explicitly uses pattern backgrounds (e.g., a textile brand); document the stripe definition |
|
|
96
|
-
| V7 | Nested cards: a card inside a card inside a card | Depth hierarchy collapses; user cannot parse elevation intent | A truly three-level hierarchy (e.g., project → board → card); ensure each level has distinct visual weight |
|
|
97
|
-
| V9 | Noise or grain texture laid over a gradient as a "premium" surface default | The visual sibling of V6's diagonal stripes — a generated-CSS-art texture reached for to make a flat gradient look considered, applied because it is available rather than because the surface needed a texture | The texture is part of a documented brand surface treatment (a print-inspired or analog-photographic identity) with the grain opacity defined as a token, not chosen per surface |
|
|
111
|
+
| # | Pattern | Why it reads as AI-generated | Override condition | Class | Remediation | Verification |
|
|
112
|
+
|---|---|---|---|---|---|---|
|
|
113
|
+
| V1 | A colored accent border above 1px — the side stripe (`border-left` / `border-right`), a fully colored border on all four sides, or a gradient `border-image` | The single most recognizable AI-UI signature; every scaffold-default card uses it. Widened 2026-09-03: the side stripe was the 2024 form, the four-sided colored or gradient card border is the current one, and the entry as written reached only the first | Brand token explicitly defines the accent border; document the decision in the design brief. A 1px neutral border, a `border-color`-only focus treatment, and `transparent` / `currentColor` at any width are not accents and do not flag | craft-presumption | delete → retune | static |
|
|
114
|
+
| V2 | Glassmorphism as decoration (`backdrop-blur` + `bg-white/10`) with no functional depth hierarchy | Model defaults to it for "premium feel"; result looks like 2021 Material You clip-art | Element genuinely sits above a complex, blurred background layer; use sparingly and only for top-level floating surfaces | craft-presumption | delete → reduce | static |
|
|
115
|
+
| V3 | Ghost card: `border: 1px solid` + box-shadow ≥ 16px spread together | The combination creates visual noise — the ghost card signals no confident decision about depth | Choose either border OR shadow to indicate depth; never both on the same surface | invariant | delete → reduce | static |
|
|
116
|
+
| V4 | Over-rounded small cards or badges: `border-radius` > 16px on elements < 200px wide | Excessive rounding on small surfaces looks toy-ish; standard cap is 12–16px | Pill shape (`border-radius: 9999px`) is intentional on single-line tags/chips only | craft-presumption | retune | static |
|
|
117
|
+
| V5 | Hand-drawn or illustrated SVG icons mixed with crisp icon-system icons | Visual register collision; instantly reads as "generated asset" | Intentional illustrative section (hero illustration, empty-state art); isolate from the icon system | invariant | replace | render |
|
|
118
|
+
| V6 | Repeating diagonal stripes as a background texture | A cliché background default; reads as generated CSS art | Brand explicitly uses pattern backgrounds (e.g., a textile brand); document the stripe definition | style-preference | delete | static |
|
|
119
|
+
| V7 | Nested cards: a card inside a card inside a card | Depth hierarchy collapses; user cannot parse elevation intent | A truly three-level hierarchy (e.g., project → board → card); ensure each level has distinct visual weight | invariant | delete → reduce | render |
|
|
120
|
+
| V9 | Noise or grain texture laid over a gradient as a "premium" surface default | The visual sibling of V6's diagonal stripes — a generated-CSS-art texture reached for to make a flat gradient look considered, applied because it is available rather than because the surface needed a texture | The texture is part of a documented brand surface treatment (a print-inspired or analog-photographic identity) with the grain opacity defined as a token, not chosen per surface | style-preference | delete | render |
|
|
98
121
|
|
|
99
122
|
---
|
|
100
123
|
|
|
101
124
|
## Typography
|
|
102
125
|
|
|
103
|
-
| # | Pattern | Why it reads as AI-generated | Override condition |
|
|
104
|
-
|
|
105
|
-
| T1 | Flat type hierarchy: body and headings use the same optical weight and nearly the same size | Type hierarchy is invisible; user cannot scan the page | Deliberately minimal aesthetic where all text is body-weight; must be an explicit brand decision |
|
|
106
|
-
| T2 | Oversized italic serif as the primary hero headline | The "AI startup landing page" template; seen on ~60% of AI-generated marketing pages | Brand adopts editorial-magazine aesthetic with a documented italic serif rationale |
|
|
107
|
-
| T3 | Icon tile (small rounded-square container) above heading | The universal AI feature-card template; reads as scaffold | Listed features genuinely benefit from visual-icon-then-title affordance AND the icons are custom, not library defaults |
|
|
108
|
-
| T4 | Eyebrow / ALL-CAPS label above every section heading | Overuse collapses the emphasis; maximum is 1 eyebrow per 3 sections (countable: grep tracking classes) | Used for genuine section-type differentiation with meaningful vocabulary (not just "FEATURES", "PRICING") |
|
|
109
|
-
| T5 | Repeated section kickers ("Our mission", "What we offer", "Why choose us") | Filler vocabulary; every AI-generated page has the same three section titles | Every kicker is substantive and uses brand-specific vocabulary, not generic marketing speak |
|
|
110
|
-
| T6 | Crushed letter-spacing on display text (`letter-spacing` < −0.04em) | Below −0.04em glyphs collide optically; reads as "designer-ish effect" with no grounding | Intentional tight display treatment with a documented minimum floor; verify at the actual render size |
|
|
111
|
-
| T7 | Overused fonts without a stated reason: Inter, Roboto, DM Sans, Geist, Space Grotesk, Instrument Serif | These are the default AI-coding-tool font picks; every generated UI uses one of them | **Register-scoped.** In the **brand** register: the brand has explicitly adopted one of these AND there is a documented reason. In the **product** register: a single reliable family is the sanctioned strategy ([`design-modes`](design-modes.md) § The two registers), so one of these is legitimate on a **stated** product-register choice — the register itself is the reason, and it must be stated (DESIGN.md, the surface brief, or `design-slop-disable`). Neither register admits an *undeclared* pick. |
|
|
112
|
-
| T8 | Single typeface for everything | Missed typographic contrast opportunity; in the **brand** register an unexamined single family reads as "I did not think about fonts" | **Register-scoped like T7.** Intentional mono-typeface aesthetic (e.g., terminal-inspired), stated in the brief — *or* the **product** register, where one reliable family is the sanctioned strategy ([`design-modes`](design-modes.md) § The two registers) and contrast is carried by weight and scale rather than by a second family. |
|
|
113
|
-
| T9 | All-caps body paragraphs or field labels | Reduces legibility below WCAG AA for sustained reading; reads as flair over function | Short UI labels (e.g., button text in a brutalist layout); never for body paragraphs |
|
|
114
|
-
| T10 | Wide letter-spacing on body text (`letter-spacing` > 0.05em) | Reduces readability for sustained reading; reserved for display use | Display text (headlines, pull quotes) where intentional tracking is a brand element |
|
|
126
|
+
| # | Pattern | Why it reads as AI-generated | Override condition | Class | Remediation | Verification |
|
|
127
|
+
|---|---|---|---|---|---|---|
|
|
128
|
+
| T1 | Flat type hierarchy: body and headings use the same optical weight and nearly the same size | Type hierarchy is invisible; user cannot scan the page | Deliberately minimal aesthetic where all text is body-weight; must be an explicit brand decision | craft-presumption | retune | render |
|
|
129
|
+
| T2 | Oversized italic serif as the primary hero headline | The "AI startup landing page" template; seen on ~60% of AI-generated marketing pages | Brand adopts editorial-magazine aesthetic with a documented italic serif rationale | style-preference | replace | render |
|
|
130
|
+
| T3 | Icon tile (small rounded-square container) above heading | The universal AI feature-card template; reads as scaffold | Listed features genuinely benefit from visual-icon-then-title affordance AND the icons are custom, not library defaults | style-preference | delete | static |
|
|
131
|
+
| T4 | Eyebrow / ALL-CAPS label above every section heading | Overuse collapses the emphasis; maximum is 1 eyebrow per 3 sections (countable: grep tracking classes) | Used for genuine section-type differentiation with meaningful vocabulary (not just "FEATURES", "PRICING") | craft-presumption | delete → reduce | static |
|
|
132
|
+
| T5 | Repeated section kickers ("Our mission", "What we offer", "Why choose us") | Filler vocabulary; every AI-generated page has the same three section titles | Every kicker is substantive and uses brand-specific vocabulary, not generic marketing speak | craft-presumption | replace | judgment |
|
|
133
|
+
| T6 | Crushed letter-spacing on display text (`letter-spacing` < −0.04em) | Below −0.04em glyphs collide optically; reads as "designer-ish effect" with no grounding | Intentional tight display treatment with a documented minimum floor; verify at the actual render size | floor | retune | static |
|
|
134
|
+
| T7 | Overused fonts without a stated reason: Inter, Roboto, DM Sans, Geist, Space Grotesk, Instrument Serif | These are the default AI-coding-tool font picks; every generated UI uses one of them | **Register-scoped.** In the **brand** register: the brand has explicitly adopted one of these AND there is a documented reason. In the **product** register: a single reliable family is the sanctioned strategy ([`design-modes`](design-modes.md) § The two registers), so one of these is legitimate on a **stated** product-register choice — the register itself is the reason, and it must be stated (DESIGN.md, the surface brief, or `design-slop-disable`). Neither register admits an *undeclared* pick. | reference-constraint | replace | judgment |
|
|
135
|
+
| T8 | Single typeface for everything | Missed typographic contrast opportunity; in the **brand** register an unexamined single family reads as "I did not think about fonts" | **Register-scoped like T7.** Intentional mono-typeface aesthetic (e.g., terminal-inspired), stated in the brief — *or* the **product** register, where one reliable family is the sanctioned strategy ([`design-modes`](design-modes.md) § The two registers) and contrast is carried by weight and scale rather than by a second family. | reference-constraint | retune | judgment |
|
|
136
|
+
| T9 | All-caps body paragraphs or field labels | Reduces legibility below WCAG AA for sustained reading; reads as flair over function | Short UI labels (e.g., button text in a brutalist layout); never for body paragraphs | floor | delete → retune | static |
|
|
137
|
+
| T10 | Wide letter-spacing on body text (`letter-spacing` > 0.05em) | Reduces readability for sustained reading; reserved for display use | Display text (headlines, pull quotes) where intentional tracking is a brand element | craft-presumption | retune | static |
|
|
115
138
|
|
|
116
139
|
---
|
|
117
140
|
|
|
118
141
|
## Color
|
|
119
142
|
|
|
120
|
-
| # | Pattern | Why it reads as AI-generated | Override condition |
|
|
121
|
-
|
|
122
|
-
| C1 | Purple/violet + cyan-on-dark palette as the primary scheme | The most recognizable AI-UI color combination in 2024–2026; instantly signals "generated" | Brand color system genuinely defines a violet primary; must come from `brand-to-tokens`, not from model defaults |
|
|
123
|
-
| C2 | Gradient text via `background-clip: text` as a primary accent | Overused to the point of invisibility; also has rendering edge cases on some platforms | Headline treatment in a brand that explicitly uses gradient identity (e.g., a product whose logo is a gradient) |
|
|
124
|
-
| C3 | Glowing colored accents on dark mode (bright neon `box-shadow` or `text-shadow`) | Looks like a 2020 gaming UI; reads as an AI attempt at "moody" | Brand explicitly defines neon accents with a documented usage rule (e.g., error or alert states in a security product) |
|
|
125
|
-
| C4 | Gray text on colored background without WCAG AA check | Muted gray chosen for "elegance" often fails 4.5:1 contrast; the failure is invisible until audited | Any use — always verify the contrast ratio; if it fails, either darken the text or lighten/darken the background |
|
|
126
|
-
| C5 | Cream/sand body background (OKLCH L 0.84–0.97, C < 0.06) with brass/clay/oxblood accents | The 2025 "premium-consumer" AI palette; every generated "sophisticated" product uses this exact combination | Brand has an explicit warm-neutral design language documented in `brand-to-tokens`; the palette is first-party, not a default reach |
|
|
143
|
+
| # | Pattern | Why it reads as AI-generated | Override condition | Class | Remediation | Verification |
|
|
144
|
+
|---|---|---|---|---|---|---|
|
|
145
|
+
| C1 | Purple/violet + cyan-on-dark palette as the primary scheme | The most recognizable AI-UI color combination in 2024–2026; instantly signals "generated" | Brand color system genuinely defines a violet primary; must come from `brand-to-tokens`, not from model defaults | style-preference | replace | static |
|
|
146
|
+
| C2 | Gradient text via `background-clip: text` as a primary accent | Overused to the point of invisibility; also has rendering edge cases on some platforms | Headline treatment in a brand that explicitly uses gradient identity (e.g., a product whose logo is a gradient) | style-preference | delete | static |
|
|
147
|
+
| C3 | Glowing colored accents on dark mode (bright neon `box-shadow` or `text-shadow`) | Looks like a 2020 gaming UI; reads as an AI attempt at "moody" | Brand explicitly defines neon accents with a documented usage rule (e.g., error or alert states in a security product) | style-preference | delete → reduce | static |
|
|
148
|
+
| C4 | Gray text on colored background without WCAG AA check | Muted gray chosen for "elegance" often fails 4.5:1 contrast; the failure is invisible until audited | Any use — always verify the contrast ratio; if it fails, either darken the text or lighten/darken the background | floor | retune | static |
|
|
149
|
+
| C5 | Cream/sand body background (OKLCH L 0.84–0.97, C < 0.06) with brass/clay/oxblood accents | The 2025 "premium-consumer" AI palette; every generated "sophisticated" product uses this exact combination | Brand has an explicit warm-neutral design language documented in `brand-to-tokens`; the palette is first-party, not a default reach | style-preference | replace | static |
|
|
127
150
|
|
|
128
151
|
---
|
|
129
152
|
|
|
130
153
|
## Layout
|
|
131
154
|
|
|
132
|
-
| # | Pattern | Why it reads as AI-generated | Override condition |
|
|
133
|
-
|
|
134
|
-
| L1 | Hero metric template: giant number, small label, 3–4 stats in a row, gradient | The default SaaS dashboard hero; appears on ~70% of AI-generated dashboard screens | Data storytelling genuinely requires a primary metric with supporting context; must vary the arrangement |
|
|
135
|
-
| L2 | Three identical feature cards in a grid with the same visual weight | The scaffold-default; no visual rhythm, no hierarchy among features | Product genuinely has three equally weighted features; must still vary padding, or use a different composition |
|
|
136
|
-
| L3 | Monotonous spacing: one spacing value (usually 24px) used for everything | Spacing is rhythm; uniform spacing collapses the hierarchy of proximity | Intentional grid where every element has equal weight; must document the grid definition |
|
|
137
|
-
| L4 | Numbered section markers (01 / 02 / 03) as a primary section-order device | Universal AI-generated marketing page tell; seen on virtually every generated landing page | A genuinely numbered process or sequenced guide where the step number carries meaning beyond decoration |
|
|
138
|
-
| L5 | Line length > 80ch in body copy without column constraint | Reduces readability; WCAG recommends 45–75 characters; beyond 80 the eye struggles to track | Data-dense dashboards where column width is driven by tabular data, not narrative text |
|
|
139
|
-
| L6 | `position: absolute` dropdown inside `overflow: hidden` container | Dropdown clips; a common AI-generated layout bug | Refactor: use `<dialog>`, the Popover API, or `position: fixed` / portal to escape the stacking context |
|
|
140
|
-
| L7 | Content that overflows its container | Text truncation or reflow failures at non-default viewport widths; reads as untested | Never acceptable in production output; test at 320px, 768px, 1280px minimally |
|
|
141
|
-
| L8 | Z-index values of 99, 999, 9999 without a semantic z-index scale | Magic numbers; the first time two elements compete, the scale breaks | Establish a named semantic z-index scale (`--z-modal: 400`, `--z-toast: 500`, etc.) and use it |
|
|
155
|
+
| # | Pattern | Why it reads as AI-generated | Override condition | Class | Remediation | Verification |
|
|
156
|
+
|---|---|---|---|---|---|---|
|
|
157
|
+
| L1 | Hero metric template: giant number, small label, 3–4 stats in a row, gradient | The default SaaS dashboard hero; appears on ~70% of AI-generated dashboard screens | Data storytelling genuinely requires a primary metric with supporting context; must vary the arrangement | craft-presumption | retune | render |
|
|
158
|
+
| L2 | Three identical feature cards in a grid with the same visual weight | The scaffold-default; no visual rhythm, no hierarchy among features | Product genuinely has three equally weighted features; must still vary padding, or use a different composition | craft-presumption | retune | render |
|
|
159
|
+
| L3 | Monotonous spacing: one spacing value (usually 24px) used for everything | Spacing is rhythm; uniform spacing collapses the hierarchy of proximity | Intentional grid where every element has equal weight; must document the grid definition | craft-presumption | retune | static |
|
|
160
|
+
| L4 | Numbered section markers (01 / 02 / 03) as a primary section-order device | Universal AI-generated marketing page tell; seen on virtually every generated landing page | A genuinely numbered process or sequenced guide where the step number carries meaning beyond decoration | style-preference | delete | static |
|
|
161
|
+
| L5 | Line length > 80ch in body copy without column constraint | Reduces readability; WCAG recommends 45–75 characters; beyond 80 the eye struggles to track | Data-dense dashboards where column width is driven by tabular data, not narrative text | floor | retune | render |
|
|
162
|
+
| L6 | `position: absolute` dropdown inside `overflow: hidden` container | Dropdown clips; a common AI-generated layout bug | Refactor: use `<dialog>`, the Popover API, or `position: fixed` / portal to escape the stacking context | invariant | replace | render |
|
|
163
|
+
| L7 | Content that overflows its container | Text truncation or reflow failures at non-default viewport widths; reads as untested | Never acceptable in production output; test at 320px, 768px, 1280px minimally | invariant | retune | render |
|
|
164
|
+
| L8 | Z-index values of 99, 999, 9999 without a semantic z-index scale | Magic numbers; the first time two elements compete, the scale breaks | Establish a named semantic z-index scale (`--z-modal: 400`, `--z-toast: 500`, etc.) and use it | invariant | replace | static |
|
|
142
165
|
|
|
143
166
|
---
|
|
144
167
|
|
|
145
168
|
## Motion
|
|
146
169
|
|
|
147
|
-
| # | Pattern | Why it reads as AI-generated | Override condition |
|
|
148
|
-
|
|
149
|
-
| M1 | Bounce or elastic easing curves on UI elements | Bounce draws attention to the animation itself; UI motion should serve the action, not perform | Intentional playful affordance (game UI, onboarding celebration state); must be brief and non-repeating |
|
|
150
|
-
| M2 | Animating layout properties (width, height, top, left, padding) | Triggers browser layout recalculation; janky on mid-range devices; always solvable with `transform` | Never — use `transform: scaleX()` for width-like effects, `transform: translateY()` for position |
|
|
151
|
-
| M3 | Animating `<img>` element on hover (scale, filter, transform) | Triggers composite + image decode; often causes content shift | Animate the card's background, border, or shadow instead; leave the image static |
|
|
152
|
-
| M4 | `transition: all` shorthand | Animates every property including layout, color, opacity simultaneously; unpredictable and expensive | Enumerate only the properties that should animate: `transition: transform 200ms ease-out, opacity 200ms` |
|
|
153
|
-
| M5 | Missing `@media (prefers-reduced-motion: reduce)` alternative for any animation | Accessibility violation; vestibular disorders make animated UI unusable | Never acceptable; always add a `prefers-reduced-motion` variant — gentler animation (reduced distance/opacity) is preferred over `display: none` |
|
|
154
|
-
| M6 | Every section fading and rising into view on scroll | The most recognisable interaction tell of the current generation; a reveal applied per section carries no information — the reader has already scrolled to the content, so the animation delays what they asked for | The reveal carries meaning: a stepped narrative where each beat must land before the next, or a long-form article using position to signal progress. A reveal on *every* section is a default, not a decision |
|
|
155
|
-
| M7 | A radial highlight tracking the pointer across a dark hero | A `mousemove` handler feeding a radial gradient; it draws the eye to the cursor, which is the one thing on the page the user already knows the position of | The spotlight is the interaction — a genuine reveal mechanic, a canvas inspection tool, an accessibility magnifier. Ambience is not a purpose |
|
|
156
|
-
| M8 | An interactive control that reduces its own opacity on hover | Reads as the element retreating from the pointer rather than responding to it, and a fade is the one hover treatment that *reduces* legibility at the moment the user is committing to the target — see the six interaction states in [`design-review`](../../src/skills/design-review/SKILL.md) | The fade communicates a real state change (an item being dismissed, a layer being peeled back). Hover must stay legible; brightness, background or border carry hover without spending contrast |
|
|
170
|
+
| # | Pattern | Why it reads as AI-generated | Override condition | Class | Remediation | Verification |
|
|
171
|
+
|---|---|---|---|---|---|---|
|
|
172
|
+
| M1 | Bounce or elastic easing curves on UI elements | Bounce draws attention to the animation itself; UI motion should serve the action, not perform | Intentional playful affordance (game UI, onboarding celebration state); must be brief and non-repeating | invariant | replace | feel |
|
|
173
|
+
| M2 | Animating layout properties (width, height, top, left, padding) | Triggers browser layout recalculation; janky on mid-range devices; always solvable with `transform` | Never — use `transform: scaleX()` for width-like effects, `transform: translateY()` for position | floor | replace | static |
|
|
174
|
+
| M3 | Animating `<img>` element on hover (scale, filter, transform) | Triggers composite + image decode; often causes content shift | Animate the card's background, border, or shadow instead; leave the image static | invariant | replace | render |
|
|
175
|
+
| M4 | `transition: all` shorthand | Animates every property including layout, color, opacity simultaneously; unpredictable and expensive | Enumerate only the properties that should animate: `transition: transform 200ms ease-out, opacity 200ms` | invariant | replace | static |
|
|
176
|
+
| M5 | Missing `@media (prefers-reduced-motion: reduce)` alternative for any animation | Accessibility violation; vestibular disorders make animated UI unusable | Never acceptable; always add a `prefers-reduced-motion` variant — gentler animation (reduced distance/opacity) is preferred over `display: none` | floor | delete → retune | static |
|
|
177
|
+
| M6 | Every section fading and rising into view on scroll | The most recognisable interaction tell of the current generation; a reveal applied per section carries no information — the reader has already scrolled to the content, so the animation delays what they asked for | The reveal carries meaning: a stepped narrative where each beat must land before the next, or a long-form article using position to signal progress. A reveal on *every* section is a default, not a decision | craft-presumption | delete → reduce | feel |
|
|
178
|
+
| M7 | A radial highlight tracking the pointer across a dark hero | A `mousemove` handler feeding a radial gradient; it draws the eye to the cursor, which is the one thing on the page the user already knows the position of | The spotlight is the interaction — a genuine reveal mechanic, a canvas inspection tool, an accessibility magnifier. Ambience is not a purpose | style-preference | delete | feel |
|
|
179
|
+
| M8 | An interactive control that reduces its own opacity on hover | Reads as the element retreating from the pointer rather than responding to it, and a fade is the one hover treatment that *reduces* legibility at the moment the user is committing to the target — see the six interaction states in [`design-review`](../../src/skills/design-review/SKILL.md) | The fade communicates a real state change (an item being dismissed, a layer being peeled back). Hover must stay legible; brightness, background or border carry hover without spending contrast | craft-presumption | retune | feel |
|
|
157
180
|
|
|
158
181
|
---
|
|
159
182
|
|
|
160
183
|
## Copy
|
|
161
184
|
|
|
162
|
-
| # | Pattern | Why it reads as AI-generated | Override condition |
|
|
163
|
-
|
|
164
|
-
| CP1 | Em-dash (`—`) overuse | The #1 syntactic LLM signature; appears in AI copy at 3–5× the frequency of human editorial copy; maximum 2 per 500 words | Specific editorial voice that uses em-dashes deliberately; count them before shipping |
|
|
165
|
-
| CP2 | Marketing buzzwords: streamline, empower, supercharge, world-class, enterprise-grade, seamlessly, robust, leverage | These words carry no information; an AI-slop test: replace each with nothing — the sentence still communicates the same thing | No override; if a word can be deleted without loss, delete it |
|
|
166
|
-
| CP3 | Aphoristic manufactured contrast ("We don't do X. We do Y." / "Not just A, but B.") | A generated sentence rhythm that sounds like brand writing but carries no specificity | Aphoristic copy is legitimate when the contrast reveals a genuine product distinction; test by asking whether the Y side says something concrete |
|
|
167
|
-
| CP4 | "Theater" framing — copy that announces what the product does without saying how or why | "The platform for modern teams." communicates nothing; it is content-shaped noise | Every tagline must pass the "so what" test: can a skeptic follow it with "but how?" and get a concrete answer? |
|
|
168
|
-
| CP5 | Emoji-decoration in UI markup — 🚀/✅/🎉 prepending headings, buttons, list items, or CTAs (`🚀 Get Started`) | Performative-enthusiasm coating; the default-startup-template tell. No emoji is better than decorative emoji | Brand/`DESIGN.md` declares a systematic emoji strategy, or the emoji is functional (status indicator, category marker tied to real meaning) |
|
|
169
|
-
| CP6 | Stock render subject named instead of the product's own subject matter — "floating abstract shapes", "gradient mesh", "glowing orb", "particle field", "futuristic HUD" | These name the default thing a render becomes when nobody decided what it is about; same delete-test as CP2, applied to art direction — swap the phrase for what the product actually shows and the brief says more | The subject IS abstract by decision (a generative-art surface, a data-driven field whose data is named), and the brief says which decision and why |
|
|
185
|
+
| # | Pattern | Why it reads as AI-generated | Override condition | Class | Remediation | Verification |
|
|
186
|
+
|---|---|---|---|---|---|---|
|
|
187
|
+
| CP1 | Em-dash (`—`) overuse | The #1 syntactic LLM signature; appears in AI copy at 3–5× the frequency of human editorial copy; maximum 2 per 500 words | Specific editorial voice that uses em-dashes deliberately; count them before shipping | craft-presumption | delete → reduce | static |
|
|
188
|
+
| CP2 | Marketing buzzwords: streamline, empower, supercharge, world-class, enterprise-grade, seamlessly, robust, leverage | These words carry no information; an AI-slop test: replace each with nothing — the sentence still communicates the same thing | No override; if a word can be deleted without loss, delete it | craft-presumption | delete | static |
|
|
189
|
+
| CP3 | Aphoristic manufactured contrast ("We don't do X. We do Y." / "Not just A, but B.") | A generated sentence rhythm that sounds like brand writing but carries no specificity | Aphoristic copy is legitimate when the contrast reveals a genuine product distinction; test by asking whether the Y side says something concrete | style-preference | delete → replace | judgment |
|
|
190
|
+
| CP4 | "Theater" framing — copy that announces what the product does without saying how or why | "The platform for modern teams." communicates nothing; it is content-shaped noise | Every tagline must pass the "so what" test: can a skeptic follow it with "but how?" and get a concrete answer? | craft-presumption | replace | judgment |
|
|
191
|
+
| CP5 | Emoji-decoration in UI markup — 🚀/✅/🎉 prepending headings, buttons, list items, or CTAs (`🚀 Get Started`) | Performative-enthusiasm coating; the default-startup-template tell. No emoji is better than decorative emoji | Brand/`DESIGN.md` declares a systematic emoji strategy, or the emoji is functional (status indicator, category marker tied to real meaning) | craft-presumption | delete | static |
|
|
192
|
+
| CP6 | Stock render subject named instead of the product's own subject matter — "floating abstract shapes", "gradient mesh", "glowing orb", "particle field", "futuristic HUD" | These name the default thing a render becomes when nobody decided what it is about; same delete-test as CP2, applied to art direction — swap the phrase for what the product actually shows and the brief says more | The subject IS abstract by decision (a generative-art surface, a data-driven field whose data is named), and the brief says which decision and why | craft-presumption | replace | judgment |
|
|
170
193
|
|
|
171
194
|
---
|
|
172
195
|
|
|
@@ -86,6 +86,34 @@ translation frequently denote different mechanisms — here `route`, `dispatch`,
|
|
|
86
86
|
five ways — so a sweep over them destroys information the echo classes exist to
|
|
87
87
|
protect.
|
|
88
88
|
|
|
89
|
+
## The avoid-list — one term, one concept
|
|
90
|
+
|
|
91
|
+
A homonym collision is only half-diagnosed when it is classified. The other
|
|
92
|
+
half is the **decision**: which concept keeps the word, and what every other
|
|
93
|
+
sense is called instead. This list carries the decided ones. A word is added
|
|
94
|
+
here when the same term has been observed denoting more than one shipped
|
|
95
|
+
mechanism; it is removed only when the collision is gone from the tree, never
|
|
96
|
+
because the entry became inconvenient.
|
|
97
|
+
|
|
98
|
+
Read the columns as a rename instruction for **prose you write from now on**.
|
|
99
|
+
The identifier layer is decided separately and per cluster, exactly as the
|
|
100
|
+
prose/identifier split above requires — a term may be `canonicalize-term` in
|
|
101
|
+
prose and `keep-distinct` in identifiers, and both verdicts are recorded.
|
|
102
|
+
|
|
103
|
+
| Term | Concept that keeps the word | Other senses, and what to call them | Identifier verdict |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| `envelope` | The **transport wrapper** around a payload — `OutcomeEnvelope` (a run's terminal outcome, `src/scripts/_lib/outcome_envelope.ts`) and the `CHECKPOINT` envelope a worker capsule rides in. | The **session continuity record** is a **capsule**. The word is not chosen for readability — it is the shipped discriminator (`CAPSULE_SCHEMA_VERSION`, `CAPSULE_VARIANTS = ['worker','main_session']`, `src/scripts/_lib/subagent_capsule.ts`), so the surviving term is read off what ships rather than off what reads best. | `keep-distinct` for now. `MainSessionRecycleEnvelope` and `RECYCLE_ENVELOPE_*` keep their names until a rename is costed on its own; the prose rule binds immediately and the symbols are a separate blast radius. |
|
|
106
|
+
| `handoff` | The **session-to-session continuity handover** a developer invokes — the `handoff` verb and the `/agent-handoff` command. | The lint over senior-tier skills' `## Related Skills` edges is a **cross-wing skill link**, never "a handoff". | `keep-distinct`, recorded reason: `lint_handoffs.ts` mirrors a ported CLI contract (ADR-200) whose name is an external surface. Its module docstring already says "cross-wing", which is the disambiguation the prose rule now requires everywhere else. |
|
|
107
|
+
|
|
108
|
+
**Why a list and not a linter.** `lint_canonical_terms` decides *spelling*
|
|
109
|
+
pairs, where one side is mechanically wrong. A homonym is not mechanically
|
|
110
|
+
wrong anywhere — every occurrence is a legitimate word for a legitimate
|
|
111
|
+
concept, and only the reader's inability to tell them apart is the defect. A
|
|
112
|
+
gate that flagged `envelope` would flag the entry that is supposed to survive.
|
|
113
|
+
So this list is enforced at review, by citation, and its cost of being ignored
|
|
114
|
+
is the cost the taxonomy already names: the model telling you it has not
|
|
115
|
+
decided.
|
|
116
|
+
|
|
89
117
|
## Why any of this is worth a gate at all
|
|
90
118
|
|
|
91
119
|
Generated code trends toward duplication rather than reuse: measured
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@event4u/agent-config",
|
|
3
3
|
"mcpName": "io.github.event4u-app/agent-config",
|
|
4
|
-
"version": "14.
|
|
4
|
+
"version": "14.20.0",
|
|
5
5
|
"description": "Governed skills, rules and commands for AI coding tools (Claude Code, Cursor, Windsurf, Copilot) — every claim machine-checked, including the counts in these badges.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"private": false,
|
package/src/agent-src/README.md
CHANGED
|
@@ -17,7 +17,7 @@ it as `.augment/` (local projection).
|
|
|
17
17
|
├── contexts/ # Background context documents for the agent
|
|
18
18
|
├── guidelines/ # Coding guidelines by language (reference material)
|
|
19
19
|
├── rules/ # Always-active behavior rules (auto-loaded every conversation)
|
|
20
|
-
├── skills/ # On-demand expertise (
|
|
20
|
+
├── skills/ # On-demand expertise (named or trigger-matched)
|
|
21
21
|
└── templates/ # File templates for roadmaps, features, skills, etc.
|
|
22
22
|
```
|
|
23
23
|
|