@agentwhy/cli 0.0.0-dev
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/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +181 -0
- package/THIRD_PARTY_NOTICES.md +31 -0
- package/dist/adapter/claude-code/contract/assumptions.js +208 -0
- package/dist/adapter/claude-code/contract/denials.js +15 -0
- package/dist/adapter/claude-code/contract/entry-points.js +15 -0
- package/dist/adapter/claude-code/contract/fields.js +73 -0
- package/dist/adapter/claude-code/contract/hooks.js +96 -0
- package/dist/adapter/claude-code/contract/identifiers.js +15 -0
- package/dist/adapter/claude-code/contract/layout.js +29 -0
- package/dist/adapter/claude-code/contract/line-types.js +26 -0
- package/dist/adapter/claude-code/contract/projects.js +23 -0
- package/dist/adapter/claude-code/contract/recognition.js +14 -0
- package/dist/adapter/claude-code/contract/session-title.js +20 -0
- package/dist/adapter/claude-code/contract/settings.js +27 -0
- package/dist/adapter/claude-code/contract/task-notifications.js +33 -0
- package/dist/adapter/claude-code/contract/tools.js +37 -0
- package/dist/adapter/claude-code/contract/version.js +51 -0
- package/dist/adapter/claude-code/discovery/claude-code-project-catalogue.js +129 -0
- package/dist/adapter/claude-code/discovery/claude-code-recognition.js +46 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-catalogue.js +100 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-discovery.js +61 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-titles.js +28 -0
- package/dist/adapter/claude-code/discovery/discovered-session.js +1 -0
- package/dist/adapter/claude-code/discovery/session-entries.js +41 -0
- package/dist/adapter/claude-code/discovery/transcript-tail.js +81 -0
- package/dist/adapter/claude-code/events/claude-code-session-source.js +197 -0
- package/dist/adapter/claude-code/events/delegation-index.js +15 -0
- package/dist/adapter/claude-code/events/transcript-scan.js +179 -0
- package/dist/adapter/claude-code/hooks/hook-output.js +42 -0
- package/dist/adapter/claude-code/hooks/pre-tool-use-input.js +23 -0
- package/dist/adapter/claude-code/hooks/stop-input.js +25 -0
- package/dist/adapter/claude-code/hooks/subagent-stop-input.js +26 -0
- package/dist/adapter/claude-code/policy/deny-rules.js +46 -0
- package/dist/adapter/claude-code/probe/claude-code-probe.js +86 -0
- package/dist/adapter/claude-code/probe/collectors/agent-tool-input-key-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/denial-kind-collector.js +20 -0
- package/dist/adapter/claude-code/probe/collectors/denied-call-collector.js +11 -0
- package/dist/adapter/claude-code/probe/collectors/identifier-collector.js +19 -0
- package/dist/adapter/claude-code/probe/collectors/line-collector.js +1 -0
- package/dist/adapter/claude-code/probe/collectors/line-type-collector.js +29 -0
- package/dist/adapter/claude-code/probe/collectors/sidechain-collector.js +20 -0
- package/dist/adapter/claude-code/probe/collectors/task-notification-collector.js +51 -0
- package/dist/adapter/claude-code/probe/collectors/tool-result-reference-collector.js +31 -0
- package/dist/adapter/claude-code/probe/collectors/tool-use-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/tool-version-collector.js +14 -0
- package/dist/adapter/claude-code/probe/collectors/top-level-key-collector.js +14 -0
- package/dist/adapter/claude-code/probe/collectors/unknown-line-type-key-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/working-directory-collector.js +28 -0
- package/dist/adapter/claude-code/probe/doctor-report.js +1 -0
- package/dist/adapter/claude-code/probe/meta-tally.js +42 -0
- package/dist/adapter/claude-code/probe/session-probe.js +1 -0
- package/dist/adapter/claude-code/probe/session-tally.js +41 -0
- package/dist/adapter/claude-code/probe/transcript-line.js +30 -0
- package/dist/adapter/claude-code/probe/transcript-tally.js +74 -0
- package/dist/adapter/claude-code/settings/deny-entries.js +65 -0
- package/dist/adapter/claude-code/settings/hook-entries.js +303 -0
- package/dist/adapter/codex/contract/actions.js +69 -0
- package/dist/adapter/codex/contract/assumptions.js +55 -0
- package/dist/adapter/codex/contract/capabilities.js +24 -0
- package/dist/adapter/codex/contract/delegations.js +30 -0
- package/dist/adapter/codex/contract/deliveries.js +25 -0
- package/dist/adapter/codex/contract/envelope.js +33 -0
- package/dist/adapter/codex/contract/hook-refusals.js +14 -0
- package/dist/adapter/codex/contract/hooks.js +46 -0
- package/dist/adapter/codex/contract/messages.js +47 -0
- package/dist/adapter/codex/contract/permissions.js +27 -0
- package/dist/adapter/codex/contract/reviews.js +13 -0
- package/dist/adapter/codex/contract/session.js +31 -0
- package/dist/adapter/codex/contract/turns.js +23 -0
- package/dist/adapter/codex/contract/version.js +15 -0
- package/dist/adapter/codex/discovery/codex-conversations.js +44 -0
- package/dist/adapter/codex/discovery/codex-project-catalogue.js +49 -0
- package/dist/adapter/codex/discovery/codex-recognition.js +20 -0
- package/dist/adapter/codex/discovery/codex-session-catalogue.js +28 -0
- package/dist/adapter/codex/discovery/codex-session-discovery.js +115 -0
- package/dist/adapter/codex/discovery/codex-session-index.js +21 -0
- package/dist/adapter/codex/discovery/codex-session-titles.js +135 -0
- package/dist/adapter/codex/discovery/session-header.js +86 -0
- package/dist/adapter/codex/discovery/session-owners.js +11 -0
- package/dist/adapter/codex/discovery/session-roots.js +49 -0
- package/dist/adapter/codex/events/action-items.js +138 -0
- package/dist/adapter/codex/events/capability-records.js +26 -0
- package/dist/adapter/codex/events/codex-session-source.js +121 -0
- package/dist/adapter/codex/events/hook-refusals.js +27 -0
- package/dist/adapter/codex/events/rollout-scan.js +614 -0
- package/dist/adapter/codex/events/turn-permissions.js +60 -0
- package/dist/adapter/codex/hooks/pre-tool-use-input.js +24 -0
- package/dist/adapter/codex/hooks/stop-refusals.js +57 -0
- package/dist/adapter/codex/probe/codex-doctor-report.js +1 -0
- package/dist/adapter/codex/probe/codex-probe.js +268 -0
- package/dist/adapter/codex/settings/codex-hooks.js +83 -0
- package/dist/cli/cli-command.js +1 -0
- package/dist/cli/command-router.js +42 -0
- package/dist/cli/commands/check-cli-command.js +128 -0
- package/dist/cli/commands/codex-stop-cli-command.js +27 -0
- package/dist/cli/commands/doctor-arguments.js +32 -0
- package/dist/cli/commands/doctor-cli-command.js +31 -0
- package/dist/cli/commands/doctor-usage.js +14 -0
- package/dist/cli/commands/init-cli-command.js +123 -0
- package/dist/cli/commands/menu-cli-command.js +58 -0
- package/dist/cli/commands/notify-cli-command.js +158 -0
- package/dist/cli/commands/refuse-cli-command.js +79 -0
- package/dist/cli/commands/report-arguments.js +62 -0
- package/dist/cli/commands/report-cli-command.js +36 -0
- package/dist/cli/commands/report-usage.js +41 -0
- package/dist/cli/commands/sessions-cli-command.js +184 -0
- package/dist/cli/commands/start-cli-command.js +83 -0
- package/dist/cli/commands/watch-cli-command.js +142 -0
- package/dist/cli/exit-codes.js +13 -0
- package/dist/cli/project-switches.js +46 -0
- package/dist/cli.js +80 -0
- package/dist/composition-root.js +411 -0
- package/dist/core/access/command-line.js +454 -0
- package/dist/core/access/listing.js +58 -0
- package/dist/core/access/path-shape.js +59 -0
- package/dist/core/access/path-tokens.js +37 -0
- package/dist/core/access/protected-access.js +310 -0
- package/dist/core/access/protected-values.js +102 -0
- package/dist/core/access/recorded-effect.js +67 -0
- package/dist/core/access/returns.js +173 -0
- package/dist/core/access/search-output.js +34 -0
- package/dist/core/access/search-reach.js +268 -0
- package/dist/core/access/uses.js +143 -0
- package/dist/core/access/words-before.js +52 -0
- package/dist/core/agent.js +1 -0
- package/dist/core/capability.js +11 -0
- package/dist/core/combined-project-catalogue.js +36 -0
- package/dist/core/combined-session-catalogue.js +25 -0
- package/dist/core/completeness.js +10 -0
- package/dist/core/context.js +1 -0
- package/dist/core/correlation/correlate.js +329 -0
- package/dist/core/delegation.js +1 -0
- package/dist/core/detector/prompt-signals.js +78 -0
- package/dist/core/entry-point.js +1 -0
- package/dist/core/event.js +1 -0
- package/dist/core/evidence.js +9 -0
- package/dist/core/late-message.js +32 -0
- package/dist/core/message.js +1 -0
- package/dist/core/nearest-project.js +28 -0
- package/dist/core/policy/default-policy.js +32 -0
- package/dist/core/policy/glob.js +56 -0
- package/dist/core/policy/parse-policy.js +70 -0
- package/dist/core/policy/policy.js +20 -0
- package/dist/core/policy/resolve-policy.js +16 -0
- package/dist/core/project-catalogue.js +1 -0
- package/dist/core/project-root.js +133 -0
- package/dist/core/provider-titles.js +10 -0
- package/dist/core/redaction/entropy.js +46 -0
- package/dist/core/redaction/redacted.js +4 -0
- package/dist/core/redaction/redactor.js +339 -0
- package/dist/core/redaction/secret-patterns.js +22 -0
- package/dist/core/redaction/value-shapes.js +81 -0
- package/dist/core/redaction/value-trace.js +110 -0
- package/dist/core/review.js +1 -0
- package/dist/core/session-catalogue.js +19 -0
- package/dist/core/session-filter.js +42 -0
- package/dist/core/session-format.js +27 -0
- package/dist/core/session-model.js +1 -0
- package/dist/core/session-reader.js +22 -0
- package/dist/core/session-records.js +1 -0
- package/dist/core/session-source.js +1 -0
- package/dist/core/session-titles.js +21 -0
- package/dist/core/turn.js +1 -0
- package/dist/doctor/codex-doctor.js +14 -0
- package/dist/doctor/doctor-use-case.js +1 -0
- package/dist/doctor/format-selecting-doctor.js +28 -0
- package/dist/doctor/render/attention/attention-rule.js +1 -0
- package/dist/doctor/render/attention/doctor-attention-rules.js +28 -0
- package/dist/doctor/render/attention/rules/damaged-meta-files-rule.js +8 -0
- package/dist/doctor/render/attention/rules/damaged-transcripts-rule.js +9 -0
- package/dist/doctor/render/attention/rules/incomplete-subagent-pairs-rule.js +6 -0
- package/dist/doctor/render/attention/rules/missing-main-transcript-rule.js +5 -0
- package/dist/doctor/render/attention/rules/missing-spilled-results-rule.js +6 -0
- package/dist/doctor/render/attention/rules/multiple-working-directories-rule.js +15 -0
- package/dist/doctor/render/attention/rules/unknown-denial-kinds-rule.js +5 -0
- package/dist/doctor/render/attention/rules/unknown-line-types-rule.js +6 -0
- package/dist/doctor/render/attention/rules/unrecognised-entries-rule.js +6 -0
- package/dist/doctor/render/attention/rules/unusable-directories-rule.js +12 -0
- package/dist/doctor/render/attention/transcript-scopes.js +6 -0
- package/dist/doctor/render/codex-text-doctor-renderer.js +97 -0
- package/dist/doctor/render/doctor-renderers.js +1 -0
- package/dist/doctor/render/json-doctor-renderer.js +7 -0
- package/dist/doctor/render/output-format.js +1 -0
- package/dist/doctor/render/text-doctor-renderer.js +124 -0
- package/dist/doctor/session-doctor.js +16 -0
- package/dist/infrastructure/clack-asker.js +24 -0
- package/dist/infrastructure/clack-chooser.js +40 -0
- package/dist/infrastructure/clack-multi-chooser.js +31 -0
- package/dist/infrastructure/file-alert-store.js +120 -0
- package/dist/infrastructure/file-checked-store.js +55 -0
- package/dist/infrastructure/file-mark-store.js +67 -0
- package/dist/infrastructure/file-onboarding-store.js +93 -0
- package/dist/infrastructure/folder-window.js +26 -0
- package/dist/infrastructure/node-agentwhy-invocation.js +99 -0
- package/dist/infrastructure/node-browser.js +40 -0
- package/dist/infrastructure/node-file-system.js +111 -0
- package/dist/infrastructure/node-local-server.js +115 -0
- package/dist/infrastructure/node-text-input.js +26 -0
- package/dist/infrastructure/os-notifier.js +21 -0
- package/dist/infrastructure/osascript-folder-chooser.js +53 -0
- package/dist/infrastructure/powershell-folder-chooser.js +78 -0
- package/dist/infrastructure/real-directory.js +18 -0
- package/dist/infrastructure/stream-printer.js +11 -0
- package/dist/infrastructure/terminal-banner.js +19 -0
- package/dist/ports/agentwhy-invocation.js +1 -0
- package/dist/ports/alert-store.js +1 -0
- package/dist/ports/asker.js +1 -0
- package/dist/ports/browser.js +1 -0
- package/dist/ports/checked-store.js +1 -0
- package/dist/ports/chooser.js +1 -0
- package/dist/ports/directory-reader.js +1 -0
- package/dist/ports/file-access-error.js +11 -0
- package/dist/ports/file-reader.js +1 -0
- package/dist/ports/file-tail-reader.js +1 -0
- package/dist/ports/file-writer.js +1 -0
- package/dist/ports/folder-chooser.js +1 -0
- package/dist/ports/local-server.js +1 -0
- package/dist/ports/mark-store.js +10 -0
- package/dist/ports/multi-chooser.js +1 -0
- package/dist/ports/notifier.js +1 -0
- package/dist/ports/onboarding-store.js +1 -0
- package/dist/ports/printer.js +1 -0
- package/dist/ports/text-input.js +1 -0
- package/dist/refuse/command-reach.js +135 -0
- package/dist/refuse/command-refusal.js +88 -0
- package/dist/refuse/render/codex-stop-words.js +21 -0
- package/dist/refuse/render/refusal-words.js +34 -0
- package/dist/report/build-report.js +1037 -0
- package/dist/report/check/actions-digest.js +73 -0
- package/dist/report/check/check-lines.js +83 -0
- package/dist/report/check/mark-request.js +90 -0
- package/dist/report/check/marks.js +84 -0
- package/dist/report/check/render/text-digest-renderer.js +332 -0
- package/dist/report/check/session-actions.js +90 -0
- package/dist/report/check/session-check.js +91 -0
- package/dist/report/choose-policy.js +61 -0
- package/dist/report/flow-reads.js +18 -0
- package/dist/report/private-files/tell-lists.js +84 -0
- package/dist/report/project-rules.js +33 -0
- package/dist/report/render/home-relative.js +18 -0
- package/dist/report/render/html-head.js +26 -0
- package/dist/report/render/html-report-components.js +48 -0
- package/dist/report/render/html-report-styles.js +500 -0
- package/dist/report/render/html-sidebar.js +42 -0
- package/dist/report/render/path-tail.js +14 -0
- package/dist/report/render/report-copy.js +1177 -0
- package/dist/report/render/report-page/advanced-view.js +167 -0
- package/dist/report/render/report-page/file-story.js +114 -0
- package/dist/report/render/report-page/files-view.js +381 -0
- package/dist/report/render/report-page/files.js +77 -0
- package/dist/report/render/report-page/fix-wizard-script.js +269 -0
- package/dist/report/render/report-page/fix-wizard.js +310 -0
- package/dist/report/render/report-page/helpers-view.js +383 -0
- package/dist/report/render/report-page/helpers.js +51 -0
- package/dist/report/render/report-page/item-names.js +63 -0
- package/dist/report/render/report-page/protect-patterns.js +13 -0
- package/dist/report/render/report-page/providers.js +208 -0
- package/dist/report/render/report-page/record-view.js +367 -0
- package/dist/report/render/report-page/report-page-renderer.js +129 -0
- package/dist/report/render/report-page/report-views.js +31 -0
- package/dist/report/render/report-page/story-window.js +356 -0
- package/dist/report/render/report-page/times.js +25 -0
- package/dist/report/render/report-page/to-do-view.js +299 -0
- package/dist/report/render/report-page/to-do.js +152 -0
- package/dist/report/render/report-page.js +1 -0
- package/dist/report/render/session-view.js +250 -0
- package/dist/report/render/text-report-renderer.js +981 -0
- package/dist/report/render/ui/add-file-popup.js +122 -0
- package/dist/report/render/ui/app-sidebar.js +78 -0
- package/dist/report/render/ui/ask-panel.js +80 -0
- package/dist/report/render/ui/avatar.js +19 -0
- package/dist/report/render/ui/backdrop.js +29 -0
- package/dist/report/render/ui/brand-mark.js +4 -0
- package/dist/report/render/ui/button.js +67 -0
- package/dist/report/render/ui/callout.js +20 -0
- package/dist/report/render/ui/chat-example.js +17 -0
- package/dist/report/render/ui/checklist.js +50 -0
- package/dist/report/render/ui/confirm-dialog.js +34 -0
- package/dist/report/render/ui/data-table.js +49 -0
- package/dist/report/render/ui/drawer.js +25 -0
- package/dist/report/render/ui/file-chip.js +37 -0
- package/dist/report/render/ui/fold-line.js +22 -0
- package/dist/report/render/ui/guide-card.js +25 -0
- package/dist/report/render/ui/hero.js +37 -0
- package/dist/report/render/ui/labelled-select.js +10 -0
- package/dist/report/render/ui/live-script.js +222 -0
- package/dist/report/render/ui/local-date.js +58 -0
- package/dist/report/render/ui/mode-icon.js +6 -0
- package/dist/report/render/ui/page-shell.js +101 -0
- package/dist/report/render/ui/pill-tabs.js +47 -0
- package/dist/report/render/ui/popup.js +77 -0
- package/dist/report/render/ui/progress.js +35 -0
- package/dist/report/render/ui/project-list.js +284 -0
- package/dist/report/render/ui/scope-choice.js +19 -0
- package/dist/report/render/ui/stats.js +21 -0
- package/dist/report/render/ui/status-icon.js +30 -0
- package/dist/report/render/ui/status-look.js +21 -0
- package/dist/report/render/ui/switch.js +11 -0
- package/dist/report/render/ui/tag.js +19 -0
- package/dist/report/render/ui/task-list.js +56 -0
- package/dist/report/render/ui/tokens.js +46 -0
- package/dist/report/render/ui/update-notice.js +146 -0
- package/dist/report/render/ui/words/app-words.js +163 -0
- package/dist/report/render/ui/words/conversations-words.js +457 -0
- package/dist/report/render/ui/words/month-words.js +59 -0
- package/dist/report/render/ui/words/onboarding-words.js +446 -0
- package/dist/report/render/ui/words/projects-words.js +217 -0
- package/dist/report/render/ui/words/report-words.js +2099 -0
- package/dist/report/render/ui/words/settings-words.js +611 -0
- package/dist/report/render/ui/words/to-fix-words.js +287 -0
- package/dist/report/report-model.js +2 -0
- package/dist/report/report-use-case.js +1 -0
- package/dist/report/rule-names.js +20 -0
- package/dist/report/session-report.js +163 -0
- package/dist/report/start/app-nav.js +37 -0
- package/dist/report/start/conversations/calendar-view.js +104 -0
- package/dist/report/start/conversations/conversation-columns.js +187 -0
- package/dist/report/start/conversations/conversations-renderer.js +54 -0
- package/dist/report/start/conversations/empty-week.js +120 -0
- package/dist/report/start/conversations/files-window.js +166 -0
- package/dist/report/start/conversations/period-section.js +280 -0
- package/dist/report/start/conversations/periods-script.js +440 -0
- package/dist/report/start/conversations/periods.js +110 -0
- package/dist/report/start/conversations/week-view.js +30 -0
- package/dist/report/start/conversations/weeks.js +17 -0
- package/dist/report/start/month/month-renderer.js +50 -0
- package/dist/report/start/month/month-view.js +135 -0
- package/dist/report/start/month/months.js +17 -0
- package/dist/report/start/onboarding/done.js +171 -0
- package/dist/report/start/onboarding/finish-onboarding.js +93 -0
- package/dist/report/start/onboarding/intro.js +100 -0
- package/dist/report/start/onboarding/onboarding-changes.js +40 -0
- package/dist/report/start/onboarding/onboarding-renderer.js +195 -0
- package/dist/report/start/onboarding/onboarding-script.js +400 -0
- package/dist/report/start/onboarding/onboarding-view.js +98 -0
- package/dist/report/start/onboarding/project-step.js +210 -0
- package/dist/report/start/onboarding/steps.js +239 -0
- package/dist/report/start/onboarding/welcome.js +66 -0
- package/dist/report/start/page-notice.js +10 -0
- package/dist/report/start/projects/index-projects.js +43 -0
- package/dist/report/start/projects/moved-page.js +82 -0
- package/dist/report/start/projects/project-switch.js +138 -0
- package/dist/report/start/projects/projects-window.js +67 -0
- package/dist/report/start/projects/temporary-space.js +18 -0
- package/dist/report/start/render/air-datepicker-vendor.js +27 -0
- package/dist/report/start/render/session-status.js +41 -0
- package/dist/report/start/render/start-words.js +84 -0
- package/dist/report/start/repository.js +28 -0
- package/dist/report/start/serve/index-handler.js +372 -0
- package/dist/report/start/serve/onboarding-request.js +50 -0
- package/dist/report/start/serve/settings-request.js +1 -0
- package/dist/report/start/serve/settings-setup.js +193 -0
- package/dist/report/start/session-index.js +1 -0
- package/dist/report/start/session-start.js +974 -0
- package/dist/report/start/settings/alerts-tab.js +104 -0
- package/dist/report/start/settings/files-tab.js +169 -0
- package/dist/report/start/settings/general-tab.js +71 -0
- package/dist/report/start/settings/settings-renderer.js +254 -0
- package/dist/report/start/settings/settings-script.js +161 -0
- package/dist/report/start/settings/settings-view.js +240 -0
- package/dist/report/start/settings/settings-windows.js +334 -0
- package/dist/report/start/settings-files.js +43 -0
- package/dist/report/start/to-fix/done-list.js +45 -0
- package/dist/report/start/to-fix/file-window.js +110 -0
- package/dist/report/start/to-fix/to-fix-list.js +70 -0
- package/dist/report/start/to-fix/to-fix-renderer.js +237 -0
- package/dist/report/start/to-fix/to-fix-script.js +94 -0
- package/dist/report/start/to-fix/to-fix-view.js +124 -0
- package/dist/report/watch/agent-alert.js +72 -0
- package/dist/report/watch/notice-choices.js +35 -0
- package/dist/report/watch/notice-settings.js +65 -0
- package/dist/report/watch/preferences.js +100 -0
- package/dist/report/watch/render/instruction-words.js +54 -0
- package/dist/report/watch/render/notice-words.js +182 -0
- package/dist/report/watch/subagent-watch.js +345 -0
- package/dist/report/watch/watch-notice.js +1 -0
- package/dist/setup/behind.js +18 -0
- package/dist/setup/codex-mirror.js +171 -0
- package/dist/setup/not-a-project.js +19 -0
- package/dist/setup/project-setup.js +644 -0
- package/dist/setup/protected-patterns.js +30 -0
- package/dist/shared/colour.js +23 -0
- package/dist/shared/compare.js +4 -0
- package/dist/shared/content-version.js +13 -0
- package/dist/shared/counter.js +11 -0
- package/dist/shared/file-stamp.js +4 -0
- package/dist/shared/json.js +13 -0
- package/dist/shared/label.js +13 -0
- package/dist/shared/package-name.js +6 -0
- package/dist/shared/plain-invocation.js +44 -0
- package/dist/shared/plain-version.js +21 -0
- package/dist/shared/printable.js +25 -0
- package/dist/shared/renderer.js +1 -0
- package/dist/shared/sentence.js +20 -0
- package/dist/shared/terminal-logo.js +41 -0
- package/dist/shared/text-table.js +15 -0
- package/dist/shared/wrap.js +29 -0
- package/package.json +70 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { escapeHtml as e } from '../../render/html-report-components.js';
|
|
2
|
+
import { inLanguages } from '../../render/report-copy.js';
|
|
3
|
+
import { addFilePopup } from '../../render/ui/add-file-popup.js';
|
|
4
|
+
import { confirmDialog } from '../../render/ui/confirm-dialog.js';
|
|
5
|
+
/** The window a hook's switch opens: the one that turns it on where it is off, and off where it is on. */
|
|
6
|
+
export function hookWindowId(hook, on) {
|
|
7
|
+
return 'set-' + hook + '-' + (on ? 'on' : 'off');
|
|
8
|
+
}
|
|
9
|
+
export const WATCH_WINDOW = 'set-watch-too';
|
|
10
|
+
/** K8, K9: every private file that is not blocked whole, blocked in one confirmed write. */
|
|
11
|
+
export const FINISH_WINDOW = 'set-finish';
|
|
12
|
+
export const ADD_WINDOW = 'set-add';
|
|
13
|
+
/** `codex-blocks-too` CK5: the files blocked here, kept from Codex's shell commands too. */
|
|
14
|
+
export const CODEX_WINDOW = 'set-codex';
|
|
15
|
+
export const ADD_CONFIRM_WINDOW = 'set-add-confirm';
|
|
16
|
+
/** The window a row not watched yet opens (F34a): that one group, confirmed like every other write. */
|
|
17
|
+
export function rowWatchWindowId(at) {
|
|
18
|
+
return 'set-watch-row-' + at;
|
|
19
|
+
}
|
|
20
|
+
export function removeWindowId(at) {
|
|
21
|
+
return 'set-remove-' + at;
|
|
22
|
+
}
|
|
23
|
+
/** F57: the confirmation of one row's switch, and of taking a told row off its list. */
|
|
24
|
+
export function modeWindowId(at) {
|
|
25
|
+
return 'set-mode-' + at;
|
|
26
|
+
}
|
|
27
|
+
export function untellWindowId(at) {
|
|
28
|
+
return 'set-untell-' + at;
|
|
29
|
+
}
|
|
30
|
+
/** General's confirmation of making everything agentwhy saved one file's (F56). */
|
|
31
|
+
export function scopeWindowId(file) {
|
|
32
|
+
return 'set-scope-' + file;
|
|
33
|
+
}
|
|
34
|
+
/** General's **Uninstall** (F59). */
|
|
35
|
+
export const UNINSTALL_WINDOW = 'set-uninstall';
|
|
36
|
+
export function settingsWindows(view) {
|
|
37
|
+
if (!view.canWrite)
|
|
38
|
+
return '';
|
|
39
|
+
return hookWindow(view, 'watch') + finishWindow(view) + codexWindow(view) + scopeWindow(view, 'local') + scopeWindow(view, 'shared') + uninstallWindow(view) +
|
|
40
|
+
(view.unread.length > 0 || view.rows.some((row) => !row.watched) ? watchWindow(view) : '') +
|
|
41
|
+
view.rows.map((row, at) => (row.watched || row.name === undefined ? '' : rowWatchWindow(view, row.name, row.patterns, at))).join('') +
|
|
42
|
+
view.rows.map((row, at) => (row.remove === undefined ? '' : removeWindow(at, row.remove.rule, row.remove.file))).join('') +
|
|
43
|
+
view.rows.map((row, at) => (row.switchTo === undefined ? '' : modeWindow(view, row, at))).join('') +
|
|
44
|
+
view.rows.map((row, at) => (row.untell === undefined ? '' : untellWindow(view, row, at))).join('') +
|
|
45
|
+
(view.canAdd ? addWindow() + addConfirmWindow(view) : '');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* F40: turning alerts on or off, confirmed; turning off is the coral button. It is written where General says (F56) -
|
|
49
|
+
* the one file everything is in, else where an add goes - and asks nobody again. `refuse` has no window of its own: it
|
|
50
|
+
* is half of every block (`block-means-blocked` K1), and Finish blocking is where a missing one is put back.
|
|
51
|
+
*/
|
|
52
|
+
function hookWindow(view, hook) {
|
|
53
|
+
const state = view.alerts;
|
|
54
|
+
const on = !state.on;
|
|
55
|
+
const words = 'set.confirm.alerts.' + (on ? 'on' : 'off');
|
|
56
|
+
const id = hookWindowId(hook, on);
|
|
57
|
+
const where = on ? view.writeTo : state.who ?? 'local';
|
|
58
|
+
// `init --watch` alone takes a running `refuse` out of the file it writes (R4b), so the command names it too
|
|
59
|
+
// wherever it runs from that file; the page's own write says the same with `keep`.
|
|
60
|
+
const otherIn = view.stop.who === where;
|
|
61
|
+
const command = on
|
|
62
|
+
? 'agentwhy init --' + hook + (otherIn ? ' --refuse' : '') + shared(where)
|
|
63
|
+
: 'agentwhy init --remove --' + hook + shared(where);
|
|
64
|
+
return confirmDialog({
|
|
65
|
+
id,
|
|
66
|
+
glyph: '',
|
|
67
|
+
title: inLanguages((t) => t(words)),
|
|
68
|
+
subject: '',
|
|
69
|
+
sentence: inLanguages((t) => t(words + '.text')),
|
|
70
|
+
option: '',
|
|
71
|
+
note: say(),
|
|
72
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
73
|
+
confirm: inLanguages((t) => t(on ? 'set.confirm.turnOn' : 'set.confirm.turnOff')),
|
|
74
|
+
tone: on ? 'mint' : 'primary',
|
|
75
|
+
confirmAttributes: write({ change: 'hooks', hooks: [hook], on, where }) + commandAttribute(where, command),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* F56: everything agentwhy saved, into one file - its rules moved one by one, then its hooks. Offered only where there
|
|
80
|
+
* is something to move; the command for a page opened as a file is the same runs, in the same order.
|
|
81
|
+
*/
|
|
82
|
+
function scopeWindow(view, file) {
|
|
83
|
+
const move = view.moves[file];
|
|
84
|
+
if (move.patterns.length === 0 && move.hooks.length === 0)
|
|
85
|
+
return '';
|
|
86
|
+
const from = file === 'local' ? 'shared' : 'local';
|
|
87
|
+
const commands = [
|
|
88
|
+
...move.patterns.flatMap((pattern) => [
|
|
89
|
+
'agentwhy init --remove --unprotect ' + quoted(pattern) + shared(from),
|
|
90
|
+
'agentwhy init --protect ' + quoted(pattern) + shared(file),
|
|
91
|
+
]),
|
|
92
|
+
...(move.hooks.length === 0 ? [] : ['agentwhy init ' + hooksNow(view, file, move.hooks).map((hook) => '--' + hook).join(' ') + shared(file)]),
|
|
93
|
+
];
|
|
94
|
+
return confirmDialog({
|
|
95
|
+
id: scopeWindowId(file),
|
|
96
|
+
glyph: '',
|
|
97
|
+
title: inLanguages((t) => t('set.confirm.scope.' + file)),
|
|
98
|
+
subject: '',
|
|
99
|
+
sentence: inLanguages((t) => t('set.confirm.scope.' + file + '.text')),
|
|
100
|
+
option: '',
|
|
101
|
+
note: say(),
|
|
102
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
103
|
+
confirm: inLanguages((t) => t('set.confirm.scope.go')),
|
|
104
|
+
tone: 'mint',
|
|
105
|
+
confirmAttributes: write({ change: 'scope', patterns: move.patterns, hooks: move.hooks, where: file }) + commandAttribute(file, commands.join(' && ')),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* F59: both hooks and every whole rule agentwhy wrote, out of each file that holds any - the coral button, since it takes
|
|
110
|
+
* all protection away. It says what stays, and, where the shared file is one of them, that everyone gets the change.
|
|
111
|
+
*/
|
|
112
|
+
function uninstallWindow(view) {
|
|
113
|
+
const files = ['local', 'shared'].filter((file) => view.uninstall[file] !== undefined);
|
|
114
|
+
if (files.length === 0)
|
|
115
|
+
return '';
|
|
116
|
+
const command = files.map((file) => 'agentwhy init --remove --watch --refuse' +
|
|
117
|
+
(view.uninstall[file] ?? []).map((rule) => ' --unprotect ' + quoted(rule)).join('') + shared(file)).join(' && ');
|
|
118
|
+
return confirmDialog({
|
|
119
|
+
id: UNINSTALL_WINDOW,
|
|
120
|
+
glyph: '',
|
|
121
|
+
title: inLanguages((t) => t('set.confirm.uninstall')),
|
|
122
|
+
subject: '',
|
|
123
|
+
sentence: inLanguages((t) => t('set.confirm.uninstall.text') + (files.includes('shared') ? ' ' + t('set.confirm.everyone') : '')),
|
|
124
|
+
option: '',
|
|
125
|
+
note: say(),
|
|
126
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
127
|
+
confirm: inLanguages((t) => t('set.confirm.uninstall.go')),
|
|
128
|
+
tone: 'primary',
|
|
129
|
+
confirmAttributes: write({ change: 'uninstall', rules: view.uninstall }) + commandAttribute('local', command),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/** The hooks a file runs once the moved ones are in it: `init` with hook flags takes out any it is not given (R4b). */
|
|
133
|
+
function hooksNow(view, file, moved) {
|
|
134
|
+
const there = ['watch', 'refuse'].filter((hook) => (hook === 'watch' ? view.alerts.who : view.stop.who) === file);
|
|
135
|
+
return [...new Set([...there, ...moved])];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* K9: what is missing of every block, in one write - the rules no file holds, with the built-in list and `refuse`, as an
|
|
139
|
+
* add writes them; or, where every rule is there, `refuse` alone, where it is written and asks nobody (F56). The window
|
|
140
|
+
* names the files as their rows do, and closes with the guidelines' honesty line, as every block does.
|
|
141
|
+
*/
|
|
142
|
+
function finishWindow(view) {
|
|
143
|
+
const { rows, patterns, refuse } = view.unfinished;
|
|
144
|
+
if (patterns.length === 0 && !refuse)
|
|
145
|
+
return '';
|
|
146
|
+
const open = view.rows.filter((row) => row.kept !== undefined);
|
|
147
|
+
const alertsIn = view.alerts.who === view.writeTo;
|
|
148
|
+
const confirmAttributes = patterns.length > 0
|
|
149
|
+
? write({ change: 'adopt', patterns, where: view.addTo }) + commandAttribute(view.addTo, protectCommand(view, patterns, view.addTo))
|
|
150
|
+
: write({ change: 'hooks', hooks: ['refuse'], on: true, where: view.writeTo }) +
|
|
151
|
+
commandAttribute(view.writeTo, 'agentwhy init --refuse' + (alertsIn ? ' --watch' : '') + shared(view.writeTo));
|
|
152
|
+
return confirmDialog({
|
|
153
|
+
id: FINISH_WINDOW,
|
|
154
|
+
glyph: '',
|
|
155
|
+
title: inLanguages((t) => t('set.finish.title')),
|
|
156
|
+
subject: '',
|
|
157
|
+
sentence: inLanguages((t) => t('set.finish.text', { n: rows, names: open.map((row) => rowName(row, t)).join(', ') }) +
|
|
158
|
+
// The built-in list it writes is what these rows are, so the add's "written into your project with it" is not said.
|
|
159
|
+
((patterns.length > 0 ? view.addTo : view.writeTo) === 'shared' ? ' ' + t('set.confirm.everyone') : '') +
|
|
160
|
+
'<span class="set-soft set-honest">' + t('set.finish.honest') + '</span>'),
|
|
161
|
+
option: '',
|
|
162
|
+
note: say(),
|
|
163
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
164
|
+
confirm: inLanguages((t) => t('set.finish.yes', { n: rows })),
|
|
165
|
+
tone: 'mint',
|
|
166
|
+
confirmAttributes,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* CK5, CK7: Codex's hook, written to match the block Claude Code runs - the page's confirmation is the consent, as for
|
|
171
|
+
* every block - and the honesty line under it. Opened as a file, it hands over `agentwhy init --codex`.
|
|
172
|
+
*/
|
|
173
|
+
function codexWindow(view) {
|
|
174
|
+
if (view.codex !== 'off' || !view.stop.on)
|
|
175
|
+
return '';
|
|
176
|
+
return confirmDialog({
|
|
177
|
+
id: CODEX_WINDOW,
|
|
178
|
+
glyph: '',
|
|
179
|
+
title: inLanguages((t) => t('set.codex.title')),
|
|
180
|
+
subject: '',
|
|
181
|
+
sentence: inLanguages((t) => t('set.codex.text') + '<span class="set-soft set-honest">' + t('set.finish.honest') + '</span>'),
|
|
182
|
+
option: '',
|
|
183
|
+
note: say(),
|
|
184
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
185
|
+
confirm: inLanguages((t) => t('set.codex.yes')),
|
|
186
|
+
tone: 'mint',
|
|
187
|
+
confirmAttributes: write({ change: 'codex' }) + commandAttribute(view.writeTo, 'agentwhy init --codex'),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/** F34 and O7: the project's own rules, copied into the file the hooks read - with the built-in list where it is missing. */
|
|
191
|
+
function watchWindow(view) {
|
|
192
|
+
const patterns = [...new Set([...view.withBuiltIn, ...view.unread.map((rule) => rule.rule)])];
|
|
193
|
+
return confirmDialog({
|
|
194
|
+
id: WATCH_WINDOW,
|
|
195
|
+
glyph: '',
|
|
196
|
+
title: inLanguages((t) => t('set.confirm.watch')),
|
|
197
|
+
subject: '',
|
|
198
|
+
sentence: inLanguages((t) => t('set.confirm.watch.text') + extra(view, t)),
|
|
199
|
+
option: '',
|
|
200
|
+
note: say(),
|
|
201
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
202
|
+
confirm: inLanguages((t) => t('set.confirm.watch.go')),
|
|
203
|
+
confirmAttributes: write({ change: 'adopt', patterns, where: view.addTo }) + commandAttribute(view.addTo, protectCommand(view, patterns, view.addTo)),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/** F34a: one built-in group written into the file the hooks read - the same change as Watch them too, for that group. */
|
|
207
|
+
function rowWatchWindow(view, name, patterns, at) {
|
|
208
|
+
return confirmDialog({
|
|
209
|
+
id: rowWatchWindowId(at),
|
|
210
|
+
glyph: '',
|
|
211
|
+
title: inLanguages((t) => t('set.confirm.row')),
|
|
212
|
+
subject: '',
|
|
213
|
+
sentence: inLanguages((t) => t('set.confirm.row.text', { name: '<strong>' + t('set.rule.' + name) + '</strong>' })),
|
|
214
|
+
option: '',
|
|
215
|
+
note: say(),
|
|
216
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
217
|
+
confirm: inLanguages((t) => t('set.confirm.watch.go')),
|
|
218
|
+
confirmAttributes: write({ change: 'adopt', patterns, where: view.addTo }) + commandAttribute(view.addTo, protectCommand(view, patterns, view.addTo)),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* F57: one row to the other mode. Going to Tell me is the risky way, so it is the coral button and says the cost - for a
|
|
223
|
+
* built-in group, in the words of the decision of 2026-09-24: what is inside goes to the AI company, and only changing
|
|
224
|
+
* the keys undoes it. Where alerts are off, it says the report is then the only place it is seen. Going to Block is
|
|
225
|
+
* the mint "Yes, block it". A page opened as a file cannot write a told list, so its command is `agentwhy start`.
|
|
226
|
+
*/
|
|
227
|
+
function modeWindow(view, row, at) {
|
|
228
|
+
const change = row.switchTo;
|
|
229
|
+
const tell = change.to === 'tell';
|
|
230
|
+
const words = tell ? (row.name === undefined ? 'set.confirm.tell' : 'set.confirm.tell.secret') : 'set.confirm.block';
|
|
231
|
+
return confirmDialog({
|
|
232
|
+
id: modeWindowId(at),
|
|
233
|
+
glyph: '',
|
|
234
|
+
title: inLanguages((t) => t(words)),
|
|
235
|
+
subject: '',
|
|
236
|
+
sentence: inLanguages((t) => t(words + '.text', { name: rowName(row, t) }) + (tell && !view.alerts.on ? ' ' + t('set.confirm.tell.alertsOff') : '')),
|
|
237
|
+
option: '',
|
|
238
|
+
note: say(),
|
|
239
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
240
|
+
confirm: inLanguages((t) => t(tell ? 'set.confirm.tell.go' : 'set.confirm.block.go')),
|
|
241
|
+
tone: tell ? 'primary' : 'mint',
|
|
242
|
+
confirmAttributes: write({ change: 'mode', to: change.to, patterns: change.patterns, rules: change.rules, where: view.writeTo }) + commandAttribute(view.writeTo, 'agentwhy start'),
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
function untellWindow(view, row, at) {
|
|
246
|
+
return confirmDialog({
|
|
247
|
+
id: untellWindowId(at),
|
|
248
|
+
glyph: '',
|
|
249
|
+
title: inLanguages((t) => t('set.confirm.untell')),
|
|
250
|
+
subject: '',
|
|
251
|
+
sentence: inLanguages((t) => t('set.confirm.untell.text', { name: rowName(row, t) })),
|
|
252
|
+
option: '',
|
|
253
|
+
note: say(),
|
|
254
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
255
|
+
confirm: inLanguages((t) => t('set.confirm.remove.go')),
|
|
256
|
+
tone: 'primary',
|
|
257
|
+
confirmAttributes: write({ change: 'mode', to: 'none', patterns: row.untell ?? [], rules: [], where: view.writeTo }) + commandAttribute(view.writeTo, 'agentwhy start'),
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/** A row as a sentence names it: a built-in group by its words, anything else by its pattern. */
|
|
261
|
+
function rowName(row, t) {
|
|
262
|
+
return row.name === undefined ? '<code class="set-code">' + e(row.patterns[0] ?? '') + '</code>' : '<strong>' + t('set.rule.' + row.name) + '</strong>';
|
|
263
|
+
}
|
|
264
|
+
function removeWindow(at, rule, file) {
|
|
265
|
+
return confirmDialog({
|
|
266
|
+
id: removeWindowId(at),
|
|
267
|
+
glyph: '',
|
|
268
|
+
title: inLanguages((t) => t('set.confirm.remove')),
|
|
269
|
+
subject: '',
|
|
270
|
+
sentence: inLanguages((t) => t('set.confirm.remove.text', { name: '<code class="set-code">' + e(rule) + '</code>' })),
|
|
271
|
+
option: '',
|
|
272
|
+
note: say(),
|
|
273
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
274
|
+
confirm: inLanguages((t) => t('set.confirm.remove.go')),
|
|
275
|
+
tone: 'primary',
|
|
276
|
+
confirmAttributes: write({ change: 'unprotect', pattern: rule, where: file }),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* F35, F36: the kit's "Add a private file" (`add-file-popup.ts`), which the onboarding opens too. It hands the page a
|
|
281
|
+
* name turned into a pattern, and Settings' script opens the confirmation below with it.
|
|
282
|
+
*/
|
|
283
|
+
function addWindow() {
|
|
284
|
+
return addFilePopup(ADD_WINDOW);
|
|
285
|
+
}
|
|
286
|
+
/** The confirmation of an add: the pattern exactly as it will be written (F35), and what it means in words (F36). */
|
|
287
|
+
function addConfirmWindow(view) {
|
|
288
|
+
const name = '<code class="set-code" data-set-name></code>';
|
|
289
|
+
const kinds = ['file', 'folder', 'pattern'].map((kind) => '<span class="set-kind" data-set-kind="' + kind + '"' + (kind === 'file' ? '' : ' hidden') + '>' +
|
|
290
|
+
inLanguages((t) => t('set.confirm.add.' + kind, { name })) + '</span>').join('');
|
|
291
|
+
return confirmDialog({
|
|
292
|
+
id: ADD_CONFIRM_WINDOW,
|
|
293
|
+
glyph: '',
|
|
294
|
+
title: inLanguages((t) => t('set.confirm.add')),
|
|
295
|
+
subject: '<span class="chip set-pattern" data-set-pattern></span>',
|
|
296
|
+
sentence: kinds + inLanguages((t) => ' ' + t('set.confirm.add.also') + extra(view, t)),
|
|
297
|
+
option: '',
|
|
298
|
+
note: say(),
|
|
299
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
300
|
+
confirm: inLanguages((t) => t('set.confirm.add.go')),
|
|
301
|
+
// What the script needs to post the add, and to say it as a command where the page is a file: `--watch` rides
|
|
302
|
+
// along where alerts run from that file, since `init` with a hook flag takes out any it is not given (R4b).
|
|
303
|
+
confirmAttributes: ' data-set-add="' + e(JSON.stringify({ builtIn: view.withBuiltIn, where: view.addTo, watch: view.alerts.who === view.addTo })) + '"',
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
/** What else a write from Private files does: the built-in list goes with it (S4.3), and a shared file reaches everyone. */
|
|
307
|
+
function extra(view, t) {
|
|
308
|
+
return (view.withBuiltIn.length === 0 ? '' : ' ' + t('set.confirm.builtIn')) + (view.addTo === 'shared' ? ' ' + t('set.confirm.everyone') : '');
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Protecting from a page opened as a file: the rules, and `refuse` with them (F38, amended 2026-09-24), and `watch`
|
|
312
|
+
* where it runs from the same file - `init` with a hook flag takes out any it is not given (R4b).
|
|
313
|
+
*/
|
|
314
|
+
function protectCommand(view, patterns, where) {
|
|
315
|
+
return 'agentwhy init' + patterns.map((pattern) => ' --protect ' + quoted(pattern)).join('') + ' --refuse' +
|
|
316
|
+
(view.alerts.who === where ? ' --watch' : '') + shared(where);
|
|
317
|
+
}
|
|
318
|
+
function shared(where) {
|
|
319
|
+
return where === 'shared' ? ' --shared' : '';
|
|
320
|
+
}
|
|
321
|
+
/** A shell word, quoted where it needs to be: the same rule the page's script uses for a typed name. */
|
|
322
|
+
function quoted(text) {
|
|
323
|
+
return /^[\w@%+=:,./*-]+$/.test(text) ? text : "'" + text.replace(/'/g, "'\\''") + "'";
|
|
324
|
+
}
|
|
325
|
+
function commandAttribute(where, command) {
|
|
326
|
+
return ' data-set-command-' + where + '="' + e(command) + '"';
|
|
327
|
+
}
|
|
328
|
+
/** The line a window's script fills: saving, the reason a change was refused (R59), or the command to run (R61). */
|
|
329
|
+
function say() {
|
|
330
|
+
return '<p class="set-say" data-set-say hidden></p>';
|
|
331
|
+
}
|
|
332
|
+
function write(body) {
|
|
333
|
+
return ' data-set-write="' + e(JSON.stringify(body)) + '"';
|
|
334
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { fileRulesIn } from '../../adapter/claude-code/settings/deny-entries.js';
|
|
2
|
+
import { missingHookEntries } from '../../adapter/claude-code/settings/hook-entries.js';
|
|
3
|
+
/**
|
|
4
|
+
* A settings file, read the way `init` reads it. Absent is an answer - a project nobody set up has none - and a file
|
|
5
|
+
* that is not a JSON object is `unreadable`, so nothing is drawn from a guess about what it holds.
|
|
6
|
+
*/
|
|
7
|
+
export async function readSettingsFile(files, path) {
|
|
8
|
+
let text;
|
|
9
|
+
try {
|
|
10
|
+
text = await files.readText(path);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const settings = JSON.parse(text);
|
|
17
|
+
if (settings === null || typeof settings !== 'object' || Array.isArray(settings))
|
|
18
|
+
return 'unreadable';
|
|
19
|
+
return settings;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return 'unreadable';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Whether a file runs a hook whole. `watch` is not installed where only one of its two events is (`hookEntries`'s own
|
|
27
|
+
* comment): a file left running `watch` on `SubagentStop` alone never says anything in the conversation and never checks
|
|
28
|
+
* the session's own agent, so a hook this incomplete reads as off - the `missingHookEntries` a fresh `init` uses to find
|
|
29
|
+
* the gap.
|
|
30
|
+
*/
|
|
31
|
+
export function hookComplete(settings, hook) {
|
|
32
|
+
return missingHookEntries(settings, [hook], '', undefined).length === 0;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Whether agentwhy is set up in a project, from its settings files (`.ai/specs/2026-09-27-which-project.md` V10, and the
|
|
36
|
+
* onboarding's W23 as amended the same day): one of its hooks runs there whole, or the files hold rules that block a file
|
|
37
|
+
* - a rule a person wrote by hand included. Decided by the maintainer on 2026-09-28: a project that blocks files is set
|
|
38
|
+
* up, and is not offered the setup again. A file that could not be read says nothing.
|
|
39
|
+
*/
|
|
40
|
+
export function setUpBy(files) {
|
|
41
|
+
return files.some((settings) => settings !== undefined && settings !== 'unreadable' &&
|
|
42
|
+
(hookComplete(settings, 'watch') || hookComplete(settings, 'refuse') || fileRulesIn(settings).length > 0));
|
|
43
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { escapeHtml as e } from '../../render/html-report-components.js';
|
|
2
|
+
import { inLanguages } from '../../render/report-copy.js';
|
|
3
|
+
import { textButton } from '../../render/ui/button.js';
|
|
4
|
+
import { confirmDialog } from '../../render/ui/confirm-dialog.js';
|
|
5
|
+
import { dayName } from '../../render/ui/local-date.js';
|
|
6
|
+
import { opener } from '../../render/ui/popup.js';
|
|
7
|
+
import { fileTitle } from './to-fix-list.js';
|
|
8
|
+
export function undoWindowId(at) {
|
|
9
|
+
return 'fix-undo-' + at;
|
|
10
|
+
}
|
|
11
|
+
/** "today", "yesterday", or the day's date, in the page's zone (O2); `standing` starts a line: "Today". */
|
|
12
|
+
export function dayWord(when, t, lang, standing = false) {
|
|
13
|
+
return when.relative === undefined ? dayName(when.day, lang) : t((standing ? 'fix.day.' : 'fix.') + when.relative);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The Done tab (T9, T10): every standing mark, newest first, with what the person wrote. A shared page lists them
|
|
17
|
+
* without the notes and without Undo (T19, R37).
|
|
18
|
+
*/
|
|
19
|
+
export function doneList(done, writable) {
|
|
20
|
+
if (done.length === 0)
|
|
21
|
+
return '<p class="tf-empty">' + inLanguages((t) => t('fix.done.none')) + '</p>';
|
|
22
|
+
return '<p class="tf-done-lead">' + inLanguages((t) => t('fix.done.lead')) + '</p>' +
|
|
23
|
+
'<ul class="tf-done">' + done.map((file, at) => '<li class="tf-done-row"><span class="tf-done-text"><span class="tf-done-title">' + inLanguages((t) => fileTitle(file, t)) + '</span>' +
|
|
24
|
+
'<span class="tf-done-sub"><span class="chip">' + e(file.path) + '</span>' +
|
|
25
|
+
(file.note === undefined ? '' : '<span class="tf-note">“' + e(file.note) + '”</span>') + '</span></span>' +
|
|
26
|
+
'<span class="tf-fixed">' + inLanguages((t, lang) => t('fix.done.fixed', { when: dayWord(file.when, t, lang) })) + '</span>' +
|
|
27
|
+
(writable ? textButton(inLanguages((t) => t('fix.done.undo')), opener(undoWindowId(at)), 'tf-undo') : '') +
|
|
28
|
+
'</li>').join('') + '</ul>';
|
|
29
|
+
}
|
|
30
|
+
/** T10: Undo puts back work the person said was done, so it asks first (D6). */
|
|
31
|
+
export function undoWindows(done) {
|
|
32
|
+
return done.map((file, at) => confirmDialog({
|
|
33
|
+
id: undoWindowId(at),
|
|
34
|
+
glyph: '',
|
|
35
|
+
title: inLanguages((t) => t('fix.undo.title')),
|
|
36
|
+
subject: '<span class="chip">' + e(file.path) + '</span>',
|
|
37
|
+
sentence: inLanguages((t) => t('fix.undo.text')),
|
|
38
|
+
option: '',
|
|
39
|
+
note: '<p class="tf-say" data-fix-say hidden></p>',
|
|
40
|
+
cancel: inLanguages((t) => t('app.cancel')),
|
|
41
|
+
confirm: inLanguages((t) => t('fix.undo.go')),
|
|
42
|
+
tone: 'primary',
|
|
43
|
+
confirmAttributes: ' data-fix-unmark="' + e(JSON.stringify({ path: file.path })) + '"',
|
|
44
|
+
})).join('');
|
|
45
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { escapeHtml as e } from '../../render/html-report-components.js';
|
|
2
|
+
import { inLanguages, labelAttributes } from '../../render/report-copy.js';
|
|
3
|
+
import { closeButton, pill } from '../../render/ui/button.js';
|
|
4
|
+
import { callout } from '../../render/ui/callout.js';
|
|
5
|
+
import { fixWizard } from '../../render/report-page/fix-wizard.js';
|
|
6
|
+
import { storyWindowOf } from '../../render/report-page/story-window.js';
|
|
7
|
+
import { fixId, storyId } from '../../render/report-page/to-do-view.js';
|
|
8
|
+
import { CLOSES, opener, popup, popupFoot } from '../../render/ui/popup.js';
|
|
9
|
+
import { dayWord } from './done-list.js';
|
|
10
|
+
import { fileTitle } from './to-fix-list.js';
|
|
11
|
+
/** T15: the conversations shown before "Show all". */
|
|
12
|
+
const FIRST = 6;
|
|
13
|
+
/** The window a card's "What happened" opens (T11a): the report page's own id for it. */
|
|
14
|
+
export function happenedId(at) {
|
|
15
|
+
return storyId(at);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A file's Fix it (T11-T15): the report page's own wizard, one step at a time, for the file as every conversation read
|
|
19
|
+
* it - with where it was read folded under "Now fixing", and a note in the last step, sent with the mark.
|
|
20
|
+
*/
|
|
21
|
+
export function fixWindow(files, at, page) {
|
|
22
|
+
const file = files[at];
|
|
23
|
+
return fixWizard(files.map((each) => each.item), at, {
|
|
24
|
+
done: new Set(),
|
|
25
|
+
shared: !page.writable,
|
|
26
|
+
protectKeys: new Map(),
|
|
27
|
+
protectedPaths: new Set(),
|
|
28
|
+
...(page.told === undefined ? {} : { toldPaths: page.told }),
|
|
29
|
+
protectAt: page.settings + '#files',
|
|
30
|
+
}, {
|
|
31
|
+
...(file.reopened === undefined ? {} : { notice: backAgain(file) }),
|
|
32
|
+
where: {
|
|
33
|
+
summary: inLanguages((t) => t('fix.window.where') + ' · ' + t('fix.in', { n: file.count })),
|
|
34
|
+
body: whereList(file),
|
|
35
|
+
},
|
|
36
|
+
note: page.writable,
|
|
37
|
+
skip: file.skip,
|
|
38
|
+
since: page.since,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* "What happened" (T11a): the report page's own window - Story, Diagram, Record - told from the newest conversation that
|
|
43
|
+
* read the file, which it names, with every conversation in a fourth tab. A file no report could tell falls back to what
|
|
44
|
+
* the index knows: what the AI did, where, and what to do.
|
|
45
|
+
*/
|
|
46
|
+
export function happenedWindow(file, kind, at, page) {
|
|
47
|
+
if (file.story !== undefined) {
|
|
48
|
+
const { story, sessionId, conversation } = file.story;
|
|
49
|
+
const title = conversation.entry.title === undefined ? undefined : '“' + e(conversation.entry.title) + '”';
|
|
50
|
+
return storyWindowOf(story, file.item, at, sessionId, false, page.clock, {
|
|
51
|
+
context: inLanguages((t, lang) => t('fix.story.from', {
|
|
52
|
+
title: title ?? t('fix.window.untitled'),
|
|
53
|
+
day: dayWord(conversation.when, t, lang, true),
|
|
54
|
+
time: conversation.when.time,
|
|
55
|
+
}) + (file.count > 1 ? ' ' + t('fix.story.more', { n: file.count - 1 }) : '')),
|
|
56
|
+
tabs: [{ label: inLanguages((t) => t('fix.story.tab')) + ' <span class="tf-tab-count">' + file.count + '</span>', panel: '<div class="tf-story-where">' + whereList(file) + '</div>' }],
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const id = happenedId(at);
|
|
60
|
+
const did = file.label === 'unknown' ? 'unknown' : kind;
|
|
61
|
+
const head = '<div class="tf-window-head"><div class="tf-window-top">' +
|
|
62
|
+
'<span class="tf-window-group tf-window-' + kind + '">' + inLanguages((t) => t('fix.' + kind)) + '</span>' +
|
|
63
|
+
closeButton(labelAttributes((t) => t('app.close')) + CLOSES) + '</div>' +
|
|
64
|
+
'<h2 class="tf-window-title" id="' + id + '-title">' + inLanguages((t) => fileTitle(file, t)) + '</h2>' +
|
|
65
|
+
'<span class="chip tf-window-chip">' + e(file.path) + '</span></div>';
|
|
66
|
+
const row = (title, body) => '<section class="tf-fact"><h3 class="tf-h3">' + inLanguages((t) => t(title)) + '</h3>' + body + '</section>';
|
|
67
|
+
const body = '<div class="tf-window-body">' +
|
|
68
|
+
(file.reopened === undefined ? '' : backAgain(file)) +
|
|
69
|
+
row('fix.happened.did', '<p class="tf-fact-text">' + inLanguages((t) => t('fix.happened.' + did)) + '</p>') +
|
|
70
|
+
row('fix.window.where', whereList(file)) +
|
|
71
|
+
row('fix.window.todo', '<p class="tf-fact-text">' + inLanguages((t) => t('fix.happened.todo.' + did)) + '</p>') +
|
|
72
|
+
'</div>';
|
|
73
|
+
const foot = popupFoot(inLanguages((t) => t('fix.window.after')), pill({ label: inLanguages((t) => t('app.close')), tone: 'outline', size: 'md', button: true, attributes: CLOSES }) +
|
|
74
|
+
pill({ label: inLanguages((t) => t('fix.' + kind + '.go')), tone: 'primary', size: 'md', href: '#' + fixId(at), attributes: opener(fixId(at)) + ' data-fix-from' }));
|
|
75
|
+
return popup({ id, size: 'small', labelledBy: id + '-title', body: head + body + foot });
|
|
76
|
+
}
|
|
77
|
+
/** T12. */
|
|
78
|
+
function backAgain(file) {
|
|
79
|
+
return callout({
|
|
80
|
+
tone: 'coral',
|
|
81
|
+
body: inLanguages((t, lang) => t('fix.window.back', { day: dayWord(file.reopened, t, lang) })),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/** T15: the conversations it was read in, newest first; six, then the rest behind "Show all". */
|
|
85
|
+
function whereList(file) {
|
|
86
|
+
const shown = file.conversations;
|
|
87
|
+
const gone = file.count - shown.length;
|
|
88
|
+
const rows = shown.map((conversation, at) => {
|
|
89
|
+
const title = conversation.entry.title === undefined ? undefined : e(conversation.entry.title);
|
|
90
|
+
return '<li class="tf-where-row' + (at >= FIRST ? ' tf-more' : '') + '">' +
|
|
91
|
+
'<span class="tf-where-when"><span class="tf-where-day">' +
|
|
92
|
+
inLanguages((t, lang) => dayWord(conversation.when, t, lang, true)) +
|
|
93
|
+
'</span><span class="tf-where-time">' + conversation.when.time + '</span></span>' +
|
|
94
|
+
'<span class="tf-where-ask">' + (title ?? inLanguages((t) => t('fix.window.untitled'))) + '</span>' +
|
|
95
|
+
(conversation.report === undefined
|
|
96
|
+
? '<span class="tf-where-none">' + inLanguages((t) => t('fix.window.noReport')) + '</span>'
|
|
97
|
+
: pill({ label: inLanguages((t) => t('fix.window.see')), tone: 'outline', href: e(conversation.report) })) +
|
|
98
|
+
'</li>';
|
|
99
|
+
}).join('');
|
|
100
|
+
return '<div class="tf-where-block"><ul class="tf-where" data-fix-where>' + rows + '</ul>' +
|
|
101
|
+
(shown.length > FIRST || gone > 0
|
|
102
|
+
? '<div class="tf-where-foot">' +
|
|
103
|
+
(shown.length > FIRST
|
|
104
|
+
? '<button type="button" class="tf-all js-only" data-fix-all>' + inLanguages((t) => t('fix.window.all', { n: shown.length })) + '</button>'
|
|
105
|
+
: '') +
|
|
106
|
+
(gone > 0 ? '<span class="tf-context">' + inLanguages((t) => t('fix.window.gone', { n: gone })) + '</span>' : '') +
|
|
107
|
+
'</div>'
|
|
108
|
+
: '') +
|
|
109
|
+
'</div>';
|
|
110
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { escapeHtml as e } from '../../render/html-report-components.js';
|
|
2
|
+
import { inLanguages, labelAttributes } from '../../render/report-copy.js';
|
|
3
|
+
import { pill } from '../../render/ui/button.js';
|
|
4
|
+
import { callout } from '../../render/ui/callout.js';
|
|
5
|
+
import { foldLine } from '../../render/ui/fold-line.js';
|
|
6
|
+
import { fixId } from '../../render/report-page/to-do-view.js';
|
|
7
|
+
import { opener, opens } from '../../render/ui/popup.js';
|
|
8
|
+
import { tag } from '../../render/ui/tag.js';
|
|
9
|
+
import { taskList } from '../../render/ui/task-list.js';
|
|
10
|
+
import { happenedId } from './file-window.js';
|
|
11
|
+
/** T6: what a file is, in words - the rule that matched it, else "A private file". */
|
|
12
|
+
export function fileTitle(file, t) {
|
|
13
|
+
return t(file.name === undefined ? 'fix.private' : 'set.rule.' + file.name);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The To fix tab (T4-T8): keys to change, then a look to take, each hidden when empty, then the files whose name only
|
|
17
|
+
* was seen, folded. `numbered` gives each file the window number the page gave it.
|
|
18
|
+
*/
|
|
19
|
+
export function toFixList(view, numbered) {
|
|
20
|
+
const empty = view.keys.length === 0 && view.look.length === 0;
|
|
21
|
+
return (view.marksUnreadable ? callout({ tone: 'grey', body: inLanguages((t) => t('fix.marksUnreadable')) }) : '') +
|
|
22
|
+
group('keys', view.keys, numbered) +
|
|
23
|
+
group('look', view.look, numbered) +
|
|
24
|
+
(empty ? '<p class="tf-empty">' + inLanguages((t) => t('fix.empty')) + '</p>' : '') +
|
|
25
|
+
seenFold(view.seen);
|
|
26
|
+
}
|
|
27
|
+
const GROUP_LOOK = {
|
|
28
|
+
keys: { tone: 'coral', go: 'primary' },
|
|
29
|
+
look: { tone: 'amber', go: 'outline' },
|
|
30
|
+
};
|
|
31
|
+
function group(kind, files, numbered) {
|
|
32
|
+
if (files.length === 0)
|
|
33
|
+
return '';
|
|
34
|
+
const look = GROUP_LOOK[kind];
|
|
35
|
+
const tasks = files.map((file) => {
|
|
36
|
+
const at = numbered.get(file) ?? 0;
|
|
37
|
+
return {
|
|
38
|
+
title: inLanguages((t) => fileTitle(file, t)),
|
|
39
|
+
path: file.path,
|
|
40
|
+
done: false,
|
|
41
|
+
// The card as a whole opens Fix it; the pill says so, and is not a second control. "What happened" is one.
|
|
42
|
+
details: pill({ label: inLanguages((t) => t('rp.what')), tone: 'secondary', href: '#' + happenedId(at), attributes: opener(happenedId(at)) }),
|
|
43
|
+
action: pill({ label: inLanguages((t) => t('fix.' + kind + '.go')), tone: look.go }),
|
|
44
|
+
compact: {
|
|
45
|
+
bar: look.tone,
|
|
46
|
+
...(file.reopened === undefined ? {} : { tag: tag(inLanguages((t) => t('fix.back')), 'coral', 'badge', true) }),
|
|
47
|
+
context: inLanguages((t) => t('fix.in', { n: file.count })),
|
|
48
|
+
opens: opens(fixId(at)),
|
|
49
|
+
label: labelAttributes((t) => e(fileTitle(file, t) + ' · ' + file.path)),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
return '<section class="tf-group tf-group-' + look.tone + '">' +
|
|
54
|
+
'<div class="tf-group-head"><span class="tf-dot" aria-hidden="true"></span><h2 class="tf-h2">' +
|
|
55
|
+
inLanguages((t) => t('fix.' + kind)) + '</h2><span class="tf-group-count">' + files.length + '</span></div>' +
|
|
56
|
+
'<p class="tf-group-lead">' + inLanguages((t) => t('fix.' + kind + '.lead')) + '</p>' +
|
|
57
|
+
taskList(undefined, tasks) + '</section>';
|
|
58
|
+
}
|
|
59
|
+
/** T7: what only named a file asks nothing, so it is one folded line, and each file opened under it says so. */
|
|
60
|
+
function seenFold(files) {
|
|
61
|
+
if (files.length === 0)
|
|
62
|
+
return '';
|
|
63
|
+
return foldLine({
|
|
64
|
+
summary: inLanguages((t) => t('fix.seen', { n: files.length })),
|
|
65
|
+
body: '<ul class="tf-seen">' + files.map((file) => '<li class="tf-seen-row"><span class="tf-seen-text"><span class="tf-seen-title">' + inLanguages((t) => fileTitle(file, t)) + '</span>' +
|
|
66
|
+
'<span class="tf-seen-sub"><span class="chip">' + e(file.path) + '</span><span class="tf-context">' +
|
|
67
|
+
inLanguages((t) => t('fix.in', { n: file.count })) + '</span></span></span>' +
|
|
68
|
+
'<span class="tf-seen-label">○ ' + inLanguages((t) => t('fix.seen.label')) + '</span></li>').join('') + '</ul>',
|
|
69
|
+
});
|
|
70
|
+
}
|