@uniqbit/mate-core 0.15.5 → 0.16.0-canary.1
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/.claude-plugin/plugin.json +2 -2
- package/claude-plugin/hooks/hooks.json +3 -6
- package/claude-plugin/hooks/session-guidance.mjs +8 -0
- package/claude-plugin/hooks/ts-loader.mjs +19 -0
- package/package.json +7 -5
- package/src/cli/commands/artifact/artifact.ts +19 -3
- package/src/cli/commands/artifact/finish/command.ts +183 -57
- package/src/cli/commands/artifact/finish/engine.ts +80 -91
- package/src/cli/commands/artifact/finish/finisher.ts +26 -33
- package/src/cli/commands/artifact/finish/git.ts +34 -23
- package/src/cli/commands/artifact/finish/index.ts +9 -3
- package/src/cli/commands/artifact/finish/openspec.ts +225 -97
- package/src/cli/commands/artifact/pending/command.ts +175 -0
- package/src/cli/commands/artifact/pending/discovery.ts +249 -0
- package/src/cli/commands/artifact/pending/index.ts +17 -0
- package/src/cli/commands/cap/index-cmd.ts +9 -1
- package/src/cli/commands/cap/index.ts +2 -6
- package/src/cli/commands/cap/tokensave.ts +4 -4
- package/src/cli/commands/companion/companion.ts +5 -1
- package/src/cli/commands/companion/link.ts +2 -2
- package/src/cli/commands/companion/sync.ts +92 -0
- package/src/cli/commands/doctor.ts +0 -3
- package/src/cli/commands/launch/shared.ts +23 -5
- package/src/cli/commands/report/collector.ts +72 -78
- package/src/cli/commands/report/contract.ts +40 -1
- package/src/cli/commands/report/highlight.ts +27 -0
- package/src/cli/commands/report/index.ts +11 -18
- package/src/cli/commands/report/renderer.ts +199 -2
- package/src/cli/commands/report/types.ts +26 -1
- package/src/cli/commands/shared/companion-selection.ts +107 -10
- package/src/cli/commands/studio/areas.ts +68 -0
- package/src/cli/commands/studio/index.ts +69 -0
- package/src/cli/commands/studio/inventory.ts +55 -0
- package/src/cli/commands/studio/mate-inventory.ts +43 -0
- package/src/cli/commands/studio/openspec-cli.ts +198 -0
- package/src/cli/commands/studio/payload.ts +184 -0
- package/src/cli/commands/studio/routes.ts +2 -0
- package/src/cli/commands/studio/selection.ts +61 -0
- package/src/cli/commands/studio/server.ts +201 -0
- package/src/cli/commands/studio/snapshot.ts +63 -0
- package/src/cli/commands/studio/topology.ts +199 -0
- package/src/cli/commands/studio/views/client.ts +197 -0
- package/src/cli/commands/studio/views/companion-picker.tsx +91 -0
- package/src/cli/commands/studio/views/companion-selector.tsx +90 -0
- package/src/cli/commands/studio/views/dashboard/changes.tsx +107 -0
- package/src/cli/commands/studio/views/dashboard/index.tsx +19 -0
- package/src/cli/commands/studio/views/document.tsx +256 -0
- package/src/cli/commands/studio/views/error.tsx +20 -0
- package/src/cli/commands/studio/views/model.ts +34 -0
- package/src/cli/commands/studio/views/pairings.tsx +38 -0
- package/src/cli/commands/studio/views/skills/index.tsx +87 -0
- package/src/cli/commands/studio/views/specs/index.tsx +101 -0
- package/src/cli/commands/studio/views/styles.ts +389 -0
- package/src/cli/commands/studio/views/warnings.tsx +21 -0
- package/src/cli/commands/studio/views/workflow/index.tsx +21 -0
- package/src/cli/commands/studio/views/workflow/steps.ts +329 -0
- package/src/cli/commands/studio/views/workflow/transcript.tsx +190 -0
- package/src/cli/commands/unwrap.ts +70 -0
- package/src/cli/commands/wrap.ts +164 -0
- package/src/cli/main.ts +68 -19
- package/src/cli/parse-flags.ts +36 -11
- package/src/cli/usage.ts +12 -3
- package/src/framework.ts +1 -7
- package/src/hooks/session-banner.ts +64 -11
- package/src/hooks/session-guidance.ts +40 -0
- package/src/hooks/validate-artifact-path.ts +108 -35
- package/src/lib/fs-utils.ts +9 -0
- package/src/lib/install.ts +33 -0
- package/src/lib/orchestrator/adapters/base.ts +14 -125
- package/src/lib/orchestrator/adapters/claude.ts +0 -11
- package/src/lib/orchestrator/adapters/opencode.ts +2 -32
- package/src/lib/orchestrator/companion-git-sync.ts +94 -84
- package/src/lib/orchestrator/config-store.ts +2 -21
- package/src/lib/orchestrator/editor.ts +12 -22
- package/src/lib/orchestrator/framework-context.ts +17 -6
- package/src/lib/orchestrator/global-config-store.ts +1 -1
- package/src/lib/orchestrator/launcher.ts +97 -7
- package/src/lib/orchestrator/opencode-guidance.ts +4 -56
- package/src/lib/orchestrator/projection-claude-entry.ts +198 -0
- package/src/lib/orchestrator/projection-claude-skills.ts +120 -0
- package/src/lib/orchestrator/projection-companion-link.ts +62 -0
- package/src/lib/orchestrator/projection-entries.ts +377 -0
- package/src/lib/orchestrator/projection-record.ts +56 -0
- package/src/lib/orchestrator/projection-runtime-documents.ts +424 -0
- package/src/lib/orchestrator/projection-types.ts +169 -0
- package/src/lib/orchestrator/repo-local-registry.ts +37 -133
- package/src/lib/orchestrator/repo-local-store.ts +96 -0
- package/src/lib/orchestrator/setup-compatibilities.ts +1 -9
- package/src/lib/orchestrator/types.ts +1 -0
- package/src/lib/orchestrator/working-repo-projection.ts +366 -0
- package/src/lib/orchestrator/workspace-inventory.ts +1 -1
- package/src/lib/package-paths.ts +11 -1
- package/src/lib/public-npm.ts +2 -1
- package/src/lib/update-checker.ts +15 -9
- package/src/opencode/companion-hooks.ts +89 -245
- package/src/opencode/companion-policy.ts +35 -10
- package/src/opencode/index.ts +1 -0
- package/src/opencode/projected-guidance.ts +56 -0
- package/src/opencode/tui.tsx +13 -4
- package/src/playbooks/companion-guidance.ts +32 -116
- package/src/plugins.ts +0 -1
- package/src/runtime/companion-git-state.ts +156 -0
- package/src/runtime/companion-git.ts +203 -0
- package/src/runtime/companion-guidance.ts +222 -0
- package/src/runtime/companion-sync.ts +298 -0
- package/src/runtime/env-names.ts +30 -0
- package/src/runtime/env.ts +67 -35
- package/src/runtime/framework.ts +10 -0
- package/src/runtime/freshness.ts +58 -0
- package/src/runtime/index.ts +104 -0
- package/src/runtime/install.ts +30 -0
- package/src/runtime/policy.ts +66 -0
- package/src/runtime/projected-guidance.ts +45 -0
- package/src/runtime/projection.ts +224 -0
- package/src/runtime/repo-local.ts +64 -0
- package/src/templates/capabilities/openspec-cap/mate-minimal/schema.yaml +56 -0
- package/src/templates/capabilities/openspec-cap/mate-minimal/templates/spec.md +48 -0
- package/src/templates/capabilities/openspec-cap/mate-minimal/templates/tasks.md +22 -0
- package/src/templates/capabilities/openspec-cap/mate-v1/schema.yaml +31 -90
- package/src/templates/capabilities/openspec-cap/mate-v1/templates/design.md +3 -0
- package/src/templates/capabilities/openspec-cap/mate-v1/templates/explore-brief.md +6 -6
- package/src/templates/capabilities/openspec-cap/mate-v1/templates/spec.md +3 -5
- package/src/templates/capabilities/openspec-cap/mate-v1/templates/tasks.md +3 -0
- package/src/templates/capabilities/openspec-cap/openspec-conventions.yaml +30 -0
- package/src/templates/capabilities/react-doctor/claude/hooks/react-doctor.sh +2 -2
- package/src/templates/mate-skills/agents/mate-artifact-publish/SKILL.md +185 -0
- package/src/templates/mate-skills/agents/mate-artifact-publish/references/openspec.md +227 -0
- package/src/templates/mate-skills/agents/mate-domain-modeling/SKILL.md +68 -0
- package/src/templates/mate-skills/agents/mate-domain-modeling/references/ADR-FORMAT.md +9 -0
- package/src/templates/mate-skills/agents/mate-domain-modeling/references/CONTEXT-FORMAT.md +18 -0
- package/src/templates/mate-skills/agents/mate-grill-me/SKILL.md +14 -0
- package/src/templates/mate-skills/agents/mate-grill-with-docs/SKILL.md +29 -0
- package/src/templates/mate-skills/agents/mate-grilling/SKILL.md +49 -0
- package/src/templates/mate-skills/agents/mate-interview-me/SKILL.md +156 -0
- package/src/templates/{capabilities/openspec-cap/mate-skills → mate-skills}/agents/mate-openspec-backfill/SKILL.md +4 -2
- package/src/templates/mate-skills/agents/mate-show-me/SKILL.md +139 -0
- package/src/templates/mate-skills/agents/mate-simplify-code/SKILL.md +503 -0
- package/src/templates/mate-skills/claude/mate-artifact-publish/SKILL.md +185 -0
- package/src/templates/mate-skills/claude/mate-artifact-publish/references/openspec.md +227 -0
- package/src/templates/mate-skills/claude/mate-domain-modeling/SKILL.md +68 -0
- package/src/templates/mate-skills/claude/mate-domain-modeling/references/ADR-FORMAT.md +9 -0
- package/src/templates/mate-skills/claude/mate-domain-modeling/references/CONTEXT-FORMAT.md +18 -0
- package/src/templates/mate-skills/claude/mate-grill-me/SKILL.md +14 -0
- package/src/templates/mate-skills/claude/mate-grill-with-docs/SKILL.md +29 -0
- package/src/templates/mate-skills/claude/mate-grilling/SKILL.md +49 -0
- package/src/templates/mate-skills/claude/mate-interview-me/SKILL.md +156 -0
- package/src/templates/mate-skills/claude/mate-openspec-backfill/SKILL.md +67 -0
- package/src/templates/mate-skills/claude/mate-show-me/SKILL.md +139 -0
- package/src/templates/mate-skills/claude/mate-simplify-code/SKILL.md +503 -0
- package/src/templates/report-assets/README.md +32 -0
- package/src/templates/report-assets/mermaid.LICENSE +21 -0
- package/src/templates/report-assets/mermaid.min.js +4376 -0
- package/src/templates/root/TEMPLATE_CLAUDE.md +1 -9
- package/src/tools/setup/__snapshots__/runtime-surface-golden.test.ts.snap +1476 -197
- package/src/tools/setup/capabilities/graphify.ts +16 -7
- package/src/tools/setup/capabilities/openspec.ts +63 -56
- package/src/tools/setup/capabilities/tokensave.ts +116 -2
- package/src/tools/setup/engine.ts +34 -6
- package/src/tools/setup/mate.ts +42 -13
- package/src/tools/setup/plugin.ts +9 -0
- package/src/tools/setup/plugins/guidance.ts +11 -1
- package/src/tools/setup/providers/claude-format.ts +49 -4
- package/src/tools/setup/providers/claude-plugin-hooks.ts +117 -0
- package/src/tools/setup/providers/claude.ts +55 -220
- package/src/tools/setup/providers/opencode.ts +41 -14
- package/src/tools/setup/runtime-documents.ts +174 -0
- package/src/tools/setup/surface-target.ts +50 -0
- package/src/tools/setup/working-repo-cleanup.ts +33 -26
- package/src/tools/setup/working-repo-local-state.ts +21 -1
- package/src/tools/setup.ts +25 -3
- package/wrappers/bin/graphify +57 -8
- package/wrappers/bin/openspec +50 -3
- package/claude-plugin/hooks/artifact-finish-nudge.mjs +0 -8
- package/src/cli/commands/cap/headroom.ts +0 -52
- package/src/cli/commands/workspace/list.ts +0 -25
- package/src/cli/commands/workspace/materialize.ts +0 -46
- package/src/cli/commands/workspace/workspace.ts +0 -22
- package/src/hooks/artifact-finish-nudge.ts +0 -244
- package/src/lib/orchestrator/headroom/proxy.ts +0 -116
- package/src/lib/orchestrator/workspace-materialize.ts +0 -80
- package/src/templates/capabilities/openspec-cap/mate-skills/agents/mate-artifact-finish/SKILL.md +0 -51
- package/src/templates/capabilities/openspec-cap/mate-skills/agents/mate-artifact-finish/references/openspec.md +0 -134
- package/src/templates/capabilities/openspec-cap/mate-skills/claude/mate-artifact-finish/SKILL.md +0 -58
- package/src/templates/capabilities/openspec-cap/mate-skills/claude/mate-artifact-finish/references/openspec.md +0 -139
- package/src/tools/setup/capabilities/headroom.ts +0 -57
- /package/src/cli/commands/{workspace → companion}/open.ts +0 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mate-simplify-code
|
|
3
|
+
description: Simplifies code for clarity. Use when refactoring code for clarity without changing behavior. Use when code works but is harder to read, maintain, or extend than it should be. Use when reviewing code that has accumulated unnecessary complexity.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Mate Simplify Code
|
|
8
|
+
|
|
9
|
+
> Inspired by [Addy Osmani's code-simplification skill](https://github.com/addyosmani/agent-skills/tree/main/skills/code-simplification) and adapted here as a Mate process-driven skill.
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
Simplify code by reducing complexity while preserving exact behavior. The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. Every simplification must pass a simple test: "Would a new team member understand this faster than the original?"
|
|
14
|
+
|
|
15
|
+
## Mate Workflow
|
|
16
|
+
|
|
17
|
+
- Inspect the requested scope and its callers, callees, and tests before editing. Use the available code-graph tools before broad source scans.
|
|
18
|
+
- Keep the refactor limited to the requested scope; do not make unrelated cleanup changes.
|
|
19
|
+
- Run the relevant tests after each simplification. Do not modify tests merely to make a refactor pass.
|
|
20
|
+
- Format touched files with the project's own formatter — detect it first (see Principle 2); never run a formatter the project has not adopted.
|
|
21
|
+
- Run `mate cap index --tokensave` after code changes.
|
|
22
|
+
- Never commit, push, or create a pull request unless the user explicitly asks.
|
|
23
|
+
|
|
24
|
+
## When to Use
|
|
25
|
+
|
|
26
|
+
- After a feature is working and tests pass, but the implementation feels heavier than it needs to be
|
|
27
|
+
- During code review when readability or complexity issues are flagged
|
|
28
|
+
- When you encounter deeply nested logic, long functions, or unclear names
|
|
29
|
+
- When refactoring code written under time pressure
|
|
30
|
+
- When consolidating related logic scattered across files
|
|
31
|
+
- After merging changes that introduced duplication or inconsistency
|
|
32
|
+
|
|
33
|
+
**When NOT to use:**
|
|
34
|
+
|
|
35
|
+
- Code is already clean and readable — don't simplify for the sake of it
|
|
36
|
+
- You don't understand what the code does yet — comprehend before you simplify
|
|
37
|
+
- The code is performance-critical and the "simpler" version would be measurably slower
|
|
38
|
+
- You're about to rewrite the module entirely — simplifying throwaway code wastes effort
|
|
39
|
+
|
|
40
|
+
## The Five Principles
|
|
41
|
+
|
|
42
|
+
### 1. Preserve Behavior Exactly
|
|
43
|
+
|
|
44
|
+
Don't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical. If you're not sure a simplification preserves behavior, don't make it.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
ASK BEFORE EVERY CHANGE:
|
|
48
|
+
→ Does this produce the same output for every input?
|
|
49
|
+
→ Does this maintain the same error behavior?
|
|
50
|
+
→ Does this preserve the same side effects and ordering?
|
|
51
|
+
→ Do all existing tests still pass without modification?
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 2. Follow Project Conventions
|
|
55
|
+
|
|
56
|
+
Simplification means making code more consistent with the codebase, not imposing external preferences. Before simplifying:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
1. Read CLAUDE.md / project conventions
|
|
60
|
+
2. Study how neighboring code handles similar patterns
|
|
61
|
+
3. Match the project's style for:
|
|
62
|
+
- Import ordering and module system
|
|
63
|
+
- Function declaration style
|
|
64
|
+
- Naming conventions
|
|
65
|
+
- Error handling patterns
|
|
66
|
+
- Type annotation depth
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Simplification that breaks project consistency is not simplification — it's churn.
|
|
70
|
+
|
|
71
|
+
**Formatting is a project convention, not yours.** Never reach for a formatter by habit. Reformatting with a tool the project has not adopted rewrites lines you never touched and buries the refactor in noise.
|
|
72
|
+
|
|
73
|
+
Detect the formatter before formatting anything — first match wins:
|
|
74
|
+
|
|
75
|
+
| Signal in the repo | Formatter to run |
|
|
76
|
+
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
77
|
+
| `format` / `fmt` script in `package.json`, `Makefile`, `justfile`, `Taskfile.yml` | Run that script — it encodes the project's intent and needs no further detection |
|
|
78
|
+
| `biome.json` / `biome.jsonc` | `biome format --write` |
|
|
79
|
+
| `.oxfmtrc.json`, or `oxfmt` in devDependencies | `oxfmt` |
|
|
80
|
+
| `dprint.json` / `.dprint.jsonc` | `dprint fmt` |
|
|
81
|
+
| `.prettierrc*`, `prettier.config.*`, or a `prettier` key in `package.json` | `prettier --write` |
|
|
82
|
+
| `rustfmt.toml`, or any Cargo crate | `cargo fmt` |
|
|
83
|
+
| `[tool.ruff]` in `pyproject.toml` | `ruff format` |
|
|
84
|
+
| `[tool.black]` in `pyproject.toml` | `black` |
|
|
85
|
+
| Go module | `gofmt -w` (or `goimports -w` if already used) |
|
|
86
|
+
| Only `.editorconfig`, or no signal at all | Do not format — match the surrounding style by hand |
|
|
87
|
+
|
|
88
|
+
Rules:
|
|
89
|
+
|
|
90
|
+
- Invoke the project's pinned local binary through its package manager or runner, inferred from the lockfile (`bun`, `pnpm`, `yarn`, `npm`) — never a global install and never an `npx`-downloaded version, which may differ from the one that formatted the committed code.
|
|
91
|
+
- If several formatters are configured, the `format` script decides. If there is no script and the signals conflict, ask which is canonical instead of picking one.
|
|
92
|
+
- Format only the files you changed. A repo-wide format pass is a separate change with its own diff.
|
|
93
|
+
- If the formatter rewrites far more than the lines you touched, its config disagrees with the committed code. Stop, revert the formatting, and report it — do not fold that drift into a simplification change.
|
|
94
|
+
|
|
95
|
+
### 3. Prefer Clarity Over Cleverness
|
|
96
|
+
|
|
97
|
+
Explicit code is better than compact code when the compact version requires a mental pause to parse.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// UNCLEAR: Dense ternary chain
|
|
101
|
+
const label = isNew ? "New" : isUpdated ? "Updated" : isArchived ? "Archived" : "Active";
|
|
102
|
+
|
|
103
|
+
// CLEAR: Readable mapping
|
|
104
|
+
function getStatusLabel(item: Item): string {
|
|
105
|
+
if (item.isNew) return "New";
|
|
106
|
+
if (item.isUpdated) return "Updated";
|
|
107
|
+
if (item.isArchived) return "Archived";
|
|
108
|
+
return "Active";
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// UNCLEAR: Chained reduces with inline logic
|
|
114
|
+
const result = items.reduce(
|
|
115
|
+
(acc, item) => ({
|
|
116
|
+
...acc,
|
|
117
|
+
[item.id]: { ...acc[item.id], count: (acc[item.id]?.count ?? 0) + 1 },
|
|
118
|
+
}),
|
|
119
|
+
{},
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// CLEAR: Named intermediate step
|
|
123
|
+
const countById = new Map<string, number>();
|
|
124
|
+
for (const item of items) {
|
|
125
|
+
countById.set(item.id, (countById.get(item.id) ?? 0) + 1);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 4. Maintain Balance
|
|
130
|
+
|
|
131
|
+
Simplification has a failure mode: over-simplification. Watch for these traps:
|
|
132
|
+
|
|
133
|
+
- **Inlining too aggressively** — removing a helper that gave a concept a name makes the call site harder to read
|
|
134
|
+
- **Combining unrelated logic** — two simple functions merged into one complex function is not simpler
|
|
135
|
+
- **Removing "unnecessary" abstraction** — some abstractions exist for extensibility or testability, not complexity
|
|
136
|
+
- **Optimizing for line count** — fewer lines is not the goal; easier comprehension is
|
|
137
|
+
|
|
138
|
+
### 5. Scope to What Changed
|
|
139
|
+
|
|
140
|
+
Default to simplifying recently modified code. Avoid drive-by refactors of unrelated code unless explicitly asked to broaden scope. Unscoped simplification creates noise in diffs and risks unintended regressions.
|
|
141
|
+
|
|
142
|
+
## The Simplification Process
|
|
143
|
+
|
|
144
|
+
### Step 1: Understand Before Touching (Chesterton's Fence)
|
|
145
|
+
|
|
146
|
+
Before changing or removing anything, understand why it exists. This is Chesterton's Fence: if you see a fence across a road and don't understand why it's there, don't tear it down. First understand the reason, then decide if the reason still applies.
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
BEFORE SIMPLIFYING, ANSWER:
|
|
150
|
+
- What is this code's responsibility?
|
|
151
|
+
- What calls it? What does it call?
|
|
152
|
+
- What are the edge cases and error paths?
|
|
153
|
+
- Are there tests that define the expected behavior?
|
|
154
|
+
- Why might it have been written this way? (Performance? Platform constraint? Historical reason?)
|
|
155
|
+
- Check git blame: what was the original context for this code?
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If you can't answer these, you're not ready to simplify. Read more context first.
|
|
159
|
+
|
|
160
|
+
### Step 2: Identify Simplification Opportunities
|
|
161
|
+
|
|
162
|
+
#### Step 2a: Mechanical pre-scan (required)
|
|
163
|
+
|
|
164
|
+
Run the scan before reading source. Its output **is** the candidate list — a pattern
|
|
165
|
+
nobody looked for is a pattern nobody finds, and prose tables alone are read with a
|
|
166
|
+
bias toward "this file looks fine".
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
PRE-SCAN THE REQUESTED SCOPE:
|
|
170
|
+
1. Code graph, if available — tokensave_module_api (export surface vs. real
|
|
171
|
+
consumers), tokensave_dead_code, tokensave_similar (near-duplicate bodies),
|
|
172
|
+
tokensave_complexity / tokensave_largest (nesting, long functions)
|
|
173
|
+
2. Unused-export detector, if the project already has one configured
|
|
174
|
+
(knip, ts-prune, eslint import-x/no-unused-modules, Python vulture)
|
|
175
|
+
3. Grep for consumers when neither is available — including test files,
|
|
176
|
+
and including the bare symbol name, not just import statements
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Do not skip the pre-scan because the file "looks clean". Judgment applies to the
|
|
180
|
+
candidates it produces, not to whether to produce them. Report candidates you
|
|
181
|
+
deliberately leave alone, with the reason.
|
|
182
|
+
|
|
183
|
+
**A pre-scan hit is a question, not a verdict.** These tools find symbols nothing
|
|
184
|
+
_imports_; they cannot see symbols resolved by name — framework exports, reflective
|
|
185
|
+
lookups, config-referenced files. Every "unused export" candidate must clear the
|
|
186
|
+
**Behavior-preservation rules for the module surface** below before you touch it.
|
|
187
|
+
Read that section before acting on this list, not after.
|
|
188
|
+
|
|
189
|
+
Then scan for these patterns — each one is a concrete signal, not a vague smell:
|
|
190
|
+
|
|
191
|
+
**Structural complexity:**
|
|
192
|
+
|
|
193
|
+
| Pattern | Signal | Simplification |
|
|
194
|
+
| -------------------------- | ---------------------------------- | --------------------------------------------------------- |
|
|
195
|
+
| Deep nesting (3+ levels) | Hard to follow control flow | Extract conditions into guard clauses or helper functions |
|
|
196
|
+
| Long functions (50+ lines) | Multiple responsibilities | Split into focused functions with descriptive names |
|
|
197
|
+
| Nested ternaries | Requires mental stack to parse | Replace with if/else chains, switch, or lookup objects |
|
|
198
|
+
| Boolean parameter flags | `doThing(true, false, true)` | Replace with options objects or separate functions |
|
|
199
|
+
| Repeated conditionals | Same `if` check in multiple places | Extract to a well-named predicate function |
|
|
200
|
+
|
|
201
|
+
**Naming and readability:**
|
|
202
|
+
|
|
203
|
+
| Pattern | Signal | Simplification |
|
|
204
|
+
| -------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------ |
|
|
205
|
+
| Generic names | `data`, `result`, `temp`, `val`, `item` | Rename to describe the content: `userProfile`, `validationErrors` |
|
|
206
|
+
| Abbreviated names | `usr`, `cfg`, `btn`, `evt` | Use full words unless the abbreviation is universal (`id`, `url`, `api`) |
|
|
207
|
+
| Misleading names | Function named `get` that also mutates state | Rename to reflect actual behavior |
|
|
208
|
+
| Comments explaining "what" | `// increment counter` above `count++` | Delete the comment — the code is clear enough |
|
|
209
|
+
| Comments explaining "why" | `// Retry because the API is flaky under load` | Keep these — they carry intent the code can't express |
|
|
210
|
+
|
|
211
|
+
**Redundancy:**
|
|
212
|
+
|
|
213
|
+
| Pattern | Signal | Simplification |
|
|
214
|
+
| ------------------------- | ------------------------------------------------------------ | --------------------------------------------------------- |
|
|
215
|
+
| Duplicated logic | Same 5+ lines in multiple places | Extract to a shared function |
|
|
216
|
+
| Dead code | Unreachable branches, unused variables, commented-out blocks | Remove (after confirming it's truly dead) |
|
|
217
|
+
| Unnecessary abstractions | Wrapper that adds no value | Inline the wrapper, call the underlying function directly |
|
|
218
|
+
| Over-engineered patterns | Factory-for-a-factory, strategy-with-one-strategy | Replace with the simple direct approach |
|
|
219
|
+
| Redundant type assertions | Casting to a type that's already inferred | Remove the assertion |
|
|
220
|
+
|
|
221
|
+
**Module surface:**
|
|
222
|
+
|
|
223
|
+
A module's public API should match what is actually consumed. Surface bloat is
|
|
224
|
+
invisible inside a single file — it only shows up when you compare exports against
|
|
225
|
+
callers, which is what the Step 2a pre-scan does.
|
|
226
|
+
|
|
227
|
+
| Pattern | Signal | Simplification |
|
|
228
|
+
| ----------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------- |
|
|
229
|
+
| Over-exported module | Export has no consumer outside its own file | Drop `export` — keep the symbol, narrow its visibility |
|
|
230
|
+
| Leaked intermediate types | Type exported only to annotate a private helper or internal step | Unexport — but only if it appears in no exported signature |
|
|
231
|
+
| Speculative public API | Export added "for later" with no caller | Unexport first; delete only per the dead-code rule above |
|
|
232
|
+
| Single-consumer bag-of-things | Many exports, exactly one importer | **Propose only** — API reshape, not a visibility change (see below) |
|
|
233
|
+
| Re-export passthrough | Barrel file that only forwards a single symbol | **Propose only** — changes module resolution repo-wide (see below) |
|
|
234
|
+
|
|
235
|
+
Narrowing visibility is not inlining — the named helper survives, so this does not
|
|
236
|
+
conflict with the over-simplification traps in Principle 4. Only inline a helper when
|
|
237
|
+
the name itself carries no meaning at the call site.
|
|
238
|
+
|
|
239
|
+
#### Behavior-preservation rules for the module surface
|
|
240
|
+
|
|
241
|
+
Principle 1 governs this table without exception. Visibility is not behavior — until
|
|
242
|
+
something resolves the symbol by name rather than by import. Then it is.
|
|
243
|
+
|
|
244
|
+
**Unexport, don't delete.** In a type-checked project, removing `export` is verified by
|
|
245
|
+
the compiler: any importer becomes a compile error, so a mistake fails loudly and
|
|
246
|
+
immediately. Deleting the symbol has no such net. Narrow visibility as its own step;
|
|
247
|
+
treat deletion as a separate decision under the dead-code rule, not as part of the
|
|
248
|
+
same edit.
|
|
249
|
+
|
|
250
|
+
**That safety net requires a type checker that actually runs over the file.** Plain
|
|
251
|
+
JavaScript, TypeScript with `checkJs` off, or a project with no `tsc --noEmit` gate
|
|
252
|
+
gets no compile error — a broken import fails at runtime instead, possibly only on one
|
|
253
|
+
code path. In an unchecked project, do not unexport on pre-scan evidence alone: confirm
|
|
254
|
+
each consumer by grep first, or leave the export and report it.
|
|
255
|
+
|
|
256
|
+
**A test is a consumer.** If the only importer is a test file, the export is load-
|
|
257
|
+
bearing — unexporting it breaks the test, and Principle 1 forbids editing tests to make
|
|
258
|
+
a refactor pass. Leave it exported. "No production consumer" is not "no consumer";
|
|
259
|
+
report it as a possible test-only seam instead of acting on it.
|
|
260
|
+
|
|
261
|
+
**A type used in an exported signature stays exported.** If an exported function takes
|
|
262
|
+
or returns the type, consumers need to name it — unexporting breaks call sites and
|
|
263
|
+
declaration emit even though nothing imports the type directly today. Only unexport a
|
|
264
|
+
type that appears exclusively in module-private positions.
|
|
265
|
+
|
|
266
|
+
**Never touch an export the framework resolves by name.** These have no importer
|
|
267
|
+
anywhere by design, so "no consumer found" is meaningless for them — the pre-scan and
|
|
268
|
+
every unused-export detector will report them as dead, and they are not:
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
FRAMEWORK-RESOLVED — OUT OF SCOPE, DO NOT UNEXPORT OR RENAME:
|
|
272
|
+
- Next.js app router: default, metadata, generateMetadata, generateStaticParams,
|
|
273
|
+
revalidate, dynamic, runtime, viewport, route handlers (GET/POST/...),
|
|
274
|
+
middleware, error/loading/not-found boundaries
|
|
275
|
+
- Next.js pages router: default, getServerSideProps, getStaticProps, getStaticPaths
|
|
276
|
+
- Test and story files: Storybook CSF (default + named story exports), fixtures,
|
|
277
|
+
setup files referenced by config rather than imported
|
|
278
|
+
- Package entry points: anything reachable from package.json exports/main/types,
|
|
279
|
+
or from a documented public API
|
|
280
|
+
- Config-referenced modules: paths named in tsconfig, bundler, or tool config
|
|
281
|
+
- Reflective resolution: dynamic import() with a computed specifier, glob imports
|
|
282
|
+
(import.meta.glob, require.context), DI containers, decorators, plugin registries
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**Propose-only rows are not yours to apply.** Collapsing a multi-export module to one
|
|
286
|
+
entry point, or deleting a barrel, is an API reshape: it rewrites call sites in files
|
|
287
|
+
outside the requested scope, changes module resolution for deep importers, and is a
|
|
288
|
+
design decision rather than a behavior-preserving edit. Both collide with Principle 5.
|
|
289
|
+
Describe the change and the affected files, then stop and let the user decide — the
|
|
290
|
+
same treatment the prop-drilling case gets under React guidance.
|
|
291
|
+
|
|
292
|
+
**When the pre-scan flags a symbol you cannot prove is unreferenced, leave it and say
|
|
293
|
+
so.** An export you were unsure about and kept costs a line of explanation. An export
|
|
294
|
+
you removed on a guess costs a production incident. Unverifiable candidates are
|
|
295
|
+
reported, not acted on.
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
BEFORE REMOVING ANY export, ALL MUST HOLD:
|
|
299
|
+
[ ] Not framework-resolved (checked against the list above)
|
|
300
|
+
[ ] Not reachable from a package entry point or documented API
|
|
301
|
+
[ ] No importer anywhere — including tests, stories, and config
|
|
302
|
+
[ ] If a type: appears in no exported signature
|
|
303
|
+
[ ] A type checker covers this file and will run before the change is accepted
|
|
304
|
+
[ ] The symbol name greps clean outside its own file
|
|
305
|
+
Any box unchecked → report the candidate, do not touch it.
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Step 3: Apply Changes Incrementally
|
|
309
|
+
|
|
310
|
+
Make one simplification at a time. Run tests after each change. **Submit refactoring changes separately from feature or bug fix changes.** A PR that refactors and adds a feature is two PRs — split them.
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
FOR EACH SIMPLIFICATION:
|
|
314
|
+
1. Make the change
|
|
315
|
+
2. Run the type checker / compiler, then the test suite
|
|
316
|
+
(visibility changes surface as compile errors, not test failures — a green
|
|
317
|
+
test run alone does not prove an unexport was safe)
|
|
318
|
+
3. If both pass → continue to the next simplification; commit only if the user explicitly asks
|
|
319
|
+
4. If either fails → revert and reconsider
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Avoid batching multiple simplifications into a single untested change. If something breaks, you need to know which simplification caused it.
|
|
323
|
+
|
|
324
|
+
**The Rule of 500:** If a refactoring would touch more than 500 lines, invest in automation (codemods or AST transforms) rather than making the changes by hand. Manual edits at that scale are error-prone and exhausting to review.
|
|
325
|
+
|
|
326
|
+
### Step 4: Verify the Result
|
|
327
|
+
|
|
328
|
+
Run the project's formatter (detected in Principle 2) over the files you touched, then re-run the type checker and test suite — formatting must never be the last unverified step.
|
|
329
|
+
|
|
330
|
+
Then step back and evaluate the whole:
|
|
331
|
+
|
|
332
|
+
```
|
|
333
|
+
COMPARE BEFORE AND AFTER:
|
|
334
|
+
- Is the simplified version genuinely easier to understand?
|
|
335
|
+
- Did you introduce any new patterns inconsistent with the codebase?
|
|
336
|
+
- Is the diff clean and reviewable?
|
|
337
|
+
- Would a teammate approve this change?
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
If the "simplified" version is harder to understand or review, revert. Not every simplification attempt succeeds.
|
|
341
|
+
|
|
342
|
+
## Language-Specific Guidance
|
|
343
|
+
|
|
344
|
+
### TypeScript / JavaScript
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
// SIMPLIFY: Unnecessary async wrapper
|
|
348
|
+
// Before
|
|
349
|
+
async function getUser(id: string): Promise<User> {
|
|
350
|
+
return await userService.findById(id);
|
|
351
|
+
}
|
|
352
|
+
// After
|
|
353
|
+
function getUser(id: string): Promise<User> {
|
|
354
|
+
return userService.findById(id);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// SIMPLIFY: Verbose conditional assignment
|
|
358
|
+
// Before
|
|
359
|
+
let displayName: string;
|
|
360
|
+
if (user.nickname) {
|
|
361
|
+
displayName = user.nickname;
|
|
362
|
+
} else {
|
|
363
|
+
displayName = user.fullName;
|
|
364
|
+
}
|
|
365
|
+
// After
|
|
366
|
+
const displayName = user.nickname || user.fullName;
|
|
367
|
+
|
|
368
|
+
// SIMPLIFY: Manual array building
|
|
369
|
+
// Before
|
|
370
|
+
const activeUsers: User[] = [];
|
|
371
|
+
for (const user of users) {
|
|
372
|
+
if (user.isActive) {
|
|
373
|
+
activeUsers.push(user);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// After
|
|
377
|
+
const activeUsers = users.filter((user) => user.isActive);
|
|
378
|
+
|
|
379
|
+
// SIMPLIFY: Redundant boolean return
|
|
380
|
+
// Before
|
|
381
|
+
function isValid(input: string): boolean {
|
|
382
|
+
if (input.length > 0 && input.length < 100) {
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
// After
|
|
388
|
+
function isValid(input: string): boolean {
|
|
389
|
+
return input.length > 0 && input.length < 100;
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Python
|
|
394
|
+
|
|
395
|
+
```python
|
|
396
|
+
# SIMPLIFY: Verbose dictionary building
|
|
397
|
+
# Before
|
|
398
|
+
result = {}
|
|
399
|
+
for item in items:
|
|
400
|
+
result[item.id] = item.name
|
|
401
|
+
# After
|
|
402
|
+
result = {item.id: item.name for item in items}
|
|
403
|
+
|
|
404
|
+
# SIMPLIFY: Nested conditionals with early return
|
|
405
|
+
# Before
|
|
406
|
+
def process(data):
|
|
407
|
+
if data is not None:
|
|
408
|
+
if data.is_valid():
|
|
409
|
+
if data.has_permission():
|
|
410
|
+
return do_work(data)
|
|
411
|
+
else:
|
|
412
|
+
raise PermissionError("No permission")
|
|
413
|
+
else:
|
|
414
|
+
raise ValueError("Invalid data")
|
|
415
|
+
else:
|
|
416
|
+
raise TypeError("Data is None")
|
|
417
|
+
# After
|
|
418
|
+
def process(data):
|
|
419
|
+
if data is None:
|
|
420
|
+
raise TypeError("Data is None")
|
|
421
|
+
if not data.is_valid():
|
|
422
|
+
raise ValueError("Invalid data")
|
|
423
|
+
if not data.has_permission():
|
|
424
|
+
raise PermissionError("No permission")
|
|
425
|
+
return do_work(data)
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### React / JSX
|
|
429
|
+
|
|
430
|
+
```tsx
|
|
431
|
+
// SIMPLIFY: Verbose conditional rendering
|
|
432
|
+
// Before
|
|
433
|
+
function UserBadge({ user }: Props) {
|
|
434
|
+
if (user.isAdmin) {
|
|
435
|
+
return <Badge variant="admin">Admin</Badge>;
|
|
436
|
+
} else {
|
|
437
|
+
return <Badge variant="default">User</Badge>;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
// After
|
|
441
|
+
function UserBadge({ user }: Props) {
|
|
442
|
+
const variant = user.isAdmin ? "admin" : "default";
|
|
443
|
+
const label = user.isAdmin ? "Admin" : "User";
|
|
444
|
+
return <Badge variant={variant}>{label}</Badge>;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// SIMPLIFY: Prop drilling through intermediate components
|
|
448
|
+
// Before — consider whether context or composition solves this better.
|
|
449
|
+
// This is a judgment call — flag it, don't auto-refactor.
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## Common Rationalizations
|
|
453
|
+
|
|
454
|
+
| Rationalization | Reality |
|
|
455
|
+
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
456
|
+
| "It's working, no need to touch it" | Working code that's hard to read will be hard to fix when it breaks. Simplifying now saves time on every future change. |
|
|
457
|
+
| "Fewer lines is always simpler" | A 1-line nested ternary is not simpler than a 5-line if/else. Simplicity is about comprehension speed, not line count. |
|
|
458
|
+
| "I'll just quickly simplify this unrelated code too" | Unscoped simplification creates noisy diffs and risks regressions in code you didn't intend to change. Stay focused. |
|
|
459
|
+
| "The types make it self-documenting" | Types document structure, not intent. A well-named function explains _why_ better than a type signature explains _what_. |
|
|
460
|
+
| "This abstraction might be useful later" | Don't preserve speculative abstractions. If it's not used now, it's complexity without value. Remove it and re-add when needed. |
|
|
461
|
+
| "The original author must have had a reason" | Maybe. Check git blame — apply Chesterton's Fence. But accumulated complexity often has no reason; it's just the residue of iteration under pressure. |
|
|
462
|
+
| "I'll refactor while adding this feature" | Separate refactoring from feature work. Mixed changes are harder to review, revert, and understand in history. |
|
|
463
|
+
|
|
464
|
+
## Red Flags
|
|
465
|
+
|
|
466
|
+
- Simplification that requires modifying tests to pass (you likely changed behavior)
|
|
467
|
+
- "Simplified" code that is longer and harder to follow than the original
|
|
468
|
+
- Renaming things to match your preferences rather than project conventions
|
|
469
|
+
- Removing error handling because "it makes the code cleaner"
|
|
470
|
+
- Simplifying code you don't fully understand
|
|
471
|
+
- Batching many simplifications into one large, hard-to-review commit
|
|
472
|
+
- Refactoring code outside the scope of the current task without being asked
|
|
473
|
+
- Deleting an export because a tool reported it unused, without checking whether the
|
|
474
|
+
framework resolves it by name (`page.tsx`, `route.ts`, stories, config-referenced files)
|
|
475
|
+
- Acting on a pre-scan candidate you could not verify — report it instead
|
|
476
|
+
- Treating a green test run as proof a visibility change was safe without a type check
|
|
477
|
+
- Unexporting a symbol whose only importer is a test, then editing the test to match
|
|
478
|
+
- Applying a propose-only row (module collapse, barrel deletion) without user sign-off
|
|
479
|
+
- Trusting "the compiler would catch it" in a project the type checker does not cover
|
|
480
|
+
|
|
481
|
+
## Verification
|
|
482
|
+
|
|
483
|
+
After completing a simplification pass:
|
|
484
|
+
|
|
485
|
+
- [ ] All existing tests pass without modification
|
|
486
|
+
- [ ] Build succeeds with no new warnings
|
|
487
|
+
- [ ] The project's own formatter was detected and run on the touched files — no formatter the project has not adopted was used
|
|
488
|
+
- [ ] Formatting touched only the changed files (no repo-wide reformat mixed in)
|
|
489
|
+
- [ ] Linter passes (no style regressions)
|
|
490
|
+
- [ ] Each simplification is a reviewable, incremental change
|
|
491
|
+
- [ ] The diff is clean — no unrelated changes mixed in
|
|
492
|
+
- [ ] Simplified code follows project conventions (checked against CLAUDE.md or equivalent)
|
|
493
|
+
- [ ] No error handling was removed or weakened
|
|
494
|
+
- [ ] No dead code was left behind (unused imports, unreachable branches)
|
|
495
|
+
- [ ] The Step 2a pre-scan was run, and every candidate is either fixed or explained
|
|
496
|
+
- [ ] Export surface matches actual consumers — nothing exported without a caller outside its file
|
|
497
|
+
- [ ] Type checker passes — no unexport broke an importer
|
|
498
|
+
- [ ] No framework-resolved export was unexported, renamed, or deleted
|
|
499
|
+
- [ ] Every removed `export` cleared all boxes of the pre-removal checklist
|
|
500
|
+
- [ ] No test was edited to accommodate a visibility change
|
|
501
|
+
- [ ] Propose-only findings were reported, not applied
|
|
502
|
+
- [ ] Behavior is bit-for-bit identical: same inputs, outputs, side effects, error paths
|
|
503
|
+
- [ ] A teammate or review agent would approve the change as a net improvement
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Report assets
|
|
2
|
+
|
|
3
|
+
Vendored browser assets inlined into `mate report` HTML output. Nothing here is
|
|
4
|
+
imported as a module or linted, formatted, or typechecked — these files are read
|
|
5
|
+
as strings at render time.
|
|
6
|
+
|
|
7
|
+
## `mermaid.min.js`
|
|
8
|
+
|
|
9
|
+
| | |
|
|
10
|
+
| -------- | ------------------------------------------------------------------------ |
|
|
11
|
+
| Upstream | [`mermaid`](https://www.npmjs.com/package/mermaid) `dist/mermaid.min.js` |
|
|
12
|
+
| Version | `12.0.0` |
|
|
13
|
+
| License | MIT — see `mermaid.LICENSE` |
|
|
14
|
+
| Form | esbuild IIFE, self-contained, zero dynamic `import()` calls |
|
|
15
|
+
| Size | 5.58 MB raw |
|
|
16
|
+
|
|
17
|
+
The IIFE build is vendored rather than installed because `@uniqbit/mate-core`
|
|
18
|
+
publishes raw `src/` with no build step, and only mermaid's ESM build lazily
|
|
19
|
+
loads per-diagram chunks. It is inlined into a report document only when that
|
|
20
|
+
report carries a mermaid payload.
|
|
21
|
+
|
|
22
|
+
### Bumping
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm pack mermaid@<version>
|
|
26
|
+
tar -xzf mermaid-<version>.tgz package/dist/mermaid.min.js package/LICENSE
|
|
27
|
+
cp package/dist/mermaid.min.js packages/mate-core/src/templates/report-assets/mermaid.min.js
|
|
28
|
+
cp package/LICENSE packages/mate-core/src/templates/report-assets/mermaid.LICENSE
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Update the version above, confirm `grep -c 'import('` on the bundle stays `0`,
|
|
32
|
+
then re-run the report renderer tests.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014 - 2022 Knut Sveidqvist
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|