@event4u/agent-config 7.4.0 → 8.0.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/.claude-plugin/marketplace.json +11 -1
- package/AGENTS.md +9 -9
- package/CHANGELOG.md +373 -0
- package/README.md +35 -5
- package/dist/agent-src/commands/analytics/prune.md +1 -1
- package/dist/agent-src/commands/analytics/show.md +1 -1
- package/dist/agent-src/commands/analyze/decision.md +2 -2
- package/dist/agent-src/commands/analyze/incident.md +2 -2
- package/dist/agent-src/commands/analyze/near-miss.md +2 -2
- package/dist/agent-src/commands/analyze/postmortem.md +2 -2
- package/dist/agent-src/commands/analyze/premortem.md +2 -2
- package/dist/agent-src/commands/cost-report.md +25 -0
- package/dist/agent-src/commands/evals/analyze.json +30 -0
- package/dist/agent-src/commands/evals/mission-upgrade.json +30 -0
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/knowledge/forget.md +1 -1
- package/dist/agent-src/commands/knowledge/ingest.md +1 -1
- package/dist/agent-src/commands/knowledge/list.md +1 -1
- package/dist/agent-src/commands/memory/load.md +12 -11
- package/dist/agent-src/commands/memory/promote.md +30 -0
- package/dist/agent-src/commands/memory/propose.md +16 -2
- package/dist/agent-src/commands/mission/upgrade.md +1 -1
- package/dist/agent-src/commands/module/explore.md +11 -7
- package/dist/agent-src/commands/optimize-project.md +243 -0
- package/dist/agent-src/commands/optimize.md +5 -0
- package/dist/agent-src/commands/pr/create.md +37 -8
- package/dist/agent-src/commands/prediction-pool.md +2 -2
- package/dist/agent-src/commands/profile/activate.md +3 -3
- package/dist/agent-src/commands/profile/deactivate.md +2 -2
- package/dist/agent-src/commands/profile/show.md +3 -3
- package/dist/agent-src/commands/research/deep.md +5 -0
- package/dist/agent-src/commands/research/report.md +2 -1
- package/dist/agent-src/commands/review-changes.md +14 -7
- package/dist/agent-src/commands/roadmap/create.md +88 -10
- package/dist/agent-src/commands/roadmap/materialize.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +15 -2
- package/dist/agent-src/commands/roadmap/process-phase.md +18 -6
- package/dist/agent-src/commands/roadmap/process-step.md +4 -0
- package/dist/agent-src/commands/roadmap.md +1 -1
- package/dist/agent-src/commands/security-audit-config.md +1 -1
- package/dist/agent-src/commands/sync-agent-settings.md +1 -1
- package/dist/agent-src/commands/sync-gitignore/fix.md +42 -6
- package/dist/agent-src/commands/team-knowledge/bootstrap.md +106 -0
- package/dist/agent-src/commands/team-knowledge/consolidate.md +105 -0
- package/dist/agent-src/commands/team-knowledge.md +64 -0
- package/dist/agent-src/contexts/authority/commit-mechanics.md +8 -0
- package/dist/agent-src/contexts/authority/destructive-mechanics.md +11 -0
- package/dist/agent-src/contexts/authority/scope-mechanics.md +25 -0
- package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +43 -0
- package/dist/agent-src/contexts/contracts/agents-md-anatomy.md +1 -1
- package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +2 -2
- package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +14 -4
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +11 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +32 -8
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +107 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +71 -15
- package/dist/agent-src/contexts/execution/subagent-steering.md +41 -1
- package/dist/agent-src/contexts/override-system.md +1 -1
- package/dist/agent-src/personas/brand-strategist.md +0 -1
- package/dist/agent-src/personas/data-integrity.md +66 -0
- package/dist/agent-src/personas/design-director.md +0 -1
- package/dist/agent-src/personas/performance-engineer.md +66 -0
- package/dist/agent-src/personas/production-validator.md +73 -0
- package/dist/agent-src/rules/agent-authority.md +3 -4
- package/dist/agent-src/rules/analysis-skill-routing.md +3 -5
- package/dist/agent-src/rules/architecture.md +2 -4
- package/dist/agent-src/rules/artifact-drafting-protocol.md +35 -6
- package/dist/agent-src/rules/artifact-engagement-recording.md +11 -4
- package/dist/agent-src/rules/ask-when-uncertain.md +10 -14
- package/dist/agent-src/rules/augment-edit-discipline.md +3 -5
- package/dist/agent-src/rules/autonomous-execution.md +3 -5
- package/dist/agent-src/rules/brand-consistency.md +3 -5
- package/dist/agent-src/rules/brand-source-of-truth.md +3 -5
- package/dist/agent-src/rules/cli-output-handling.md +4 -6
- package/dist/agent-src/rules/command-suggestion-policy.md +3 -5
- package/dist/agent-src/rules/commit-conventions.md +3 -5
- package/dist/agent-src/rules/commit-policy.md +8 -10
- package/dist/agent-src/rules/content-quoting-floor.md +88 -0
- package/dist/agent-src/rules/context-hygiene.md +3 -5
- package/dist/agent-src/rules/copilot-routing.md +4 -6
- package/dist/agent-src/rules/decision-revisit-gate.md +120 -0
- package/dist/agent-src/rules/delegation-policy.md +10 -6
- package/dist/agent-src/rules/design-fidelity.md +3 -5
- package/dist/agent-src/rules/devcontainer-routing.md +4 -6
- package/dist/agent-src/rules/direct-answers.md +13 -17
- package/dist/agent-src/rules/docker-commands.md +3 -5
- package/dist/agent-src/rules/domain-adoption-policy.md +3 -5
- package/dist/agent-src/rules/domain-safety-disclaimer.md +3 -5
- package/dist/agent-src/rules/domain-safety-pii.md +7 -8
- package/dist/agent-src/rules/domain-safety-retention.md +3 -5
- package/dist/agent-src/rules/downstream-changes.md +3 -4
- package/dist/agent-src/rules/engineering-safety-floor.md +3 -5
- package/dist/agent-src/rules/external-reference-deep-dive.md +3 -5
- package/dist/agent-src/rules/fast-path-marker-visibility.md +3 -5
- package/dist/agent-src/rules/finance-safety-floor.md +3 -6
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +3 -5
- package/dist/agent-src/rules/git-history-discipline.md +3 -5
- package/dist/agent-src/rules/guidelines.md +2 -4
- package/dist/agent-src/rules/icon-consistency.md +4 -5
- package/dist/agent-src/rules/image-likeness-and-rights.md +3 -5
- package/dist/agent-src/rules/improve-before-implement.md +5 -5
- package/dist/agent-src/rules/invite-challenge.md +3 -5
- package/dist/agent-src/rules/language-and-tone.md +13 -15
- package/dist/agent-src/rules/laravel-routing.md +3 -5
- package/dist/agent-src/rules/laravel-translations.md +3 -5
- package/dist/agent-src/rules/legal-safety-floor.md +5 -7
- package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -5
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +4 -7
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +3 -5
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +2 -4
- package/dist/agent-src/rules/media-governance-routing.md +3 -5
- package/dist/agent-src/rules/media-sync-ground-truth.md +3 -5
- package/dist/agent-src/rules/minimal-safe-diff.md +5 -5
- package/dist/agent-src/rules/missing-tool-handling.md +3 -5
- package/dist/agent-src/rules/model-recommendation.md +4 -6
- package/dist/agent-src/rules/no-attribution-footers.md +3 -5
- package/dist/agent-src/rules/no-cheap-questions.md +5 -8
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +3 -6
- package/dist/agent-src/rules/no-pr-progress-comments.md +3 -6
- package/dist/agent-src/rules/no-roadmap-references.md +3 -5
- package/dist/agent-src/rules/non-destructive-by-default.md +11 -13
- package/dist/agent-src/rules/notes-first-reasoning.md +3 -5
- package/dist/agent-src/rules/onboarding-gate.md +4 -6
- package/dist/agent-src/rules/output-discipline.md +3 -5
- package/dist/agent-src/rules/package-ci-checks.md +3 -5
- package/dist/agent-src/rules/persona-governance.md +2 -4
- package/dist/agent-src/rules/php-coding.md +3 -5
- package/dist/agent-src/rules/preservation-guard.md +2 -4
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -5
- package/dist/agent-src/rules/reviewer-awareness.md +5 -6
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +3 -5
- package/dist/agent-src/rules/roadmap-progress-sync.md +5 -5
- package/dist/agent-src/rules/role-mode-adherence.md +2 -4
- package/dist/agent-src/rules/rule-type-governance.md +3 -5
- package/dist/agent-src/rules/runtime-safety.md +2 -4
- package/dist/agent-src/rules/scope-control.md +10 -11
- package/dist/agent-src/rules/security-sensitive-stop.md +4 -5
- package/dist/agent-src/rules/size-enforcement.md +2 -4
- package/dist/agent-src/rules/skill-improvement-trigger.md +3 -5
- package/dist/agent-src/rules/skill-quality.md +3 -5
- package/dist/agent-src/rules/slash-command-routing-policy.md +3 -5
- package/dist/agent-src/rules/source-confidentiality.md +3 -5
- package/dist/agent-src/rules/source-discovery-gate.md +3 -5
- package/dist/agent-src/rules/source-of-truth.md +3 -5
- package/dist/agent-src/rules/strategy-safety-floor.md +3 -5
- package/dist/agent-src/rules/symfony-routing.md +4 -6
- package/dist/agent-src/rules/telegraph-speak.md +4 -5
- package/dist/agent-src/rules/think-before-action.md +7 -4
- package/dist/agent-src/rules/token-budget-discipline.md +29 -5
- package/dist/agent-src/rules/token-efficiency.md +3 -5
- package/dist/agent-src/rules/token-optimizer-maintenance.md +3 -5
- package/dist/agent-src/rules/tool-safety.md +2 -4
- package/dist/agent-src/rules/ui-audit-gate.md +3 -6
- package/dist/agent-src/rules/untrusted-input-defense.md +11 -10
- package/dist/agent-src/rules/upstream-proposal.md +4 -6
- package/dist/agent-src/rules/user-interaction.md +7 -5
- package/dist/agent-src/rules/user-interrupt-priority.md +17 -8
- package/dist/agent-src/rules/verify-before-complete.md +12 -22
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +3 -3
- package/dist/agent-src/scripts/update_roadmap_progress.ts +197 -7
- package/dist/agent-src/skills/adr-create/SKILL.md +52 -42
- package/dist/agent-src/skills/adversarial-review/SKILL.md +1 -1
- package/dist/agent-src/skills/agent-docs-writing/SKILL.md +18 -0
- package/dist/agent-src/skills/agent-security-review/SKILL.md +1 -1
- package/dist/agent-src/skills/ai-council/SKILL.md +14 -1
- package/dist/agent-src/skills/blade-ui/SKILL.md +4 -0
- package/dist/agent-src/skills/blameless-post-mortem/SKILL.md +0 -3
- package/dist/agent-src/skills/brand/SKILL.md +1 -1
- package/dist/agent-src/skills/brand-identity/SKILL.md +3 -3
- package/dist/agent-src/skills/brand-strategy/SKILL.md +1 -1
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +5 -4
- package/dist/agent-src/skills/canvas-design/SKILL.md +6 -0
- package/dist/agent-src/skills/check-refs/SKILL.md +7 -4
- package/dist/agent-src/skills/code-review/SKILL.md +5 -0
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +6 -5
- package/dist/agent-src/skills/condense-memory/SKILL.md +11 -11
- package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/context-document/SKILL.md +17 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -3
- package/dist/agent-src/skills/decision-record/SKILL.md +6 -0
- package/dist/agent-src/skills/decision-review/SKILL.md +5 -3
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +6 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +45 -2
- package/dist/agent-src/skills/design-intelligence/references/design-languages.md +1 -1
- package/dist/agent-src/skills/design-review/SKILL.md +23 -11
- package/dist/agent-src/skills/design-system-capture/SKILL.md +41 -0
- package/dist/agent-src/skills/design-system-capture/reference/design-system-json.md +62 -0
- package/dist/agent-src/skills/design-tokens/SKILL.md +11 -4
- package/dist/agent-src/skills/design-variations/SKILL.md +127 -0
- package/dist/agent-src/skills/design-variations/evals/triggers.json +17 -0
- package/dist/agent-src/skills/emit-tickets/SKILL.md +4 -4
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +6 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +20 -0
- package/dist/agent-src/skills/flux/SKILL.md +4 -0
- package/dist/agent-src/skills/html-deck/SKILL.md +123 -0
- package/dist/agent-src/skills/html-deck/evals/triggers.json +17 -0
- package/dist/agent-src/skills/html-deck/templates/deck-shell.html +77 -0
- package/dist/agent-src/skills/iconography/SKILL.md +1 -0
- package/dist/agent-src/skills/image-editing/evals/triggers.json +13 -13
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +136 -0
- package/dist/agent-src/skills/judge-artifact-completeness/calibration/fixtures.json +149 -0
- package/dist/agent-src/skills/judge-artifact-completeness/evals/triggers.json +17 -0
- package/dist/agent-src/skills/judge-artifact-completeness/rubrics/architecture-score.json +73 -0
- package/dist/agent-src/skills/judge-artifact-completeness/rubrics/pr-review-score.json +65 -0
- package/dist/agent-src/skills/judge-artifact-completeness/rubrics/roadmap-score.json +73 -0
- package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +73 -0
- package/dist/agent-src/skills/judge-code-quality/SKILL.md +1 -0
- package/dist/agent-src/skills/judge-injection-defense/SKILL.md +99 -0
- package/dist/agent-src/skills/judge-injection-defense/calibration/fixtures.json +24 -0
- package/dist/agent-src/skills/judge-injection-defense/evals/triggers.json +17 -0
- package/dist/agent-src/skills/judge-injection-defense/fixtures/behavioral-fixtures.json +63 -0
- package/dist/agent-src/skills/judge-injection-defense/fixtures/coverage-report.md +53 -0
- package/dist/agent-src/skills/judge-injection-defense/fixtures/perturbation-taxonomy.json +110 -0
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +134 -0
- package/dist/agent-src/skills/judge-synthesis/evals/triggers.json +17 -0
- package/dist/agent-src/skills/laravel/SKILL.md +0 -1
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +46 -0
- package/dist/agent-src/skills/lint-skills/SKILL.md +6 -6
- package/dist/agent-src/skills/logo-generation/SKILL.md +1 -1
- package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
- package/dist/agent-src/skills/md-language-check/SKILL.md +3 -3
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +66 -1
- package/dist/agent-src/skills/migration-architect/SKILL.md +1 -0
- package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +2 -2
- package/dist/agent-src/skills/performance-analysis/SKILL.md +2 -0
- package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +4 -4
- package/dist/agent-src/skills/premortem/SKILL.md +0 -3
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +16 -0
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +18 -0
- package/dist/agent-src/skills/react-shadcn-ui/reference/registry.md +59 -0
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +3 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +5 -1
- package/dist/agent-src/skills/release-comms/SKILL.md +47 -46
- package/dist/agent-src/skills/roadmap-management/SKILL.md +25 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +33 -3
- package/dist/agent-src/skills/root-cause-frameworks/SKILL.md +0 -3
- package/dist/agent-src/skills/script-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/security-audit/SKILL.md +1 -0
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -0
- package/dist/agent-src/skills/source-discovery/SKILL.md +22 -3
- package/dist/agent-src/skills/sql-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +33 -14
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +11 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-steps.md +8 -0
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +30 -1
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +4 -0
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/threat-modeling/SKILL.md +2 -2
- package/dist/agent-src/skills/token-optimizer/SKILL.md +1 -1
- package/dist/agent-src/skills/typography-system/SKILL.md +4 -3
- package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -0
- package/dist/agent-src/skills/wireframe/SKILL.md +118 -0
- package/dist/agent-src/skills/wireframe/evals/triggers.json +17 -0
- package/dist/agent-src/templates/agent-settings.md +22 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/command.md +2 -2
- package/dist/agent-src/templates/contexts/knowledge-pages.md +116 -0
- package/dist/agent-src/templates/hooks/pre-commit-frontmatter +1 -1
- package/dist/agent-src/templates/roadmaps.md +70 -2
- package/dist/agent-src/templates/rule.md +1 -1
- package/dist/agent-src/templates/scripts/README.md +3 -3
- package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +109 -0
- package/dist/agent-src/templates/tickets.md +8 -8
- package/dist/cli/commands/recordTriggerEval.test.js +1 -1
- package/dist/cli/commands/recordTriggerEval.test.js.map +1 -1
- package/dist/cli/initRouting.js +4 -2
- package/dist/cli/initRouting.js.map +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +802 -258
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +8 -8
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +46 -28
- package/dist/discovery/trust-report.md +12 -11
- package/dist/discovery/workspaces.json +32 -18
- package/dist/install/preflight.js +173 -0
- package/dist/install/preflight.js.map +1 -0
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/router.json +1 -1
- package/dist/server/routes/settings.js +4 -0
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/schemas/settings.js +6 -1
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/CLAIMS.md +108 -0
- package/docs/MIGRATION.md +3 -3
- package/docs/architecture.md +6 -6
- package/docs/benchmark.md +133 -2
- package/docs/benchmark.pinned.yml +31 -0
- package/docs/capability-matrix.md +1 -0
- package/docs/catalog.md +92 -74
- package/docs/command-flows.md +16 -4
- package/docs/comparison.yaml +35 -0
- package/docs/contracts/agents-layout.md +148 -0
- package/docs/contracts/brand-token-consumption.md +5 -0
- package/docs/contracts/capability-boundary.md +5 -0
- package/docs/contracts/command-category-governance.md +5 -0
- package/docs/contracts/command-clusters.md +1 -0
- package/docs/contracts/command-surface-tiers.md +1 -1
- package/docs/contracts/conformance.md +84 -0
- package/docs/contracts/creative-pack-boundary.md +5 -0
- package/docs/contracts/discovery-manifest.schema.json +5 -4
- package/docs/contracts/file-ownership-matrix.json +4605 -985
- package/docs/contracts/governance-enforcement-projection.md +5 -0
- package/docs/contracts/gui-wizard.md +1 -1
- package/docs/contracts/hook-architecture-v1.md +2 -2
- package/docs/contracts/implement-ticket-flow.md +1 -1
- package/docs/contracts/kernel-membership.md +13 -0
- package/docs/contracts/mcp-tool-inventory.md +23 -23
- package/docs/contracts/no-runtime-boundary.md +6 -1
- package/docs/contracts/review-lens-schema.md +5 -0
- package/docs/contracts/rule-router.md +102 -8
- package/docs/contracts/skill-bundled-assets.md +1 -1
- package/docs/contracts/skill-dry-run.md +1 -1
- package/docs/contracts/subagent-boundary.md +5 -0
- package/docs/contracts/ticket-bundle-format.md +9 -4
- package/docs/contracts/tier-3-contrib-plugin.md +2 -2
- package/docs/contracts/write-engine.md +3 -0
- package/docs/customization.md +87 -15
- package/docs/decisions/ADR-107-legal-domain-pack-adoption.md +1 -1
- package/docs/decisions/ADR-109-subagent-v1-contract.md +246 -0
- package/docs/decisions/ADR-110-discipline-profile-resolution-locus.md +105 -0
- package/docs/decisions/INDEX.md +2 -0
- package/docs/distribution/awesome-list-submission.md +46 -0
- package/docs/distribution/launch-story-draft.md +58 -0
- package/docs/end-to-end-walkthroughs.md +2 -2
- package/docs/getting-started.md +2 -2
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +24 -0
- package/docs/guidelines/agent-infra/corpus-grounding-authoring.md +1 -1
- package/docs/guidelines/agent-infra/linked-projects-onboarding-gate.md +2 -2
- package/docs/guidelines/agent-infra/missing-tool-handling.md +3 -3
- package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
- package/docs/guidelines/augment-portability-patterns.md +1 -1
- package/docs/guidelines/code-clarity.md +19 -0
- package/docs/guidelines/design-antipatterns-triggers.json +2 -1
- package/docs/guidelines/design-antipatterns.md +35 -0
- package/docs/guidelines/design-canon.md +62 -0
- package/docs/guidelines/design-modes.md +6 -0
- package/docs/guidelines/php/general.md +9 -1
- package/docs/guidelines/php/php-coding-patterns.md +7 -0
- package/docs/guides/cross-repo-retrieval.md +1 -1
- package/docs/guides/frontend-design-corpus-refresh.md +2 -2
- package/docs/guides/local-analytics.md +4 -4
- package/docs/guides/skill-discovery.md +1 -1
- package/docs/guides/skill-preview.md +1 -1
- package/docs/hook-payload-capture.md +6 -6
- package/docs/install-friction-report.md +66 -0
- package/docs/installation.md +1 -1
- package/docs/maintainers/optional-media-deps.md +50 -0
- package/docs/mcp-server.md +11 -12
- package/docs/media/proof-demo.cast +14 -0
- package/docs/media/proof-demo.gif +0 -0
- package/docs/migration/consumer-template-consumption-model.md +1 -1
- package/docs/migration/divergences/bench-stats-float-precision.md +1 -1
- package/docs/migration/node-floor.md +1 -1
- package/docs/migration/yaml-roundtrip-spike.md +1 -1
- package/docs/personas.md +16 -5
- package/docs/positioning-evidence.md +86 -0
- package/docs/proof.md +86 -0
- package/docs/skills-catalog.md +1 -1
- package/docs/troubleshooting.md +8 -8
- package/docs/wedge/production-validator/README.md +57 -0
- package/docs/wedge/production-validator/production-validator.md +56 -0
- package/docs/wizard.md +2 -2
- package/package.json +1 -1
- package/src/config/agent-settings.template.yml +71 -4
- package/src/config/agents-paths.yml +254 -0
- package/src/config/budgets.yml +16 -0
- package/src/config/discovery/packs.yml +1 -0
- package/src/config/discovery/unassigned-artefacts.yml +2 -0
- package/src/config/gitignore-block.txt +25 -0
- package/src/config/host-capabilities.yml +31 -0
- package/src/config/profiles/balanced.ini +4 -0
- package/src/config/profiles/full.ini +4 -0
- package/src/config/profiles/minimal.ini +4 -0
- package/src/scripts/_cli/cmd_conformance.ts +716 -0
- package/src/scripts/_cli/cmd_doctor.ts +23 -2
- package/src/scripts/_cli/cmd_fleet.ts +401 -0
- package/src/scripts/_cli/cmd_preflight.ts +159 -0
- package/src/scripts/_dispatch.bash +10 -0
- package/src/scripts/_lib/knowledge_events.ts +193 -0
- package/src/scripts/_lib/subagent_steering.ts +115 -3
- package/src/scripts/_lib/text_similarity.ts +75 -0
- package/src/scripts/ai-video/test-pipeline.sh +1 -1
- package/src/scripts/ai_council/clients.ts +19 -3
- package/src/scripts/append_contested.ts +112 -0
- package/src/scripts/audit_auto_rules.ts +11 -1
- package/src/scripts/audit_mcp_tools.ts +25 -11
- package/src/scripts/bench_ab_v2_run.ts +527 -40
- package/src/scripts/bench_ab_v2_stats.ts +6 -0
- package/src/scripts/bench_matrix.ts +266 -0
- package/src/scripts/bootstrap_knowledge.ts +267 -0
- package/src/scripts/build_discovery_manifest.ts +42 -2
- package/src/scripts/build_proof.ts +214 -0
- package/src/scripts/check_always_budget.ts +3 -0
- package/src/scripts/check_augment_description_cap.ts +2 -2
- package/src/scripts/check_claims.ts +270 -0
- package/src/scripts/check_comparison.ts +79 -0
- package/src/scripts/check_generated_artefact_headers.ts +109 -0
- package/src/scripts/check_generator_output_coverage.ts +142 -0
- package/src/scripts/check_gitignore_freshness.ts +127 -0
- package/src/scripts/check_knowledge_pages.ts +210 -0
- package/src/scripts/check_knowledge_sharing.ts +162 -0
- package/src/scripts/check_media_deps.ts +91 -0
- package/src/scripts/check_memory_contradiction.ts +280 -0
- package/src/scripts/check_memory_similarity.ts +134 -0
- package/src/scripts/check_quality_regression.ts +56 -10
- package/src/scripts/check_references.ts +3 -1
- package/src/scripts/check_release_pr_shape.ts +4 -0
- package/src/scripts/check_site_links.ts +135 -0
- package/src/scripts/check_skill_gaps.ts +99 -0
- package/src/scripts/check_token_quality_golden.ts +197 -11
- package/src/scripts/check_tracked_but_ignored.ts +67 -0
- package/src/scripts/cluster_near_miss_patterns.ts +0 -0
- package/src/scripts/compile_router.ts +30 -3
- package/src/scripts/condense.ts +350 -14
- package/src/scripts/consolidate_knowledge_events.ts +192 -0
- package/src/scripts/degrade_to_pointer.ts +136 -0
- package/src/scripts/design_slop_rules.test.ts +208 -0
- package/src/scripts/design_slop_rules.ts +530 -0
- package/src/scripts/emit_knowledge_event.ts +158 -0
- package/src/scripts/export_replay_corpus.ts +187 -0
- package/src/scripts/external_sources_denylist.json +14 -3
- package/src/scripts/fold_intake.ts +281 -0
- package/src/scripts/generate_capability_matrix.ts +9 -1
- package/src/scripts/generate_knowledge_index.ts +222 -0
- package/src/scripts/hook_manifest.yaml +40 -17
- package/src/scripts/hooks/design_slop_hook.ts +181 -0
- package/src/scripts/hooks/dispatch_hook.ts +18 -0
- package/src/scripts/hot_context_hook.ts +372 -0
- package/src/scripts/install +47 -0
- package/src/scripts/install-hooks.sh +17 -0
- package/src/scripts/inventory_meta_layers.ts +11 -0
- package/src/scripts/janitor.ts +258 -0
- package/src/scripts/lint_agent_security.ts +1 -0
- package/src/scripts/lint_agents_layout.ts +74 -15
- package/src/scripts/lint_bench_ab.ts +4 -1
- package/src/scripts/lint_confusables.ts +197 -0
- package/src/scripts/lint_design_slop.ts +245 -0
- package/src/scripts/lint_featured_skills.ts +0 -0
- package/src/scripts/lint_framework_leakage_allowlist.json +26 -3
- package/src/scripts/lint_knowledge_scale.ts +250 -0
- package/src/scripts/lint_legal_pack.ts +67 -0
- package/src/scripts/lint_persona_governance.ts +8 -3
- package/src/scripts/lint_regression.ts +15 -0
- package/src/scripts/lint_roadmap_blockers.ts +202 -0
- package/src/scripts/lint_roadmap_complexity.ts +81 -2
- package/src/scripts/lint_subagent_determinism.ts +125 -0
- package/src/scripts/measure_augment_budget.ts +46 -6
- package/src/scripts/measure_patterns.ts +4 -3
- package/src/scripts/measure_skill_reduction.ts +6 -6
- package/src/scripts/migration_status.ts +6 -2
- package/src/scripts/mine_missing_guardrails.ts +189 -0
- package/src/scripts/parity/phase_gate.ts +1 -1
- package/src/scripts/parity/replay.ts +21 -0
- package/src/scripts/project_thin_rules.ts +120 -16
- package/src/scripts/release.ts +39 -1
- package/src/scripts/render_benchmark_composite.ts +378 -0
- package/src/scripts/roadmap_progress_hook.ts +101 -43
- package/src/scripts/schemas/skill.schema.json +27 -0
- package/src/scripts/schemas/subagent.schema.json +106 -0
- package/src/scripts/skill_linter.ts +1 -0
- package/src/scripts/smoke/kernel.sh +5 -4
- package/src/scripts/surface-tiers.yml +1 -0
- package/src/scripts/sync_gitignore.ts +4 -0
- package/src/scripts/update_skill_candidates.ts +172 -0
- package/src/scripts/validate_frontmatter.ts +1 -0
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* design_slop_rules — the deterministic anti-slop rule registry.
|
|
4
|
+
*
|
|
5
|
+
* Data + matchers for the aesthetic-PROVENANCE tells that make a UI "look like
|
|
6
|
+
* an AI made it" — the layer `lint_design_quality` deliberately does NOT cover
|
|
7
|
+
* (it owns the OBJECTIVE floors: contrast, font-size, line-length, reduced-motion,
|
|
8
|
+
* heading hierarchy, focus). This registry is the deterministic backing for the
|
|
9
|
+
* PROSE catalog in `docs/guidelines/design-antipatterns.md`; every rule cites its
|
|
10
|
+
* catalog id (V1, C2, …) so prose ↔ rule stay traceable.
|
|
11
|
+
*
|
|
12
|
+
* DESIGN CONSTRAINT (why no postcss/@babel): this package ships to consumers via
|
|
13
|
+
* `npx` and is dependency-free by design (see lint_design_quality header). Heavy
|
|
14
|
+
* parsers (postcss/@babel/tailwind resolver) would bloat the install and break
|
|
15
|
+
* portability. The Phase-0 tells are all detectable by pattern analysis on
|
|
16
|
+
* CSS/HTML/JSX text without a cascade — we follow lint_design_quality's proven
|
|
17
|
+
* dependency-free approach. Council 2026-06-28 assumed those libs were present;
|
|
18
|
+
* for THIS package, pattern-based is the correct, frugal adaptation.
|
|
19
|
+
*
|
|
20
|
+
* Severity is a REBUTTABLE PRESUMPTION, never a hard block:
|
|
21
|
+
* P0 — objective failure (none here; those live in lint_design_quality)
|
|
22
|
+
* P1 — high-confidence tell (e.g. the side-stripe signature)
|
|
23
|
+
* P2 — confident tell
|
|
24
|
+
* P3 — co-occurrence / lower-confidence heuristic
|
|
25
|
+
* A rule is suppressed when the consumer's DESIGN.md declares the pattern as
|
|
26
|
+
* intentional (the context gate), via inline-ignore, or via .design-quality.json.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export type Severity = "P0" | "P1" | "P2" | "P3";
|
|
30
|
+
export type Engine = "css" | "html" | "jsx" | "copy";
|
|
31
|
+
|
|
32
|
+
export interface RawHit {
|
|
33
|
+
line: number;
|
|
34
|
+
snippet: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface DesignContext {
|
|
38
|
+
/** lowercased DESIGN.md text, or "" when absent */
|
|
39
|
+
raw: string;
|
|
40
|
+
/** true when DESIGN.md mentions any of the given keywords */
|
|
41
|
+
has(...keywords: string[]): boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface RuleInput {
|
|
45
|
+
content: string;
|
|
46
|
+
lines: string[];
|
|
47
|
+
ext: string; // e.g. ".css"
|
|
48
|
+
ctx: DesignContext;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SlopRule {
|
|
52
|
+
id: string; // e.g. "slop-v1-side-stripe"
|
|
53
|
+
catalogId: string; // e.g. "V1"
|
|
54
|
+
severity: Severity;
|
|
55
|
+
engines: Engine[];
|
|
56
|
+
description: string;
|
|
57
|
+
/** human-facing note on what to do — printed with the finding */
|
|
58
|
+
message: string;
|
|
59
|
+
/** suppress the rule entirely for this file when DESIGN.md declares intent */
|
|
60
|
+
gated?: (ctx: DesignContext) => boolean;
|
|
61
|
+
detect: (input: RuleInput) => RawHit[];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Shared helpers (pattern-based, dependency-free)
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
/** Split CSS-ish text into naive `selector { body }` blocks with the line of `{`. */
|
|
69
|
+
export function cssBlocks(content: string): Array<{ selector: string; body: string; line: number }> {
|
|
70
|
+
const blocks: Array<{ selector: string; body: string; line: number }> = [];
|
|
71
|
+
const re = /([^{}]+)\{([^{}]*)\}/g;
|
|
72
|
+
let m: RegExpExecArray | null;
|
|
73
|
+
while ((m = re.exec(content)) !== null) {
|
|
74
|
+
const before = content.slice(0, m.index);
|
|
75
|
+
const line = (before.match(/\n/g) ?? []).length + 1;
|
|
76
|
+
blocks.push({ selector: (m[1] ?? "").trim(), body: m[2] ?? "", line });
|
|
77
|
+
}
|
|
78
|
+
return blocks;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function lineOf(content: string, index: number): number {
|
|
82
|
+
return (content.slice(0, index).match(/\n/g) ?? []).length + 1;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Visible text from HTML/JSX/Markdown: strip tags, code fences, attributes. */
|
|
86
|
+
export function visibleText(content: string, ext: string): string {
|
|
87
|
+
let t = content;
|
|
88
|
+
if (ext === ".md" || ext === ".mdx") {
|
|
89
|
+
t = t.replace(/```[\s\S]*?```/g, " ").replace(/`[^`]*`/g, " ");
|
|
90
|
+
}
|
|
91
|
+
// strip HTML/JSX tags and JSX expression braces
|
|
92
|
+
t = t.replace(/<[^>]+>/g, " ").replace(/\{[^}]*\}/g, " ");
|
|
93
|
+
return t;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Coarse HSL hue bucket (0–11, 30° each) from a #rgb/#rrggbb hex; null if grayscale/near-black/near-white (not an accent). */
|
|
97
|
+
export function hueBucket(hex: string): number | null {
|
|
98
|
+
const m = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
99
|
+
if (!m) return null;
|
|
100
|
+
let h = m[1] ?? "";
|
|
101
|
+
if (h.length === 3) {
|
|
102
|
+
h = h
|
|
103
|
+
.split("")
|
|
104
|
+
.map((c) => c + c)
|
|
105
|
+
.join("");
|
|
106
|
+
}
|
|
107
|
+
const r = parseInt(h.slice(0, 2), 16) / 255;
|
|
108
|
+
const g = parseInt(h.slice(2, 4), 16) / 255;
|
|
109
|
+
const b = parseInt(h.slice(4, 6), 16) / 255;
|
|
110
|
+
const max = Math.max(r, g, b);
|
|
111
|
+
const min = Math.min(r, g, b);
|
|
112
|
+
const d = max - min;
|
|
113
|
+
const l = (max + min) / 2;
|
|
114
|
+
const s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
|
|
115
|
+
if (s < 0.25 || l < 0.12 || l > 0.95) return null; // grayscale / near-black / near-white
|
|
116
|
+
let hue = 0;
|
|
117
|
+
if (max === r) hue = ((g - b) / d) % 6;
|
|
118
|
+
else if (max === g) hue = (b - r) / d + 2;
|
|
119
|
+
else hue = (r - g) / d + 4;
|
|
120
|
+
hue *= 60;
|
|
121
|
+
if (hue < 0) hue += 360;
|
|
122
|
+
return Math.floor(hue / 30) % 12;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Approximate `<section>` bodies for layout-cap rules (no recursion; coarse, deterministic). */
|
|
126
|
+
export function sectionBodies(content: string): string[] {
|
|
127
|
+
const starts: number[] = [];
|
|
128
|
+
const re = /<section\b|<Section\b/gi;
|
|
129
|
+
let m: RegExpExecArray | null;
|
|
130
|
+
while ((m = re.exec(content)) !== null) starts.push(m.index);
|
|
131
|
+
if (starts.length === 0) return [];
|
|
132
|
+
const bodies: string[] = [];
|
|
133
|
+
for (let i = 0; i < starts.length; i++) {
|
|
134
|
+
const end = i + 1 < starts.length ? starts[i + 1]! : content.length;
|
|
135
|
+
bodies.push(content.slice(starts[i]!, end));
|
|
136
|
+
}
|
|
137
|
+
return bodies;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Coarse structural signature of a section body (for monotony / zigzag caps). */
|
|
141
|
+
function sectionSignature(body: string): { sig: string; mediaText: boolean } {
|
|
142
|
+
const img = /<img\b|<picture\b|<Image\b|background-image/i.test(body);
|
|
143
|
+
const grid = /\b(flex|grid|grid-cols|col-span|md:flex|lg:grid)\b/i.test(body);
|
|
144
|
+
const heading = /<h[1-6]\b/i.test(body);
|
|
145
|
+
const text = heading || /<(p|li)\b/i.test(body);
|
|
146
|
+
const blocks = Math.min((body.match(/<div\b/gi) ?? []).length, 5);
|
|
147
|
+
return { sig: `${img ? "I" : ""}${grid ? "G" : ""}${heading ? "H" : ""}${blocks}`, mediaText: img && text && grid };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const DEFAULT_FONTS = [
|
|
151
|
+
"inter",
|
|
152
|
+
"roboto",
|
|
153
|
+
"dm sans",
|
|
154
|
+
"geist",
|
|
155
|
+
"space grotesk",
|
|
156
|
+
"instrument serif",
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
const BUZZWORDS = [
|
|
160
|
+
"streamline",
|
|
161
|
+
"empower",
|
|
162
|
+
"supercharge",
|
|
163
|
+
"world-class",
|
|
164
|
+
"enterprise-grade",
|
|
165
|
+
"seamlessly",
|
|
166
|
+
"robust",
|
|
167
|
+
"leverage",
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
// The registry
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
|
|
174
|
+
export const SLOP_RULES: SlopRule[] = [
|
|
175
|
+
{
|
|
176
|
+
id: "slop-v1-side-stripe",
|
|
177
|
+
catalogId: "V1",
|
|
178
|
+
severity: "P1",
|
|
179
|
+
engines: ["css"],
|
|
180
|
+
description: "Colored side-stripe border (border-left/right > 1px) — the #1 AI-UI signature",
|
|
181
|
+
message:
|
|
182
|
+
"Side-stripe accent border reads as scaffold-default. Remove it, or declare an intentional stripe in DESIGN.md (V1).",
|
|
183
|
+
gated: (ctx) => ctx.has("side stripe", "side-stripe", "stripe accent", "accent border"),
|
|
184
|
+
detect: ({ content }) =>
|
|
185
|
+
cssBlocks(content)
|
|
186
|
+
// a side-stripe is a left/right border with a width > 1px and a color;
|
|
187
|
+
// exclude semantic blockquote/quote selectors (legitimate left rule)
|
|
188
|
+
.filter((b) => !/blockquote|\bquote\b|<q>/i.test(b.selector))
|
|
189
|
+
.filter((b) =>
|
|
190
|
+
/border-(?:left|right)\s*:\s*(?:[2-9]|\d{2,})px\s+\w+\s+(?:#|rgb|hsl|oklch|var\(|[a-z])/i.test(
|
|
191
|
+
b.body,
|
|
192
|
+
),
|
|
193
|
+
)
|
|
194
|
+
.map((b) => ({ line: b.line, snippet: b.selector.slice(0, 80) })),
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
id: "slop-v3-ghost-card",
|
|
198
|
+
catalogId: "V3",
|
|
199
|
+
severity: "P2",
|
|
200
|
+
engines: ["css"],
|
|
201
|
+
description: "Ghost card: 1px border AND a ≥16px box-shadow on the same surface",
|
|
202
|
+
message:
|
|
203
|
+
"Border + heavy shadow together signal no confident depth decision. Choose one (V3).",
|
|
204
|
+
detect: ({ content }) =>
|
|
205
|
+
cssBlocks(content)
|
|
206
|
+
.filter(
|
|
207
|
+
(b) =>
|
|
208
|
+
/border\s*:\s*1px\s+solid/i.test(b.body) &&
|
|
209
|
+
/box-shadow\s*:[^;]*?(?:1[6-9]|[2-9]\d)px/i.test(b.body),
|
|
210
|
+
)
|
|
211
|
+
.map((b) => ({ line: b.line, snippet: b.selector.slice(0, 80) })),
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: "slop-v6-diagonal-stripes",
|
|
215
|
+
catalogId: "V6",
|
|
216
|
+
severity: "P2",
|
|
217
|
+
engines: ["css"],
|
|
218
|
+
description: "repeating-linear-gradient stripes as a background texture",
|
|
219
|
+
message: "Repeating diagonal stripes are a generated-CSS-art cliché (V6).",
|
|
220
|
+
gated: (ctx) => ctx.has("pattern background", "pattern-background", "stripe texture"),
|
|
221
|
+
detect: ({ lines }) =>
|
|
222
|
+
lines.flatMap((l, i) =>
|
|
223
|
+
/background[^;]*repeating-linear-gradient\s*\(/i.test(l)
|
|
224
|
+
? [{ line: i + 1, snippet: l.trim().slice(0, 90) }]
|
|
225
|
+
: [],
|
|
226
|
+
),
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
id: "slop-c2-gradient-text",
|
|
230
|
+
catalogId: "C2",
|
|
231
|
+
severity: "P2",
|
|
232
|
+
engines: ["css"],
|
|
233
|
+
description: "Gradient text via background-clip: text",
|
|
234
|
+
message:
|
|
235
|
+
"Gradient text via background-clip:text is overused and has cross-platform rendering edges (C2).",
|
|
236
|
+
gated: (ctx) => ctx.has("gradient identity", "gradient-identity", "gradient logo"),
|
|
237
|
+
detect: ({ content }) =>
|
|
238
|
+
cssBlocks(content)
|
|
239
|
+
.filter(
|
|
240
|
+
(b) =>
|
|
241
|
+
/background-clip\s*:\s*text|-webkit-background-clip\s*:\s*text/i.test(b.body) &&
|
|
242
|
+
/linear-gradient|radial-gradient|conic-gradient/i.test(b.body),
|
|
243
|
+
)
|
|
244
|
+
.map((b) => ({ line: b.line, snippet: b.selector.slice(0, 80) })),
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: "slop-c5-cream-palette",
|
|
248
|
+
catalogId: "C5",
|
|
249
|
+
severity: "P3",
|
|
250
|
+
engines: ["css"],
|
|
251
|
+
description: "Cream/sand background + brass/clay/oxblood accent — the 2025 'premium-consumer' AI palette",
|
|
252
|
+
message:
|
|
253
|
+
"Warm cream/sand + brass/clay is the default 'tasteful AI' surface. Confirm it is first-party in DESIGN.md (C5).",
|
|
254
|
+
gated: (ctx) => ctx.has("warm neutral", "warm-neutral", "cream", "sand", "premium consumer"),
|
|
255
|
+
detect: ({ content }) => {
|
|
256
|
+
const cream = /#f[5-9bdf][f0-9a-f]e[0-9a-f]|#fbf8f1|#f7f5f1|#f5f1ea/i.test(content);
|
|
257
|
+
const brass = /#b08947|#b6553a|#9a2436|brass|oxblood|terracotta|clay/i.test(content);
|
|
258
|
+
if (!cream || !brass) return [];
|
|
259
|
+
const idx = content.search(/#f[5-9bdf][f0-9a-f]e[0-9a-f]|#fbf8f1|#f7f5f1|#f5f1ea/i);
|
|
260
|
+
return [{ line: lineOf(content, Math.max(0, idx)), snippet: "cream/sand bg + warm accent co-occur" }];
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
id: "slop-t4-eyebrow-overuse",
|
|
265
|
+
catalogId: "T4",
|
|
266
|
+
severity: "P2",
|
|
267
|
+
engines: ["html", "jsx", "css"],
|
|
268
|
+
description: "More than one ALL-CAPS eyebrow per 3 sections",
|
|
269
|
+
message:
|
|
270
|
+
"Eyebrow/ALL-CAPS labels above every section collapse emphasis; cap is 1 per 3 sections (T4).",
|
|
271
|
+
detect: ({ content }) => {
|
|
272
|
+
const sections = (content.match(/<section\b|<Section\b/gi) ?? []).length;
|
|
273
|
+
const eyebrows =
|
|
274
|
+
(content.match(/text-transform\s*:\s*uppercase/gi) ?? []).length +
|
|
275
|
+
(content.match(/(?:class|className)=["'][^"']*\buppercase\b/gi) ?? []).length;
|
|
276
|
+
const cap = Math.max(1, Math.ceil(sections / 3));
|
|
277
|
+
if (sections >= 3 && eyebrows > cap) {
|
|
278
|
+
return [
|
|
279
|
+
{
|
|
280
|
+
line: 1,
|
|
281
|
+
snippet: `${eyebrows} uppercase eyebrows across ${sections} sections (cap ${cap})`,
|
|
282
|
+
},
|
|
283
|
+
];
|
|
284
|
+
}
|
|
285
|
+
return [];
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
id: "slop-t6-crushed-tracking",
|
|
290
|
+
catalogId: "T6",
|
|
291
|
+
severity: "P2",
|
|
292
|
+
engines: ["css"],
|
|
293
|
+
description: "Crushed display letter-spacing below −0.04em",
|
|
294
|
+
message: "letter-spacing tighter than −0.04em makes glyphs collide optically (T6/Q7).",
|
|
295
|
+
detect: ({ lines }) =>
|
|
296
|
+
lines.flatMap((l, i) => {
|
|
297
|
+
const m = /letter-spacing\s*:\s*(-?\d*\.?\d+)\s*em/i.exec(l);
|
|
298
|
+
if (m && m[1] && parseFloat(m[1]) < -0.04) {
|
|
299
|
+
return [{ line: i + 1, snippet: l.trim().slice(0, 80) }];
|
|
300
|
+
}
|
|
301
|
+
return [];
|
|
302
|
+
}),
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: "slop-t7-default-fonts",
|
|
306
|
+
catalogId: "T7",
|
|
307
|
+
severity: "P2",
|
|
308
|
+
engines: ["css"],
|
|
309
|
+
description: "Default AI font (Inter/Roboto/DM Sans/Geist/Space Grotesk/Instrument Serif) without a brand reason",
|
|
310
|
+
message:
|
|
311
|
+
"This is a default AI-coding-tool font pick. Declare it in DESIGN.md with a reason, or choose deliberately (T7).",
|
|
312
|
+
gated: (ctx) => DEFAULT_FONTS.some((f) => ctx.has(f)),
|
|
313
|
+
detect: ({ lines }) =>
|
|
314
|
+
lines.flatMap((l, i) => {
|
|
315
|
+
if (!/font-family\s*:/i.test(l)) return [];
|
|
316
|
+
const lower = l.toLowerCase();
|
|
317
|
+
const hit = DEFAULT_FONTS.find((f) => lower.includes(f));
|
|
318
|
+
return hit ? [{ line: i + 1, snippet: l.trim().slice(0, 80) }] : [];
|
|
319
|
+
}),
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
id: "slop-l4-numbered-markers",
|
|
323
|
+
catalogId: "L4",
|
|
324
|
+
severity: "P3",
|
|
325
|
+
engines: ["html", "jsx"],
|
|
326
|
+
description: "Numbered section markers (01 / 02 / 03) as a decorative order device",
|
|
327
|
+
message:
|
|
328
|
+
"Numbered 01/02/03 section markers are a universal generated-landing-page tell (L4).",
|
|
329
|
+
detect: ({ content, ext }) => {
|
|
330
|
+
const text = visibleText(content, ext);
|
|
331
|
+
const markers = text.match(/(?<![\d/.])0[1-9](?![\d%])/g) ?? [];
|
|
332
|
+
const distinct = new Set(markers.map((s) => s.trim()));
|
|
333
|
+
if (distinct.has("01") && distinct.has("02") && distinct.has("03")) {
|
|
334
|
+
return [{ line: 1, snippet: "decorative 01/02/03 section markers" }];
|
|
335
|
+
}
|
|
336
|
+
return [];
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
id: "slop-l8-zindex-magic",
|
|
341
|
+
catalogId: "L8",
|
|
342
|
+
severity: "P2",
|
|
343
|
+
engines: ["css"],
|
|
344
|
+
description: "Magic z-index values (99 / 999 / 9999) with no semantic scale",
|
|
345
|
+
message: "Magic z-index breaks the first time two elements compete. Use a named scale (L8).",
|
|
346
|
+
detect: ({ lines }) =>
|
|
347
|
+
lines.flatMap((l, i) =>
|
|
348
|
+
/z-index\s*:\s*(?:99|999|9999)\b/i.test(l) ? [{ line: i + 1, snippet: l.trim().slice(0, 80) }] : [],
|
|
349
|
+
),
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
id: "slop-m4-transition-all",
|
|
353
|
+
catalogId: "M4",
|
|
354
|
+
severity: "P2",
|
|
355
|
+
engines: ["css"],
|
|
356
|
+
description: "transition: all shorthand",
|
|
357
|
+
message: "transition:all animates layout/color/opacity together — unpredictable + expensive (M4).",
|
|
358
|
+
detect: ({ lines }) =>
|
|
359
|
+
lines.flatMap((l, i) =>
|
|
360
|
+
/transition\s*:\s*all\b/i.test(l) ? [{ line: i + 1, snippet: l.trim().slice(0, 80) }] : [],
|
|
361
|
+
),
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
id: "slop-m2-animate-layout",
|
|
365
|
+
catalogId: "M2",
|
|
366
|
+
severity: "P2",
|
|
367
|
+
engines: ["css"],
|
|
368
|
+
description: "Transitioning layout properties (width/height/top/left/margin/padding)",
|
|
369
|
+
message: "Animating layout props forces reflow; use transform instead (M2).",
|
|
370
|
+
detect: ({ lines }) =>
|
|
371
|
+
lines.flatMap((l, i) =>
|
|
372
|
+
/transition\s*:\s*(?:[^;]*\b)?(?:width|height|top|left|right|bottom|margin|padding)\b[^;]*\d/i.test(l)
|
|
373
|
+
? [{ line: i + 1, snippet: l.trim().slice(0, 80) }]
|
|
374
|
+
: [],
|
|
375
|
+
),
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
id: "slop-cp1-em-dash",
|
|
379
|
+
catalogId: "CP1",
|
|
380
|
+
severity: "P2",
|
|
381
|
+
engines: ["copy"],
|
|
382
|
+
description: "Em-dash overuse in visible copy (> 2 per 500 words)",
|
|
383
|
+
message: "Em-dash density above ~2 per 500 words is the #1 LLM syntactic tell (CP1).",
|
|
384
|
+
detect: ({ content, ext }) => {
|
|
385
|
+
const text = visibleText(content, ext);
|
|
386
|
+
const words = (text.match(/\S+/g) ?? []).length;
|
|
387
|
+
const dashes = (text.match(/—/g) ?? []).length;
|
|
388
|
+
if (words >= 80 && dashes > Math.max(2, Math.round((words / 500) * 2))) {
|
|
389
|
+
return [{ line: 1, snippet: `${dashes} em-dashes in ~${words} words` }];
|
|
390
|
+
}
|
|
391
|
+
return [];
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
id: "slop-cp2-buzzword",
|
|
396
|
+
catalogId: "CP2",
|
|
397
|
+
severity: "P2",
|
|
398
|
+
engines: ["copy"],
|
|
399
|
+
description: "Marketing buzzwords (streamline/empower/supercharge/world-class/…)",
|
|
400
|
+
message: "These words carry no information — delete-test each one (CP2).",
|
|
401
|
+
detect: ({ content, ext }) => {
|
|
402
|
+
const text = visibleText(content, ext);
|
|
403
|
+
const lower = text.toLowerCase();
|
|
404
|
+
const hits = BUZZWORDS.filter((w) => new RegExp(`\\b${w}\\b`, "i").test(lower));
|
|
405
|
+
if (hits.length > 0) {
|
|
406
|
+
return [{ line: 1, snippet: `buzzwords: ${hits.join(", ")}` }];
|
|
407
|
+
}
|
|
408
|
+
return [];
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: "slop-cp5-emoji-ui",
|
|
413
|
+
catalogId: "CP5",
|
|
414
|
+
severity: "P2",
|
|
415
|
+
engines: ["html", "jsx"],
|
|
416
|
+
description: "Emoji-decoration prepending headings, buttons, list items, or CTAs",
|
|
417
|
+
message:
|
|
418
|
+
"Emoji-prepended UI text (🚀 Get Started) is the default-startup-template tell — no emoji beats decorative emoji (CP5). Functional status/category emojis and brand-declared emoji strategies are exempt.",
|
|
419
|
+
gated: (ctx) => ctx.has("emoji"),
|
|
420
|
+
detect: ({ content }) => {
|
|
421
|
+
// Emoji as the FIRST visible character inside a heading, button, list
|
|
422
|
+
// item, or link — decoration position. Emojis elsewhere (mid-sentence,
|
|
423
|
+
// table cells, status chips) are not matched: those are the functional
|
|
424
|
+
// placements CP5 explicitly exempts.
|
|
425
|
+
const re =
|
|
426
|
+
/<(h[1-6]|button|li|a)\b[^>]*>\s*(?:<(?!\/)[^>]*>\s*)*(\p{Extended_Pictographic})/giu;
|
|
427
|
+
const hits: RawHit[] = [];
|
|
428
|
+
let m: RegExpExecArray | null;
|
|
429
|
+
while ((m = re.exec(content)) !== null) {
|
|
430
|
+
const before = content.slice(0, m.index);
|
|
431
|
+
hits.push({
|
|
432
|
+
line: (before.match(/\n/g) ?? []).length + 1,
|
|
433
|
+
snippet: content.slice(m.index, m.index + 60).replace(/\n/g, " "),
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
return hits;
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
id: "slop-lock-shape",
|
|
441
|
+
catalogId: "V8",
|
|
442
|
+
severity: "P2",
|
|
443
|
+
engines: ["css"],
|
|
444
|
+
description: "Shape Lock — too many distinct corner-radius scales",
|
|
445
|
+
message: "Mixed corner-radius scales fragment the shape system; lock one scale (V8 / Shape Lock).",
|
|
446
|
+
gated: (ctx) => ctx.has("shape lock"),
|
|
447
|
+
detect: ({ content }) => {
|
|
448
|
+
const vals = new Set<number>();
|
|
449
|
+
for (const m of content.matchAll(/border-radius\s*:\s*([^;}]+)/gi)) {
|
|
450
|
+
for (const pm of (m[1] ?? "").matchAll(/(\d+(?:\.\d+)?)px/gi)) {
|
|
451
|
+
const v = parseFloat(pm[1] ?? "0");
|
|
452
|
+
if (v > 0 && v < 9990) vals.add(v);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (vals.size >= 4) {
|
|
456
|
+
const idx = content.search(/border-radius/i);
|
|
457
|
+
return [
|
|
458
|
+
{
|
|
459
|
+
line: lineOf(content, Math.max(0, idx)),
|
|
460
|
+
snippet: `${vals.size} distinct radius values: ${[...vals].sort((a, b) => a - b).join("/")}px`,
|
|
461
|
+
},
|
|
462
|
+
];
|
|
463
|
+
}
|
|
464
|
+
return [];
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
id: "slop-lock-colour",
|
|
469
|
+
catalogId: "C6",
|
|
470
|
+
severity: "P3",
|
|
471
|
+
engines: ["css"],
|
|
472
|
+
description: "Colour Lock — multiple saturated accent hue families",
|
|
473
|
+
message: "Several accent hue families read as no single accent identity; lock one (C6 / Colour Lock).",
|
|
474
|
+
gated: (ctx) => ctx.has("colour lock", "color lock"),
|
|
475
|
+
detect: ({ content }) => {
|
|
476
|
+
const buckets = new Set<number>();
|
|
477
|
+
for (const pm of content.matchAll(/#([0-9a-f]{3}|[0-9a-f]{6})\b/gi)) {
|
|
478
|
+
const b = hueBucket("#" + (pm[1] ?? ""));
|
|
479
|
+
if (b !== null) buckets.add(b);
|
|
480
|
+
}
|
|
481
|
+
if (buckets.size >= 3) {
|
|
482
|
+
const idx = content.search(/#[0-9a-f]{3,6}\b/i);
|
|
483
|
+
return [{ line: lineOf(content, Math.max(0, idx)), snippet: `${buckets.size} distinct accent hue families` }];
|
|
484
|
+
}
|
|
485
|
+
return [];
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
id: "slop-l9-section-monotony",
|
|
490
|
+
catalogId: "L9",
|
|
491
|
+
severity: "P3",
|
|
492
|
+
engines: ["html", "jsx"],
|
|
493
|
+
description: "Section-layout monotony — too few distinct layout families across many sections",
|
|
494
|
+
message: "Many sections but few distinct layouts → monotonous rhythm; vary the composition (L9).",
|
|
495
|
+
gated: (ctx) => ctx.has("brutalist", "uniform grid", "repetitive grid"),
|
|
496
|
+
detect: ({ content }) => {
|
|
497
|
+
const bodies = sectionBodies(content);
|
|
498
|
+
if (bodies.length < 8) return [];
|
|
499
|
+
const sigs = new Set(bodies.map((b) => sectionSignature(b).sig));
|
|
500
|
+
if (sigs.size < 4) {
|
|
501
|
+
return [{ line: 1, snippet: `${bodies.length} sections, only ${sigs.size} distinct layout families` }];
|
|
502
|
+
}
|
|
503
|
+
return [];
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
id: "slop-l10-zigzag",
|
|
508
|
+
catalogId: "L10",
|
|
509
|
+
severity: "P3",
|
|
510
|
+
engines: ["html", "jsx"],
|
|
511
|
+
description: "Zigzag alternation — more than two consecutive media+text two-column sections",
|
|
512
|
+
message: "More than two consecutive image+text two-column sections is the alternating-zigzag tell (L10).",
|
|
513
|
+
gated: (ctx) => ctx.has("brutalist", "uniform grid", "repetitive grid"),
|
|
514
|
+
detect: ({ content }) => {
|
|
515
|
+
const bodies = sectionBodies(content);
|
|
516
|
+
let run = 0;
|
|
517
|
+
let maxRun = 0;
|
|
518
|
+
for (const b of bodies) {
|
|
519
|
+
if (sectionSignature(b).mediaText) {
|
|
520
|
+
run += 1;
|
|
521
|
+
maxRun = Math.max(maxRun, run);
|
|
522
|
+
} else {
|
|
523
|
+
run = 0;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
if (maxRun > 2) return [{ line: 1, snippet: `${maxRun} consecutive media+text sections` }];
|
|
527
|
+
return [];
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
];
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* CLI wrapper for `appendEvent` (src/scripts/_lib/knowledge_events.ts) —
|
|
4
|
+
* road-to-knowledge-system Phase 5. This is the actual command an agent
|
|
5
|
+
* runs to append a typed observation event; the `_lib` module holds the
|
|
6
|
+
* pure schema + validation logic only (this repo's convention: `_lib/`
|
|
7
|
+
* files are never directly invoked).
|
|
8
|
+
*
|
|
9
|
+
* Usage (one flag set per event type — see --help for the full list):
|
|
10
|
+
* emit_knowledge_event.ts --type convention_detected --pattern "<p>" --evidence "file:line" [--evidence "file:line" ...] --sample-size N --scope project|global
|
|
11
|
+
* emit_knowledge_event.ts --type mistake_made --error-category "<c>" --context-source "<path>|null" --correction "<text>" --recurrence-key "<key>"
|
|
12
|
+
* emit_knowledge_event.ts --type api_shape_learned --endpoint "<path>" --method "<verb>" --request-schema "<json>" --response-schema "<json>"
|
|
13
|
+
* emit_knowledge_event.ts --type context_stale --page-path "<path>" --field "<field>" --expected "<text>" --actual "<text>" --evidence "<text>"
|
|
14
|
+
*
|
|
15
|
+
* Exit codes: 0 = appended, 1 = usage / validation error.
|
|
16
|
+
*/
|
|
17
|
+
import process from 'node:process';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
|
|
21
|
+
import { appendEvent, type KnowledgeEvent } from './_lib/knowledge_events.js';
|
|
22
|
+
|
|
23
|
+
const PROG = 'emit_knowledge_event.ts';
|
|
24
|
+
|
|
25
|
+
function printUsage(): void {
|
|
26
|
+
process.stdout.write(
|
|
27
|
+
[
|
|
28
|
+
`usage: ${PROG} --type TYPE [type-specific flags]`,
|
|
29
|
+
'',
|
|
30
|
+
' --type convention_detected --pattern P --evidence E [--evidence E ...] --sample-size N --scope project|global',
|
|
31
|
+
' --type mistake_made --error-category C --context-source PATH|null --correction TEXT --recurrence-key KEY',
|
|
32
|
+
' --type api_shape_learned --endpoint PATH --method VERB --request-schema JSON --response-schema JSON',
|
|
33
|
+
' --type context_stale --page-path PATH --field FIELD --expected TEXT --actual TEXT --evidence TEXT',
|
|
34
|
+
'',
|
|
35
|
+
].join('\n'),
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function parseFlags(argv: string[]): Map<string, string[]> {
|
|
40
|
+
const flags = new Map<string, string[]>();
|
|
41
|
+
for (let i = 0; i < argv.length; i++) {
|
|
42
|
+
const arg = argv[i];
|
|
43
|
+
if (arg === undefined || !arg.startsWith('--')) continue;
|
|
44
|
+
const key = arg.slice(2);
|
|
45
|
+
const value = argv[++i] ?? '';
|
|
46
|
+
const existing = flags.get(key) ?? [];
|
|
47
|
+
existing.push(value);
|
|
48
|
+
flags.set(key, existing);
|
|
49
|
+
}
|
|
50
|
+
return flags;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function one(flags: Map<string, string[]>, key: string): string | null {
|
|
54
|
+
return flags.get(key)?.[0] ?? null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function main(argv: string[]): number {
|
|
58
|
+
if (argv.includes('-h') || argv.includes('--help')) {
|
|
59
|
+
printUsage();
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const flags = parseFlags(argv);
|
|
64
|
+
const type = one(flags, 'type');
|
|
65
|
+
const ts = new Date().toISOString();
|
|
66
|
+
|
|
67
|
+
let event: KnowledgeEvent;
|
|
68
|
+
try {
|
|
69
|
+
switch (type) {
|
|
70
|
+
case 'convention_detected': {
|
|
71
|
+
const pattern = one(flags, 'pattern');
|
|
72
|
+
const evidence = flags.get('evidence') ?? [];
|
|
73
|
+
const sampleSizeRaw = one(flags, 'sample-size');
|
|
74
|
+
const scope = one(flags, 'scope');
|
|
75
|
+
if (!pattern || evidence.length === 0 || !sampleSizeRaw || (scope !== 'project' && scope !== 'global')) {
|
|
76
|
+
throw new Error('missing/invalid --pattern, --evidence, --sample-size, or --scope');
|
|
77
|
+
}
|
|
78
|
+
event = {
|
|
79
|
+
type: 'convention_detected',
|
|
80
|
+
ts,
|
|
81
|
+
pattern,
|
|
82
|
+
evidence,
|
|
83
|
+
sampleSize: Number.parseInt(sampleSizeRaw, 10),
|
|
84
|
+
scope,
|
|
85
|
+
};
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case 'mistake_made': {
|
|
89
|
+
const errorCategory = one(flags, 'error-category');
|
|
90
|
+
const contextSourceRaw = one(flags, 'context-source');
|
|
91
|
+
const correction = one(flags, 'correction');
|
|
92
|
+
const recurrenceKey = one(flags, 'recurrence-key');
|
|
93
|
+
if (!errorCategory || contextSourceRaw === null || !correction || !recurrenceKey) {
|
|
94
|
+
throw new Error('missing --error-category, --context-source, --correction, or --recurrence-key');
|
|
95
|
+
}
|
|
96
|
+
event = {
|
|
97
|
+
type: 'mistake_made',
|
|
98
|
+
ts,
|
|
99
|
+
errorCategory,
|
|
100
|
+
contextSource: contextSourceRaw === 'null' ? null : contextSourceRaw,
|
|
101
|
+
correction,
|
|
102
|
+
recurrenceKey,
|
|
103
|
+
};
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case 'api_shape_learned': {
|
|
107
|
+
const endpoint = one(flags, 'endpoint');
|
|
108
|
+
const method = one(flags, 'method');
|
|
109
|
+
const requestSchemaRaw = one(flags, 'request-schema');
|
|
110
|
+
const responseSchemaRaw = one(flags, 'response-schema');
|
|
111
|
+
if (!endpoint || !method || requestSchemaRaw === null || responseSchemaRaw === null) {
|
|
112
|
+
throw new Error('missing --endpoint, --method, --request-schema, or --response-schema');
|
|
113
|
+
}
|
|
114
|
+
event = {
|
|
115
|
+
type: 'api_shape_learned',
|
|
116
|
+
ts,
|
|
117
|
+
endpoint,
|
|
118
|
+
method,
|
|
119
|
+
requestSchema: JSON.parse(requestSchemaRaw),
|
|
120
|
+
responseSchema: JSON.parse(responseSchemaRaw),
|
|
121
|
+
};
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
case 'context_stale': {
|
|
125
|
+
const pagePath = one(flags, 'page-path');
|
|
126
|
+
const field = one(flags, 'field');
|
|
127
|
+
const expected = one(flags, 'expected');
|
|
128
|
+
const actual = one(flags, 'actual');
|
|
129
|
+
const evidence = one(flags, 'evidence');
|
|
130
|
+
if (!pagePath || !field || expected === null || actual === null || !evidence) {
|
|
131
|
+
throw new Error('missing --page-path, --field, --expected, --actual, or --evidence');
|
|
132
|
+
}
|
|
133
|
+
event = { type: 'context_stale', ts, pagePath, field, expected, actual, evidence };
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
default:
|
|
137
|
+
throw new Error(`--type must be one of convention_detected|mistake_made|api_shape_learned|context_stale (got "${type}")`);
|
|
138
|
+
}
|
|
139
|
+
} catch (err) {
|
|
140
|
+
process.stderr.write(`${PROG}: error: ${(err as Error).message}\n`);
|
|
141
|
+
printUsage();
|
|
142
|
+
return 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
appendEvent(event);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
process.stderr.write(`${PROG}: error: ${(err as Error).message}\n`);
|
|
149
|
+
return 1;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
process.stdout.write(`${PROG}: appended ${type} event to agents/knowledge/intake/.\n`);
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (fileURLToPath(import.meta.url) === path.resolve(process.argv[1] ?? '')) {
|
|
157
|
+
process.exit(main(process.argv.slice(2)));
|
|
158
|
+
}
|