@design-ai/cli 4.55.0 → 4.57.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/plugin.json +109 -25
- package/CHANGELOG.md +75 -0
- package/README.ko.md +15 -32
- package/README.md +18 -31
- package/cli/bin/design-ai.mjs +1 -0
- package/cli/commands/help.mjs +7 -4
- package/cli/commands/index.mjs +292 -0
- package/cli/commands/learn-help.mjs +149 -0
- package/cli/commands/learn-print-profile.mjs +373 -0
- package/cli/commands/learn-print-restore.mjs +349 -0
- package/cli/commands/learn-print-signals.mjs +453 -0
- package/cli/commands/learn.mjs +60 -1281
- package/cli/commands/pack.mjs +7 -3
- package/cli/commands/prompt.mjs +7 -3
- package/cli/commands/search.mjs +94 -1
- package/cli/lib/dispatch.mjs +3 -0
- package/cli/lib/embedding-index.mjs +199 -0
- package/cli/lib/embedding-provider.mjs +121 -0
- package/cli/lib/embedding-rerank.mjs +52 -0
- package/cli/lib/learn-args.mjs +490 -0
- package/cli/lib/learn-backup.mjs +748 -0
- package/cli/lib/learn-curation.mjs +612 -0
- package/cli/lib/learn-eval.mjs +459 -0
- package/cli/lib/learn-profile.mjs +763 -0
- package/cli/lib/learn-select.mjs +223 -0
- package/cli/lib/learn-shared.mjs +158 -0
- package/cli/lib/learn-test-support.mjs +218 -0
- package/cli/lib/learn-usage.mjs +360 -0
- package/cli/lib/learn.mjs +83 -3694
- package/cli/lib/lexical.mjs +137 -0
- package/cli/lib/local-config.mjs +110 -0
- package/cli/lib/mcp-server.mjs +221 -13
- package/cli/lib/pack.mjs +31 -4
- package/cli/lib/prompt.mjs +42 -4
- package/cli/lib/recall.mjs +193 -0
- package/cli/lib/retrieval-index.mjs +0 -0
- package/cli/lib/search-ranked.mjs +170 -0
- package/cli/lib/search.mjs +11 -1
- package/cli/lib/signals-backlog-commands.mjs +673 -0
- package/cli/lib/signals-backlog.mjs +361 -0
- package/cli/lib/signals-eval.mjs +176 -0
- package/cli/lib/signals-readiness.mjs +247 -0
- package/cli/lib/signals-registry.mjs +377 -0
- package/cli/lib/signals-render.mjs +478 -0
- package/cli/lib/signals-shared.mjs +75 -0
- package/cli/lib/signals.mjs +16 -2337
- package/cli/lib/site-analysis.mjs +297 -0
- package/cli/lib/site-args.mjs +433 -0
- package/cli/lib/site-bundle-build.mjs +127 -0
- package/cli/lib/site-bundle-check.mjs +454 -0
- package/cli/lib/site-bundle-commands.mjs +95 -0
- package/cli/lib/site-bundle-compare.mjs +157 -0
- package/cli/lib/site-bundle-contract.mjs +79 -0
- package/cli/lib/site-bundle-files.mjs +87 -0
- package/cli/lib/site-bundle-handoff-expected.mjs +173 -0
- package/cli/lib/site-bundle-handoff-runbook-action-summary.mjs +332 -0
- package/cli/lib/site-bundle-handoff-runbook-actions.mjs +113 -0
- package/cli/lib/site-bundle-handoff-runbook-evidence-fields.mjs +164 -0
- package/cli/lib/site-bundle-handoff-runbook-evidence.mjs +334 -0
- package/cli/lib/site-bundle-handoff-runbook-format.mjs +31 -0
- package/cli/lib/site-bundle-handoff-runbook-human-lines.mjs +167 -0
- package/cli/lib/site-bundle-handoff-runbook-maps.mjs +238 -0
- package/cli/lib/site-bundle-handoff-runbook-next-step.mjs +278 -0
- package/cli/lib/site-bundle-handoff-runbook-stage-metadata.mjs +84 -0
- package/cli/lib/site-bundle-handoff-runbook.mjs +444 -0
- package/cli/lib/site-bundle-handoff-summary.mjs +183 -0
- package/cli/lib/site-bundle-handoff.mjs +271 -0
- package/cli/lib/site-bundle-readme.mjs +98 -0
- package/cli/lib/site-bundle-repair-report.mjs +143 -0
- package/cli/lib/site-bundle-repair.mjs +68 -0
- package/cli/lib/site-content.mjs +399 -0
- package/cli/lib/site-evidence.mjs +35 -0
- package/cli/lib/site-mcp-commands.mjs +28 -0
- package/cli/lib/site-mcp-probes.mjs +159 -0
- package/cli/lib/site-mcp-readiness.mjs +157 -0
- package/cli/lib/site-mcp-report.mjs +324 -0
- package/cli/lib/site-next-actions.mjs +333 -0
- package/cli/lib/site-options.mjs +104 -0
- package/cli/lib/site-prompts.mjs +332 -0
- package/cli/lib/site-starter.mjs +153 -0
- package/cli/lib/site-strings.mjs +23 -0
- package/cli/lib/site-tasks.mjs +93 -0
- package/cli/lib/site-test-support.mjs +68 -0
- package/cli/lib/site-workflow-graph.mjs +309 -0
- package/cli/lib/site-workspace.mjs +492 -0
- package/cli/lib/site.mjs +108 -6617
- package/cli/lib/skill-proposals-apply-commands.mjs +135 -0
- package/cli/lib/skill-proposals-apply-contract.mjs +750 -0
- package/cli/lib/skill-proposals-apply-plan.mjs +118 -0
- package/cli/lib/skill-proposals-generate.mjs +298 -0
- package/cli/lib/skill-proposals-render.mjs +532 -0
- package/cli/lib/skill-proposals-review.mjs +262 -0
- package/cli/lib/skill-proposals.mjs +15 -2046
- package/cli/lib/workspace-args.mjs +83 -0
- package/cli/lib/workspace-git.mjs +169 -0
- package/cli/lib/workspace-learning.mjs +483 -0
- package/cli/lib/workspace-repo.mjs +139 -0
- package/cli/lib/workspace-report.mjs +283 -0
- package/cli/lib/workspace-test-support.mjs +99 -0
- package/cli/lib/workspace.mjs +30 -1056
- package/docs/AI-LEARNING-PHASE2.md +215 -0
- package/docs/DISTRIBUTION.ko.md +35 -6
- package/docs/DISTRIBUTION.md +35 -8
- package/docs/NEXT-SURFACE-DECISION.md +125 -0
- package/docs/PRODUCT-READINESS.md +3 -3
- package/docs/RELEASE-CHECKLIST.md +20 -3
- package/docs/RELEASE-GATES.ko.md +35 -0
- package/docs/RELEASE-GATES.md +234 -0
- package/docs/ROADMAP.md +2232 -8
- package/docs/external-status.md +20 -7
- package/docs/inspection-20260630.md +169 -0
- package/docs/integrations/design-ai-mcp-server.md +35 -3
- package/docs/integrations/vscode-walkthrough.ko.md +3 -3
- package/docs/integrations/vscode-walkthrough.md +3 -3
- package/docs/reference/ant-design.md +413 -0
- package/docs/reference/awesome-design-md.md +439 -0
- package/docs/reference/mui.md +783 -0
- package/docs/reference/shadcn-ui.md +298 -0
- package/docs/site-overrides/main.html +1 -1
- package/examples/component-accordion-actions.md +5 -5
- package/examples/component-accordion-details.md +5 -5
- package/examples/component-accordion-summary.md +5 -5
- package/examples/component-accordion.md +3 -3
- package/examples/component-affix.md +1 -1
- package/examples/component-alert-dialog.md +1 -1
- package/examples/component-alert-title.md +1 -1
- package/examples/component-alert.md +3 -3
- package/examples/component-anchor.md +1 -1
- package/examples/component-app-bar.md +1 -1
- package/examples/component-aspect-ratio.md +1 -1
- package/examples/component-auto-complete.md +2 -2
- package/examples/component-avatar-group.md +5 -5
- package/examples/component-avatar.md +3 -3
- package/examples/component-back-top.md +1 -1
- package/examples/component-backdrop.md +1 -1
- package/examples/component-badge.md +3 -3
- package/examples/component-border-beam.md +3 -3
- package/examples/component-bottom-navigation.md +1 -1
- package/examples/component-box.md +1 -1
- package/examples/component-breadcrumb.md +3 -3
- package/examples/component-button-base.md +3 -3
- package/examples/component-button-group.md +2 -2
- package/examples/component-button.md +3 -3
- package/examples/component-calendar.md +2 -2
- package/examples/component-card-actions.md +1 -1
- package/examples/component-card-content.md +1 -1
- package/examples/component-card-header.md +1 -1
- package/examples/component-card-media.md +1 -1
- package/examples/component-card.md +3 -3
- package/examples/component-carousel.md +2 -2
- package/examples/component-cascader.md +1 -1
- package/examples/component-chart.md +1 -1
- package/examples/component-checkbox.md +3 -3
- package/examples/component-click-away-listener.md +1 -1
- package/examples/component-code.md +1 -1
- package/examples/component-collapsible.md +1 -1
- package/examples/component-color-picker.md +1 -1
- package/examples/component-combobox.md +1 -1
- package/examples/component-command.md +1 -1
- package/examples/component-config-provider.md +3 -3
- package/examples/component-context-menu.md +1 -1
- package/examples/component-css-baseline.md +3 -3
- package/examples/component-date-picker.md +2 -2
- package/examples/component-descriptions.md +1 -1
- package/examples/component-dialog-actions.md +1 -1
- package/examples/component-dialog-content-text.md +1 -1
- package/examples/component-dialog-content.md +1 -1
- package/examples/component-dialog-title.md +1 -1
- package/examples/component-dialog.md +2 -2
- package/examples/component-divider.md +3 -3
- package/examples/component-drawer.md +3 -3
- package/examples/component-dropdown.md +3 -3
- package/examples/component-empty.md +2 -2
- package/examples/component-fade.md +1 -1
- package/examples/component-field.md +1 -1
- package/examples/component-filled-input.md +1 -1
- package/examples/component-flex.md +1 -1
- package/examples/component-float-button.md +2 -2
- package/examples/component-form-control-label.md +1 -1
- package/examples/component-form-control.md +1 -1
- package/examples/component-form-controls.md +1 -1
- package/examples/component-form-group.md +1 -1
- package/examples/component-form-helper-text.md +1 -1
- package/examples/component-form-label.md +1 -1
- package/examples/component-form.md +2 -2
- package/examples/component-grid.md +2 -2
- package/examples/component-grow.md +1 -1
- package/examples/component-hover-card.md +1 -1
- package/examples/component-icon-button.md +1 -1
- package/examples/component-icon.md +1 -1
- package/examples/component-image-list.md +1 -1
- package/examples/component-image.md +1 -1
- package/examples/component-input-adornment.md +1 -1
- package/examples/component-input-base.md +1 -1
- package/examples/component-input-number.md +1 -1
- package/examples/component-input-otp.md +2 -2
- package/examples/component-input.md +3 -3
- package/examples/component-item.md +1 -1
- package/examples/component-label.md +1 -1
- package/examples/component-layout.md +1 -1
- package/examples/component-link.md +1 -1
- package/examples/component-list-item-avatar.md +1 -1
- package/examples/component-list-item-button.md +1 -1
- package/examples/component-list-item-icon.md +1 -1
- package/examples/component-list-item-text.md +1 -1
- package/examples/component-list-item.md +1 -1
- package/examples/component-list-subheader.md +1 -1
- package/examples/component-list.md +2 -2
- package/examples/component-masonry.md +1 -1
- package/examples/component-mentions.md +1 -1
- package/examples/component-menu-item.md +1 -1
- package/examples/component-menu-list.md +1 -1
- package/examples/component-menu.md +1 -1
- package/examples/component-menubar.md +1 -1
- package/examples/component-message.md +1 -1
- package/examples/component-mobile-stepper.md +1 -1
- package/examples/component-modal.md +5 -5
- package/examples/component-navigation-menu.md +1 -1
- package/examples/component-notification.md +1 -1
- package/examples/component-outlined-input.md +1 -1
- package/examples/component-pagination.md +3 -3
- package/examples/component-paper.md +1 -1
- package/examples/component-popconfirm.md +1 -1
- package/examples/component-popover.md +3 -3
- package/examples/component-popper.md +1 -1
- package/examples/component-progress.md +2 -2
- package/examples/component-qr-code.md +1 -1
- package/examples/component-radio.md +3 -3
- package/examples/component-rate.md +2 -2
- package/examples/component-resizable.md +1 -1
- package/examples/component-result.md +1 -1
- package/examples/component-scroll-area.md +1 -1
- package/examples/component-segmented.md +3 -3
- package/examples/component-select.md +3 -3
- package/examples/component-separator.md +1 -1
- package/examples/component-sheet.md +1 -1
- package/examples/component-sidebar.md +1 -1
- package/examples/component-skeleton.md +3 -3
- package/examples/component-slide.md +1 -1
- package/examples/component-slider.md +3 -3
- package/examples/component-snackbar-content.md +1 -1
- package/examples/component-snackbar.md +1 -1
- package/examples/component-sonner.md +1 -1
- package/examples/component-space.md +1 -1
- package/examples/component-speed-dial-action.md +1 -1
- package/examples/component-speed-dial.md +1 -1
- package/examples/component-spin.md +2 -2
- package/examples/component-spinner.md +1 -1
- package/examples/component-splitter.md +2 -2
- package/examples/component-stack.md +1 -1
- package/examples/component-statistic.md +1 -1
- package/examples/component-step-button.md +4 -4
- package/examples/component-step-connector.md +4 -4
- package/examples/component-step-content.md +1 -1
- package/examples/component-step-icon.md +1 -1
- package/examples/component-step-label.md +1 -1
- package/examples/component-step.md +2 -2
- package/examples/component-steps.md +2 -2
- package/examples/component-swipeable-drawer.md +1 -1
- package/examples/component-switch.md +3 -3
- package/examples/component-tab-scroll-button.md +5 -5
- package/examples/component-tab.md +1 -1
- package/examples/component-table-body.md +1 -1
- package/examples/component-table-cell.md +1 -1
- package/examples/component-table-container.md +1 -1
- package/examples/component-table-footer.md +1 -1
- package/examples/component-table-head.md +1 -1
- package/examples/component-table-pagination.md +1 -1
- package/examples/component-table-row.md +1 -1
- package/examples/component-table-sort-label.md +1 -1
- package/examples/component-table.md +2 -2
- package/examples/component-tabs.md +3 -3
- package/examples/component-tag-badge.md +2 -2
- package/examples/component-tag.md +1 -1
- package/examples/component-textarea-autosize.md +1 -1
- package/examples/component-textarea.md +1 -1
- package/examples/component-time-picker.md +1 -1
- package/examples/component-timeline.md +1 -1
- package/examples/component-toast.md +4 -4
- package/examples/component-toggle-button.md +1 -1
- package/examples/component-toggle.md +1 -1
- package/examples/component-toolbar.md +1 -1
- package/examples/component-tooltip.md +3 -3
- package/examples/component-tour.md +1 -1
- package/examples/component-transfer.md +1 -1
- package/examples/component-tree-select.md +1 -1
- package/examples/component-tree.md +1 -1
- package/examples/component-typography.md +2 -2
- package/examples/component-upload.md +1 -1
- package/examples/component-watermark.md +1 -1
- package/examples/component-zoom.md +1 -1
- package/knowledge/COVERAGE.md +4 -3
- package/knowledge/components/INDEX.md +202 -202
- package/knowledge/patterns/brand-references.md +72 -72
- package/package.json +1 -1
- package/tools/audit/local-ci.py +16 -1
- package/tools/audit/package-smoke.py +717 -9
- package/tools/audit/registry-smoke.py +912 -10
- package/tools/audit/release-metadata.py +47 -1
- package/tools/audit/smoke_assertions.py +998 -35
- package/tools/migrations/refs-links-to-reference-pages.py +179 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Help text for `design-ai learn`.
|
|
2
|
+
|
|
3
|
+
import { LEARNING_FEEDBACK_OUTCOMES } from "../lib/learn.mjs";
|
|
4
|
+
|
|
5
|
+
export function printHelp() {
|
|
6
|
+
console.log("Usage: design-ai learn [--list] [--category kind] [--query text] [--explain] [--limit N] [--json] [--out file] [--force]");
|
|
7
|
+
console.log(" design-ai learn --recall query [--limit N] [--category kind] [--json]");
|
|
8
|
+
console.log(" design-ai learn <mode> ... Bare-word alias for a mode flag, e.g. `learn signals --json` = `learn --signals --json`");
|
|
9
|
+
console.log(" design-ai learn --init [--yes|--dry-run] [--json] [--out file] [--force]");
|
|
10
|
+
console.log(" design-ai learn --remember text [--category kind] [--json] [--out file] [--force]");
|
|
11
|
+
console.log(" design-ai learn --feedback text [--outcome keep|improve|avoid] [--category kind] [--json] [--out file] [--force]");
|
|
12
|
+
console.log(" design-ai learn --feedback --from-file notes.md [--outcome keep|improve|avoid] [--category kind] [--json] [--out file] [--force]");
|
|
13
|
+
console.log(" cat notes.md | design-ai learn --feedback --stdin [--outcome keep|improve|avoid] [--category kind] [--json] [--out file] [--force]");
|
|
14
|
+
console.log(" design-ai learn --from-file notes.md [--category kind] [--json] [--out file] [--force]");
|
|
15
|
+
console.log(" cat notes.md | design-ai learn --stdin [--category kind] [--json] [--out file] [--force]");
|
|
16
|
+
console.log(" design-ai learn --export [--category kind] [--query text] [--limit N] [--json] [--out file] [--force]");
|
|
17
|
+
console.log(" design-ai learn --backup [--json] [--out file] [--force]");
|
|
18
|
+
console.log(" design-ai learn --redact [--json] [--out file] [--force]");
|
|
19
|
+
console.log(" design-ai learn --redact --from-file learning-backup.json [--json] [--out file] [--force]");
|
|
20
|
+
console.log(" cat learning-backup.json | design-ai learn --redact --stdin [--json] [--out file] [--force]");
|
|
21
|
+
console.log(" design-ai learn --verify --from-file learning.json [--json] [--out file] [--force]");
|
|
22
|
+
console.log(" cat learning.json | design-ai learn --verify --stdin [--json] [--out file] [--force]");
|
|
23
|
+
console.log(" design-ai learn --diff --from-file learning.json [--json] [--out file] [--force]");
|
|
24
|
+
console.log(" cat learning.json | design-ai learn --diff --stdin [--json] [--out file] [--force]");
|
|
25
|
+
console.log(" design-ai learn --restore --from-file learning-backup.json [--dry-run|--yes] [--backup-file path] [--json] [--out file] [--force]");
|
|
26
|
+
console.log(" cat learning-backup.json | design-ai learn --restore --stdin [--dry-run|--yes] [--backup-file path] [--json] [--out file] [--force]");
|
|
27
|
+
console.log(" design-ai learn --restore-backups [--limit N] [--json] [--out file] [--force]");
|
|
28
|
+
console.log(" design-ai learn --restore-backups --prune [--keep N] [--dry-run|--yes] [--json] [--out file] [--force]");
|
|
29
|
+
console.log(" design-ai learn --import --from-file learning.json --dry-run [--json] [--out file] [--force]");
|
|
30
|
+
console.log(" cat learning.json | design-ai learn --import --stdin --yes [--json] [--out file] [--force]");
|
|
31
|
+
console.log(" design-ai learn --audit [--json] [--out file] [--force]");
|
|
32
|
+
console.log(" design-ai learn --audit --fix --dry-run [--json] [--out file] [--force]");
|
|
33
|
+
console.log(" design-ai learn --audit --fix --yes [--json] [--out file] [--force]");
|
|
34
|
+
console.log(" design-ai learn --curate [--dry-run|--yes] [--usage-file path] [--json|--report] [--out file] [--force]");
|
|
35
|
+
console.log(" design-ai learn --stats [--json] [--out file] [--force]");
|
|
36
|
+
console.log(" design-ai learn --usage [--limit N] [--usage-file path] [--json] [--out file] [--force]");
|
|
37
|
+
console.log(" design-ai learn --signals [--from-file signal-file-or-dir] [--usage-file path] [--strict] [--json|--report] [--out file] [--force]");
|
|
38
|
+
console.log(" design-ai learn --agent-backlog [--from-file signal-file-or-dir] [--usage-file path] [--strict] [--json|--report] [--out file] [--force]");
|
|
39
|
+
console.log(" design-ai learn --propose-skills [--from-file signal-file-or-dir] [--usage-file path] [--review-file path] [--review-check|--apply-plan] [--min-evidence N] [--strict] [--json|--report|--patch|--review-template] [--out file] [--force]");
|
|
40
|
+
console.log(" design-ai learn --eval-template [--query text] [--category kind] [--limit N] [--json] [--out file] [--force]");
|
|
41
|
+
console.log(" design-ai learn --eval --from-file eval.json [--category kind] [--limit N] [--strict] [--json] [--out file] [--force]");
|
|
42
|
+
console.log(" cat eval.json | design-ai learn --eval --stdin [--category kind] [--limit N] [--strict] [--json]");
|
|
43
|
+
console.log(" design-ai learn --forget id-or-number --yes [--json] [--out file] [--force]");
|
|
44
|
+
console.log(" design-ai learn --clear --yes [--json] [--out file] [--force]\n");
|
|
45
|
+
console.log("Stores local design preferences for explicit prompt personalization.");
|
|
46
|
+
console.log("This is local memory, not model training or fine-tuning.\n");
|
|
47
|
+
console.log("Options:");
|
|
48
|
+
console.log(" --init Preview or apply starter local learning entries for dogfood use");
|
|
49
|
+
console.log(" --remember text Remember an inline preference or project constraint");
|
|
50
|
+
console.log(" --feedback text Convert outcome feedback into a reusable local learning note");
|
|
51
|
+
console.log(` --outcome kind Feedback outcome: ${LEARNING_FEEDBACK_OUTCOMES.join(", ")}. Default: improve`);
|
|
52
|
+
console.log(" --from-file file Read remember/feedback text or import/verify/diff/restore/redact JSON from a file");
|
|
53
|
+
console.log(" --stdin Read remember/feedback text or import/verify/diff/restore/redact JSON from standard input");
|
|
54
|
+
console.log(" --category kind preference, brand, workflow, constraint, accessibility, korean, other");
|
|
55
|
+
console.log(" --query text Filter list/export output to entries whose category or text matches the query");
|
|
56
|
+
console.log(" --explain With --list, include selection score, matched tokens, and reason");
|
|
57
|
+
console.log(" --limit N Limit list/export output to the N most recent matching entries, 1-100");
|
|
58
|
+
console.log(" --recall query Read-only combined recall: top corpus knowledge files plus local learning entries ranked for the query");
|
|
59
|
+
console.log(" --list List saved learning entries. Default when no action is given");
|
|
60
|
+
console.log(" --export Print the learned-context block used by --with-learning");
|
|
61
|
+
console.log(" --backup Print a full portable learning-profile backup; use --json for importable JSON");
|
|
62
|
+
console.log(" --redact Print a portable JSON backup with sensitive-looking text redacted");
|
|
63
|
+
console.log(" --verify Validate a portable learning JSON payload without importing it");
|
|
64
|
+
console.log(" --diff Compare the active profile against a portable learning JSON payload without importing it");
|
|
65
|
+
console.log(" --restore Preview or apply replacing the active profile with a portable learning JSON payload");
|
|
66
|
+
console.log(" --restore-backups List sibling restore rollback backups for the active learning profile");
|
|
67
|
+
console.log(" --prune With --restore-backups, preview or delete older rollback backup files");
|
|
68
|
+
console.log(" --keep N With --restore-backups --prune, keep the N newest backups. Default: 5");
|
|
69
|
+
console.log(" --backup-file path With --restore, override the automatic rollback backup file path");
|
|
70
|
+
console.log(" --import Merge entries from a JSON learning profile or learn --export --json payload");
|
|
71
|
+
console.log(" --audit Inspect profile shape, sensitive content, and cleanup suggestions without changing it");
|
|
72
|
+
console.log(" --fix With --audit, prepare or apply safe cleanup suggestions");
|
|
73
|
+
console.log(" --curate Preview or apply archive-first curation for duplicate/sensitive entries, plus usage review hints");
|
|
74
|
+
console.log(" --report With --curate, --signals, --agent-backlog, or --propose-skills, emit a Markdown review report instead of human console output");
|
|
75
|
+
console.log(" --patch With --propose-skills, emit a preview-only unified diff handoff without editing skill files");
|
|
76
|
+
console.log(" --review-check With --propose-skills, verify the review file against current proposals without changing files");
|
|
77
|
+
console.log(" --apply-plan With --propose-skills, turn accepted review decisions into a read-only manual apply plan");
|
|
78
|
+
console.log(" --review-template With --propose-skills, emit a JSON proposal review-file template without changing review decisions");
|
|
79
|
+
console.log(" --dry-run Preview --init, --import, --restore, --curate, --restore-backups --prune, or --audit --fix without changing files");
|
|
80
|
+
console.log(" --stats Summarize profile counts, recency, and audit status without changing it");
|
|
81
|
+
console.log(" --usage Summarize prompt/pack --with-learning usage sidecar events without changing files");
|
|
82
|
+
console.log(" --signals Summarize local learning, usage, eval, check-capture, agent backlog, and workspace readiness signals without changing files");
|
|
83
|
+
console.log(" --agent-backlog Emit a focused local AI/agent development backlog from the signal registry without changing files");
|
|
84
|
+
console.log(" --propose-skills Preview skill instruction deltas from repeated check-capture learning signals without changing files");
|
|
85
|
+
console.log(" --min-evidence N With --propose-skills, require N related check-capture entries before emitting a proposal. Default: 2");
|
|
86
|
+
console.log(" --review-file path With --propose-skills, read proposal review decisions without changing the review file");
|
|
87
|
+
console.log(" --eval-template Generate a runnable learning eval checkpoint from the active profile");
|
|
88
|
+
console.log(" --eval Run deterministic learning-selection checkpoint cases without changing files");
|
|
89
|
+
console.log(" --strict With --eval, --signals, --agent-backlog, or --propose-skills, exit non-zero when any checkpoint, signal, backlog, or proposal gate warns or fails");
|
|
90
|
+
console.log(" --forget id-or-number Remove one entry by id or 1-based list number; requires --yes");
|
|
91
|
+
console.log(" --clear Remove all saved learning entries; requires --yes");
|
|
92
|
+
console.log(" --yes Confirm destructive local profile changes");
|
|
93
|
+
console.log(" --file path Override the learning profile path");
|
|
94
|
+
console.log(" --usage-file path Override the learning usage sidecar path used by --usage, --curate, --signals, --agent-backlog, or --propose-skills");
|
|
95
|
+
console.log(" --json Emit machine-readable output");
|
|
96
|
+
console.log(" --out file Write JSON output to a file, export Markdown for --export, or learning review report Markdown");
|
|
97
|
+
console.log(" --force Overwrite an existing --out file, or an existing --backup-file during --restore");
|
|
98
|
+
console.log("");
|
|
99
|
+
console.log("Environment:");
|
|
100
|
+
console.log(" DESIGN_AI_LEARNING_FILE=/path/learning.json Override the default profile path");
|
|
101
|
+
console.log(" DESIGN_AI_LEARNING_USAGE_FILE=/path/usage.json Override the default usage sidecar path");
|
|
102
|
+
console.log("");
|
|
103
|
+
console.log("Examples:");
|
|
104
|
+
console.log(" design-ai learn --init");
|
|
105
|
+
console.log(" design-ai learn --init --yes --json");
|
|
106
|
+
console.log(" design-ai learn --remember \"Prefer dense Korean product UI\" --category korean");
|
|
107
|
+
console.log(" design-ai learn --feedback \"Keep audit findings short and evidence-led\" --outcome keep");
|
|
108
|
+
console.log(" design-ai learn --feedback --from-file feedback.md --outcome improve");
|
|
109
|
+
console.log(" cat feedback.md | design-ai learn --feedback --stdin --outcome avoid --category brand");
|
|
110
|
+
console.log(" design-ai learn --recall \"korean payment\" --limit 5");
|
|
111
|
+
console.log(" design-ai learn --list --category korean --limit 5");
|
|
112
|
+
console.log(" design-ai learn --list --query \"keyboard accessibility\" --explain --json");
|
|
113
|
+
console.log(" design-ai learn --export --query \"pricing page\" --limit 3");
|
|
114
|
+
console.log(" design-ai learn --backup --json --out learning-backup.json");
|
|
115
|
+
console.log(" design-ai learn --redact --json --out learning-redacted.json");
|
|
116
|
+
console.log(" design-ai learn --redact --from-file learning-backup.json --json --out learning-redacted.json --force");
|
|
117
|
+
console.log(" design-ai learn --verify --from-file learning-backup.json");
|
|
118
|
+
console.log(" design-ai learn --diff --from-file learning-backup.json --json");
|
|
119
|
+
console.log(" design-ai learn --restore --from-file learning-backup.json --dry-run");
|
|
120
|
+
console.log(" design-ai learn --restore --from-file learning-backup.json --yes --backup-file learning-before-restore.json");
|
|
121
|
+
console.log(" design-ai learn --restore-backups --json");
|
|
122
|
+
console.log(" design-ai learn --restore-backups --prune --keep 5");
|
|
123
|
+
console.log(" design-ai learn --restore-backups --prune --keep 5 --yes");
|
|
124
|
+
console.log(" design-ai learn --import --from-file learning.json --dry-run");
|
|
125
|
+
console.log(" design-ai learn --audit");
|
|
126
|
+
console.log(" design-ai learn --audit --fix --dry-run");
|
|
127
|
+
console.log(" design-ai learn --curate");
|
|
128
|
+
console.log(" design-ai learn --curate --usage-file ./learning.usage.json");
|
|
129
|
+
console.log(" design-ai learn --curate --report --out learning-curation-report.md");
|
|
130
|
+
console.log(" design-ai learn --curate --yes --json");
|
|
131
|
+
console.log(" design-ai learn --stats --json");
|
|
132
|
+
console.log(" design-ai learn --usage --json");
|
|
133
|
+
console.log(" design-ai learn --signals --from-file . --json");
|
|
134
|
+
console.log(" design-ai learn --signals --from-file . --report --out learning-signals.md");
|
|
135
|
+
console.log(" design-ai learn --agent-backlog --from-file . --report --out agent-backlog.md");
|
|
136
|
+
console.log(" design-ai learn --propose-skills --from-file . --min-evidence 3 --json");
|
|
137
|
+
console.log(" design-ai learn --propose-skills --from-file . --strict --json");
|
|
138
|
+
console.log(" design-ai learn --propose-skills --from-file . --review-file skill-proposals.review.json --strict --json");
|
|
139
|
+
console.log(" design-ai learn --propose-skills --from-file . --review-file skill-proposals.review.json --review-check --json");
|
|
140
|
+
console.log(" design-ai learn --propose-skills --from-file . --review-file skill-proposals.review.json --apply-plan --json");
|
|
141
|
+
console.log(" design-ai learn --propose-skills --from-file . --review-template --out skill-proposals.review.json");
|
|
142
|
+
console.log(" design-ai learn --propose-skills --from-file . --report --out skill-proposals.md");
|
|
143
|
+
console.log(" design-ai learn --propose-skills --from-file . --patch --out skill-proposals.patch");
|
|
144
|
+
console.log(" design-ai learn --eval-template --query \"keyboard accessibility\" --out learning-eval.json");
|
|
145
|
+
console.log(" design-ai learn --eval --from-file learning-eval.json --strict --json");
|
|
146
|
+
console.log(" design-ai learn --forget learn-abc123def0 --yes");
|
|
147
|
+
console.log(" design-ai prompt \"audit checkout UX\" --with-learning");
|
|
148
|
+
console.log(" design-ai pack \"spec a pricing page\" --with-learning");
|
|
149
|
+
}
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
// Human-readable output for learn profile list/audit/curation/stats/usage results.
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
LEARNING_CATEGORIES,
|
|
5
|
+
loadLearningProfile,
|
|
6
|
+
selectLearningEntrySet,
|
|
7
|
+
} from "../lib/learn.mjs";
|
|
8
|
+
import { dim, header, info } from "../lib/log.mjs";
|
|
9
|
+
|
|
10
|
+
export function printLearningImportVerification(payload) {
|
|
11
|
+
header("design-ai learn", "Learning import verification");
|
|
12
|
+
info(`Source: ${payload.source}`);
|
|
13
|
+
info(`Importable: ${payload.importable ? "yes" : "no"}`);
|
|
14
|
+
info(`Entries: ${payload.count}`);
|
|
15
|
+
info(`Audit: ${payload.auditSummary.status} (${payload.auditSummary.failures} failure(s), ${payload.auditSummary.warnings} warning(s))`);
|
|
16
|
+
console.log();
|
|
17
|
+
|
|
18
|
+
if (payload.issues.length === 0) {
|
|
19
|
+
console.log("No learning import issues found. No changes made.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
for (const issue of payload.issues) {
|
|
24
|
+
const entry = issue.entryId ? ` (${issue.entryId})` : "";
|
|
25
|
+
console.log(`${issue.level.toUpperCase()} ${issue.code}${entry}: ${issue.message}`);
|
|
26
|
+
}
|
|
27
|
+
console.log();
|
|
28
|
+
console.log("No changes made. Review warnings before importing or using learned context.");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function learningFilter(parsed) {
|
|
32
|
+
return {
|
|
33
|
+
category: parsed.categorySpecified ? parsed.category : "",
|
|
34
|
+
limit: parsed.limit,
|
|
35
|
+
query: parsed.query,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function listPayload(filePath, parsed) {
|
|
40
|
+
const profile = loadLearningProfile(filePath);
|
|
41
|
+
const filter = learningFilter(parsed);
|
|
42
|
+
const { entries, selection } = selectLearningEntrySet(profile, {
|
|
43
|
+
...filter,
|
|
44
|
+
includeFallback: false,
|
|
45
|
+
});
|
|
46
|
+
const payload = {
|
|
47
|
+
file: filePath,
|
|
48
|
+
version: profile.version,
|
|
49
|
+
updatedAt: profile.updatedAt,
|
|
50
|
+
category: filter.category,
|
|
51
|
+
query: filter.query,
|
|
52
|
+
limit: filter.limit || null,
|
|
53
|
+
entries,
|
|
54
|
+
count: entries.length,
|
|
55
|
+
totalCount: profile.entries.length,
|
|
56
|
+
};
|
|
57
|
+
if (parsed.explain) {
|
|
58
|
+
payload.selection = selection;
|
|
59
|
+
}
|
|
60
|
+
return payload;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function printList(payload) {
|
|
64
|
+
header("design-ai learn", "Local learning profile");
|
|
65
|
+
info(`File: ${payload.file}`);
|
|
66
|
+
info(`Entries: ${payload.count}/${payload.totalCount}`);
|
|
67
|
+
if (payload.category) info(`Category: ${payload.category}`);
|
|
68
|
+
if (payload.query) info(`Query: ${payload.query}`);
|
|
69
|
+
if (payload.limit) info(`Limit: ${payload.limit}`);
|
|
70
|
+
if (payload.selection) {
|
|
71
|
+
info("Explain: selection score, matched tokens, and reason");
|
|
72
|
+
}
|
|
73
|
+
console.log();
|
|
74
|
+
|
|
75
|
+
if (payload.entries.length === 0) {
|
|
76
|
+
console.log(payload.category || payload.query || payload.limit
|
|
77
|
+
? "No local learning preferences match the current filters."
|
|
78
|
+
: "No local learning preferences are stored yet.");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for (let i = 0; i < payload.entries.length; i += 1) {
|
|
83
|
+
const entry = payload.entries[i];
|
|
84
|
+
const selected = payload.selection?.selected?.[i];
|
|
85
|
+
console.log(`${i + 1}. [${entry.category}] ${entry.text}`);
|
|
86
|
+
console.log(` ${dim(`${entry.id} · ${entry.createdAt || "unknown time"}`)}`);
|
|
87
|
+
if (selected) {
|
|
88
|
+
const matched = selected.matchedTokens.length > 0
|
|
89
|
+
? selected.matchedTokens.join(", ")
|
|
90
|
+
: "none";
|
|
91
|
+
console.log(` ${dim(`score ${selected.score} · matched ${matched} · reason ${selected.reason}`)}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function formatCategoryCounts(categoryCounts) {
|
|
97
|
+
return LEARNING_CATEGORIES
|
|
98
|
+
.filter((category) => categoryCounts[category])
|
|
99
|
+
.map((category) => `${category} ${categoryCounts[category]}`)
|
|
100
|
+
.join(", ");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function formatCounts(counts) {
|
|
104
|
+
return Object.entries(counts || {})
|
|
105
|
+
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
|
106
|
+
.map(([key, count]) => `${key} ${count}`)
|
|
107
|
+
.join(", ");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function printAudit(payload) {
|
|
111
|
+
header("design-ai learn", "Local learning profile audit");
|
|
112
|
+
info(`File: ${payload.file}`);
|
|
113
|
+
info(`Exists: ${payload.exists ? "yes" : "no"}`);
|
|
114
|
+
info(`Entries: ${payload.count}`);
|
|
115
|
+
info(`Status: ${payload.summary.status}`);
|
|
116
|
+
info(`Issues: ${payload.summary.failures} failure(s), ${payload.summary.warnings} warning(s)`);
|
|
117
|
+
|
|
118
|
+
const categories = formatCategoryCounts(payload.categoryCounts);
|
|
119
|
+
if (categories) info(`Categories: ${categories}`);
|
|
120
|
+
console.log();
|
|
121
|
+
|
|
122
|
+
if (!payload.exists) {
|
|
123
|
+
console.log("No local learning profile file exists yet.");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (payload.issues.length === 0) {
|
|
128
|
+
console.log("No learning profile issues found.");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (const issue of payload.issues) {
|
|
133
|
+
const entry = issue.entryId ? ` (${issue.entryId})` : "";
|
|
134
|
+
console.log(`${issue.level.toUpperCase()} ${issue.code}${entry}: ${issue.message}`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (payload.suggestions.length > 0) {
|
|
138
|
+
console.log();
|
|
139
|
+
console.log("Suggested cleanup:");
|
|
140
|
+
for (const suggestion of payload.suggestions) {
|
|
141
|
+
const entry = suggestion.entryId ? ` (${suggestion.entryId})` : "";
|
|
142
|
+
console.log(`- ${suggestion.action}${entry}: ${suggestion.message}`);
|
|
143
|
+
if (suggestion.command) {
|
|
144
|
+
console.log(` ${dim(suggestion.command)}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function printAuditFix(payload) {
|
|
151
|
+
header("design-ai learn", payload.dryRun ? "Learning audit cleanup dry run" : "Learning audit cleanup applied");
|
|
152
|
+
info(`File: ${payload.file}`);
|
|
153
|
+
info(`Before: ${payload.before.status} (${payload.before.failures} failure(s), ${payload.before.warnings} warning(s))`);
|
|
154
|
+
info(`Cleanup entries: ${payload.cleanupCount}`);
|
|
155
|
+
if (payload.after) {
|
|
156
|
+
info(`After: ${payload.after.status} (${payload.after.failures} failure(s), ${payload.after.warnings} warning(s))`);
|
|
157
|
+
}
|
|
158
|
+
console.log();
|
|
159
|
+
|
|
160
|
+
if (payload.cleanup.length === 0) {
|
|
161
|
+
console.log("No safe cleanup suggestions are available.");
|
|
162
|
+
} else {
|
|
163
|
+
console.log(payload.dryRun ? "Would remove:" : "Removed:");
|
|
164
|
+
for (const fix of payload.cleanup) {
|
|
165
|
+
console.log(`- ${fix.entryId}: ${fix.actions.join(", ")} (${fix.issueCodes.join(", ")})`);
|
|
166
|
+
if (fix.command) {
|
|
167
|
+
console.log(` ${dim(fix.command)}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (payload.skipped.length > 0) {
|
|
173
|
+
console.log();
|
|
174
|
+
console.log("Skipped:");
|
|
175
|
+
for (const skipped of payload.skipped) {
|
|
176
|
+
const entry = skipped.entryId ? ` (${skipped.entryId})` : "";
|
|
177
|
+
console.log(`- ${skipped.reason}${entry}: ${skipped.message}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (payload.dryRun) {
|
|
182
|
+
console.log();
|
|
183
|
+
console.log("No changes made. Re-run with `--yes` instead of `--dry-run` to apply safe cleanup.");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function printCuration(payload) {
|
|
188
|
+
header("design-ai learn", payload.dryRun ? "Learning curation preview" : "Learning curation applied");
|
|
189
|
+
info(`File: ${payload.file}`);
|
|
190
|
+
info(`Archive: ${payload.archiveFile}`);
|
|
191
|
+
info(`Before: ${payload.before.status} (${payload.before.failures} failure(s), ${payload.before.warnings} warning(s))`);
|
|
192
|
+
info(`Proposals: ${payload.proposalCount}`);
|
|
193
|
+
info(`Archive candidates: ${payload.archiveCount}`);
|
|
194
|
+
info(`Manual review: ${payload.manualReviewCount}`);
|
|
195
|
+
if (payload.after) {
|
|
196
|
+
info(`After: ${payload.after.status} (${payload.after.failures} failure(s), ${payload.after.warnings} warning(s))`);
|
|
197
|
+
}
|
|
198
|
+
console.log();
|
|
199
|
+
|
|
200
|
+
if (payload.proposals.length === 0) {
|
|
201
|
+
console.log("No learning curation candidates found.");
|
|
202
|
+
} else {
|
|
203
|
+
const archiveCandidates = payload.proposals.filter((proposal) => proposal.action === "archive");
|
|
204
|
+
const manualCandidates = payload.proposals.filter((proposal) => proposal.action === "manual-review");
|
|
205
|
+
if (archiveCandidates.length > 0) {
|
|
206
|
+
console.log(payload.dryRun ? "Would archive:" : "Archived:");
|
|
207
|
+
for (const proposal of archiveCandidates) {
|
|
208
|
+
console.log(`- ${proposal.entryId}: ${proposal.reason} (${proposal.issueCodes.join(", ")})`);
|
|
209
|
+
if (proposal.textPreview) console.log(` ${dim(proposal.textPreview)}`);
|
|
210
|
+
}
|
|
211
|
+
console.log();
|
|
212
|
+
}
|
|
213
|
+
if (manualCandidates.length > 0) {
|
|
214
|
+
console.log("Needs manual review:");
|
|
215
|
+
for (const proposal of manualCandidates) {
|
|
216
|
+
const label = proposal.entryId || "profile";
|
|
217
|
+
console.log(`- ${label}: ${proposal.reason} (${proposal.issueCodes.join(", ")})`);
|
|
218
|
+
if (proposal.textPreview) console.log(` ${dim(proposal.textPreview)}`);
|
|
219
|
+
}
|
|
220
|
+
console.log();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (payload.skipped.length > 0) {
|
|
225
|
+
console.log("Skipped:");
|
|
226
|
+
for (const skipped of payload.skipped) {
|
|
227
|
+
const entry = skipped.entryId ? `${skipped.entryId}: ` : "";
|
|
228
|
+
console.log(`- ${entry}${skipped.reason}`);
|
|
229
|
+
}
|
|
230
|
+
console.log();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (payload.usage?.exists || payload.usage?.error) {
|
|
234
|
+
console.log("Usage review:");
|
|
235
|
+
console.log(`- sidecar: ${payload.usage.usageFile}`);
|
|
236
|
+
console.log(`- events: ${payload.usage.eventCount}`);
|
|
237
|
+
console.log(`- review items: ${payload.usage.reviewCount}`);
|
|
238
|
+
if (payload.usage.error) {
|
|
239
|
+
console.log(`- error: ${payload.usage.error}`);
|
|
240
|
+
} else if (payload.usage.reviews.length === 0) {
|
|
241
|
+
console.log("- no usage-based curation review items found");
|
|
242
|
+
} else {
|
|
243
|
+
for (const review of payload.usage.reviews) {
|
|
244
|
+
const label = review.entryId || "usage";
|
|
245
|
+
console.log(`- ${label}: ${review.reason} (${review.action})`);
|
|
246
|
+
if (review.textPreview) console.log(` ${dim(review.textPreview)}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
console.log(dim("Usage review is advisory; --curate only archives duplicate/sensitive audit candidates."));
|
|
250
|
+
console.log();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (payload.dryRun) {
|
|
254
|
+
console.log("No changes made. Re-run with `--yes` to move archive candidates into the learning archive.");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function printStats(payload) {
|
|
259
|
+
header("design-ai learn", "Local learning profile stats");
|
|
260
|
+
info(`File: ${payload.file}`);
|
|
261
|
+
info(`Exists: ${payload.exists ? "yes" : "no"}`);
|
|
262
|
+
info(`Entries: ${payload.count}`);
|
|
263
|
+
info(`Updated: ${payload.updatedAt || "unknown"}`);
|
|
264
|
+
info(`Audit: ${payload.auditSummary.status} (${payload.auditSummary.failures} failure(s), ${payload.auditSummary.warnings} warning(s))`);
|
|
265
|
+
|
|
266
|
+
const categories = formatCategoryCounts(payload.categoryCounts);
|
|
267
|
+
if (categories) info(`Categories: ${categories}`);
|
|
268
|
+
|
|
269
|
+
const sources = Object.entries(payload.sourceCounts)
|
|
270
|
+
.map(([source, count]) => `${source} ${count}`)
|
|
271
|
+
.join(", ");
|
|
272
|
+
if (sources) info(`Sources: ${sources}`);
|
|
273
|
+
console.log();
|
|
274
|
+
|
|
275
|
+
if (!payload.exists) {
|
|
276
|
+
console.log("No local learning profile file exists yet.");
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (payload.auditSummary.failures > 0) {
|
|
281
|
+
console.log("Profile stats are limited because the profile has audit failures. Run `design-ai learn --audit` for details.");
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (payload.count === 0) {
|
|
286
|
+
console.log("No local learning preferences are stored yet.");
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (!payload.latestEntry) {
|
|
291
|
+
console.log("No parseable learning entry timestamps found. Run `design-ai learn --audit` for details.");
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (payload.latestEntry) {
|
|
296
|
+
console.log(`Latest: [${payload.latestEntry.category}] ${payload.latestEntry.textPreview}`);
|
|
297
|
+
console.log(` ${dim(`${payload.latestEntry.id} · ${payload.latestEntry.createdAt}`)}`);
|
|
298
|
+
}
|
|
299
|
+
if (payload.oldestEntry && payload.oldestEntry.id !== payload.latestEntry?.id) {
|
|
300
|
+
console.log(`Oldest: [${payload.oldestEntry.category}] ${payload.oldestEntry.textPreview}`);
|
|
301
|
+
console.log(` ${dim(`${payload.oldestEntry.id} · ${payload.oldestEntry.createdAt}`)}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export function printUsage(payload) {
|
|
306
|
+
header("design-ai learn", "Local learning usage report");
|
|
307
|
+
info(`File: ${payload.file}`);
|
|
308
|
+
info(`Usage sidecar: ${payload.usageFile}`);
|
|
309
|
+
info(`Usage exists: ${payload.exists ? "yes" : "no"}`);
|
|
310
|
+
info(`Events: ${payload.eventCount}`);
|
|
311
|
+
info(`Profile entries: ${payload.profileEntryCount}`);
|
|
312
|
+
info(`Used entries: ${payload.usedEntryCount}`);
|
|
313
|
+
info(`Unused entries: ${payload.unusedEntryCount}`);
|
|
314
|
+
info(`Stale selected ids: ${payload.staleSelectedEntryCount}`);
|
|
315
|
+
info(`Updated: ${payload.updatedAt || "unknown"}`);
|
|
316
|
+
|
|
317
|
+
const commands = formatCounts(payload.commandCounts);
|
|
318
|
+
if (commands) info(`Commands: ${commands}`);
|
|
319
|
+
const routes = formatCounts(payload.routeCounts);
|
|
320
|
+
if (routes) info(`Routes: ${routes}`);
|
|
321
|
+
const categories = formatCounts(payload.categoryCounts);
|
|
322
|
+
if (categories) info(`Categories: ${categories}`);
|
|
323
|
+
console.log();
|
|
324
|
+
|
|
325
|
+
if (!payload.exists) {
|
|
326
|
+
console.log("No local learning usage sidecar exists yet.");
|
|
327
|
+
console.log("Run `design-ai prompt \"...\" --with-learning` or `design-ai pack \"...\" --with-learning` to record usage metadata.");
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (payload.eventCount === 0) {
|
|
332
|
+
console.log("No local learning usage events are stored yet.");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (payload.topSelectedEntries.length > 0) {
|
|
337
|
+
console.log("Top selected entries:");
|
|
338
|
+
for (const entry of payload.topSelectedEntries) {
|
|
339
|
+
console.log(`- ${entry.id}: ${entry.usageCount} use(s) [${entry.category}] ${entry.textPreview}`);
|
|
340
|
+
if (entry.latestUsedAt) console.log(` ${dim(`latest ${entry.latestUsedAt}`)}`);
|
|
341
|
+
}
|
|
342
|
+
console.log();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (payload.recentEvents.length > 0) {
|
|
346
|
+
console.log("Recent events:");
|
|
347
|
+
for (const event of payload.recentEvents) {
|
|
348
|
+
const route = event.routeId || "unrouted";
|
|
349
|
+
const ids = event.selectedEntryIds.length > 0 ? event.selectedEntryIds.join(", ") : "none";
|
|
350
|
+
console.log(`- ${event.createdAt}: ${event.command} / ${route} selected ${ids}`);
|
|
351
|
+
console.log(` ${dim(`briefHash ${event.briefHash || "none"} · matched ${event.matchedCount}/${event.candidateCount} · fallback ${event.fallbackCount}`)}`);
|
|
352
|
+
}
|
|
353
|
+
console.log();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (payload.unusedEntryIds.length > 0) {
|
|
357
|
+
console.log(`Unused active entry ids: ${payload.unusedEntryIds.join(", ")}`);
|
|
358
|
+
}
|
|
359
|
+
if (payload.staleSelectedEntryIds.length > 0) {
|
|
360
|
+
console.log(`Stale selected entry ids: ${payload.staleSelectedEntryIds.join(", ")}`);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (payload.recommendations.length > 0) {
|
|
364
|
+
console.log();
|
|
365
|
+
console.log("Recommendations:");
|
|
366
|
+
for (const recommendation of payload.recommendations) {
|
|
367
|
+
console.log(`- ${recommendation.level}: ${recommendation.text}`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
console.log();
|
|
372
|
+
console.log("Privacy: usage events store selected entry ids and a short brief hash, not raw brief text.");
|
|
373
|
+
}
|