@aikdna/kdna-cli 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -101
- package/SECURITY.md +1 -1
- package/package.json +3 -2
- package/skills/kdna-loader/SKILL.md +18 -16
- package/src/agent.js +152 -57
- package/src/cli.js +17 -11
- package/src/cmds/_common.js +9 -3
- package/src/cmds/badge.js +8 -3
- package/src/cmds/changelog.js +31 -11
- package/src/cmds/cluster.js +67 -40
- package/src/cmds/domain.js +37 -27
- package/src/cmds/explain.js +1 -4
- package/src/cmds/governance.js +111 -42
- package/src/cmds/legacy.js +1 -2
- package/src/cmds/license.js +16 -8
- package/src/cmds/quality.js +9 -2
- package/src/cmds/studio.js +95 -42
- package/src/cmds/test.js +5 -2
- package/src/compare.js +15 -2
- package/src/diff.js +27 -11
- package/src/identity.js +9 -7
- package/src/install.js +17 -7
- package/src/package-store.js +4 -1
- package/src/paths.js +2 -2
- package/src/publish.js +90 -42
- package/src/registry.js +13 -8
- package/src/verify.js +61 -17
- package/src/version.js +15 -7
- package/templates/minimal-domain/kdna.json +7 -7
- package/templates/standard-domain/README.md +10 -10
- package/templates/standard-domain/kdna.json +6 -3
- package/validators/kdna-lint.js +45 -11
package/README.md
CHANGED
|
@@ -36,112 +36,112 @@ kdna doctor --agents
|
|
|
36
36
|
|
|
37
37
|
## The 6 Commands You Actually Need
|
|
38
38
|
|
|
39
|
-
| Command
|
|
40
|
-
|
|
41
|
-
| `kdna setup`
|
|
42
|
-
| `kdna install <domain>`
|
|
43
|
-
| `kdna list`
|
|
44
|
-
| `kdna verify <domain>`
|
|
45
|
-
| `kdna compare <domain> --input "..."` | Compare with/without KDNA judgment
|
|
46
|
-
| `kdna doctor --agents`
|
|
39
|
+
| Command | What it does |
|
|
40
|
+
| ------------------------------------- | -------------------------------------------------- |
|
|
41
|
+
| `kdna setup` | Initialize ~/.kdna, install the agent skill loader |
|
|
42
|
+
| `kdna install <domain>` | Install a domain from the registry |
|
|
43
|
+
| `kdna list` | Show installed domains with quality info |
|
|
44
|
+
| `kdna verify <domain>` | 3-layer check: structure + trust + judgment |
|
|
45
|
+
| `kdna compare <domain> --input "..."` | Compare with/without KDNA judgment |
|
|
46
|
+
| `kdna doctor --agents` | Check agent integration health |
|
|
47
47
|
|
|
48
48
|
## All Commands by Role
|
|
49
49
|
|
|
50
50
|
### Domain Authoring
|
|
51
51
|
|
|
52
|
-
| Command
|
|
53
|
-
|
|
54
|
-
| `kdna init <name>`
|
|
55
|
-
| `kdna dev validate <path>`
|
|
56
|
-
| `kdna dev pack <path>`
|
|
57
|
-
| `kdna dev unpack <file>`
|
|
58
|
-
| `kdna dev inspect <path>`
|
|
59
|
-
| `kdna dev card <path>`
|
|
60
|
-
| `kdna inspect <file.kdna>`
|
|
61
|
-
| `kdna publish <path>`
|
|
62
|
-
| `kdna publish --check <path>`
|
|
63
|
-
| `kdna version bump <level> [path]` | Beta
|
|
52
|
+
| Command | Status | Description |
|
|
53
|
+
| ---------------------------------- | ------------ | ----------------------------------------------- |
|
|
54
|
+
| `kdna init <name>` | Beta | Scaffold a new domain from template |
|
|
55
|
+
| `kdna dev validate <path>` | Stable | Validate a non-canonical dev source directory |
|
|
56
|
+
| `kdna dev pack <path>` | Beta | Build a dev source directory into a .kdna asset |
|
|
57
|
+
| `kdna dev unpack <file>` | Beta | Unpack .kdna into a dev source directory |
|
|
58
|
+
| `kdna dev inspect <path>` | Beta | Inspect a non-canonical dev source directory |
|
|
59
|
+
| `kdna dev card <path>` | Beta | Display KDNA Card from a dev source directory |
|
|
60
|
+
| `kdna inspect <file.kdna>` | Beta | Inspect a .kdna asset |
|
|
61
|
+
| `kdna publish <path>` | Experimental | Pack + sign + publish to registry |
|
|
62
|
+
| `kdna publish --check <path>` | Experimental | Quality gate check only |
|
|
63
|
+
| `kdna version bump <level> [path]` | Beta | Bump domain version |
|
|
64
64
|
|
|
65
65
|
### Agent Runtime
|
|
66
66
|
|
|
67
|
-
| Command
|
|
68
|
-
|
|
69
|
-
| `kdna available [--json]`
|
|
70
|
-
| `kdna match "<task>" [--json]`
|
|
71
|
-
| `kdna load <name\|file.kdna> [--as=prompt\|json\|raw]` | Beta
|
|
72
|
-
| `kdna postvalidate <name> --output <file>`
|
|
67
|
+
| Command | Status | Description |
|
|
68
|
+
| ------------------------------------------------------ | ------ | --------------------------------------- |
|
|
69
|
+
| `kdna available [--json]` | Beta | List installed domains with v2.1 fields |
|
|
70
|
+
| `kdna match "<task>" [--json]` | Beta | Signal matching — find relevant domains |
|
|
71
|
+
| `kdna load <name\|file.kdna> [--as=prompt\|json\|raw]` | Beta | Emit asset in agent-ready format |
|
|
72
|
+
| `kdna postvalidate <name> --output <file>` | Beta | Post-generation judgment check |
|
|
73
73
|
|
|
74
74
|
### Testing & Verification
|
|
75
75
|
|
|
76
|
-
| Command
|
|
77
|
-
|
|
78
|
-
| `kdna verify <name\|file.kdna>`
|
|
79
|
-
| `kdna compare <name\|file.kdna> --input "..."`
|
|
80
|
-
| `kdna compare <name\|file.kdna> --input "..." --report-md`
|
|
81
|
-
| `kdna compare <name\|file.kdna> --input "..." --report-json` | Beta
|
|
82
|
-
| `kdna diff <name>@<v1> <name>@<v2>`
|
|
76
|
+
| Command | Status | Description |
|
|
77
|
+
| ------------------------------------------------------------ | ------ | ------------------------------------- |
|
|
78
|
+
| `kdna verify <name\|file.kdna>` | Beta | 3-layer: structure + trust + judgment |
|
|
79
|
+
| `kdna compare <name\|file.kdna> --input "..."` | Beta | With/without KDNA reasoning diff |
|
|
80
|
+
| `kdna compare <name\|file.kdna> --input "..." --report-md` | Beta | Markdown report with scoring |
|
|
81
|
+
| `kdna compare <name\|file.kdna> --input "..." --report-json` | Beta | JSON report with scoring |
|
|
82
|
+
| `kdna diff <name>@<v1> <name>@<v2>` | Beta | Judgment-level diff between versions |
|
|
83
83
|
|
|
84
84
|
### Diagnostics & Trace
|
|
85
85
|
|
|
86
|
-
| Command
|
|
87
|
-
|
|
88
|
-
| `kdna doctor`
|
|
89
|
-
| `kdna doctor --agents`
|
|
90
|
-
| `kdna doctor --json`
|
|
91
|
-
| `kdna trace`
|
|
92
|
-
| `kdna trace --json`
|
|
93
|
-
| `kdna trace --export <file>`
|
|
94
|
-
| `kdna trace --since 7d\|30d\|90d` | Experimental | Filter by time range
|
|
95
|
-
| `kdna history`
|
|
96
|
-
| `kdna history --stats`
|
|
97
|
-
| `kdna history --domain <name>`
|
|
86
|
+
| Command | Status | Description |
|
|
87
|
+
| --------------------------------- | ------------ | ------------------------------------------------------------- |
|
|
88
|
+
| `kdna doctor` | Beta | System health check |
|
|
89
|
+
| `kdna doctor --agents` | Beta | Agent integration check (Codex/Claude/OpenCode/Cursor/Gemini) |
|
|
90
|
+
| `kdna doctor --json` | Beta | Machine-readable health report |
|
|
91
|
+
| `kdna trace` | Experimental | View recent load/postvalidate traces |
|
|
92
|
+
| `kdna trace --json` | Experimental | Machine-readable trace output |
|
|
93
|
+
| `kdna trace --export <file>` | Experimental | Export traces for audit |
|
|
94
|
+
| `kdna trace --since 7d\|30d\|90d` | Experimental | Filter by time range |
|
|
95
|
+
| `kdna history` | Experimental | Recent domain usage (last 20) |
|
|
96
|
+
| `kdna history --stats` | Experimental | Aggregate by domain and agent |
|
|
97
|
+
| `kdna history --domain <name>` | Experimental | Filter by domain |
|
|
98
98
|
|
|
99
99
|
### License & Authorization
|
|
100
100
|
|
|
101
|
-
| Command
|
|
102
|
-
|
|
103
|
-
| `kdna license generate <domain> --to <email>`
|
|
104
|
-
| `kdna license install <license.json>`
|
|
105
|
-
| `kdna license activate <domain> --key <key> --server <url>` | Experimental | Activate a license from entitlement source
|
|
106
|
-
| `kdna license sync [domain] [--server <url>]`
|
|
107
|
-
| `kdna license verify <license.json>`
|
|
108
|
-
| `kdna license bind <license.json>`
|
|
109
|
-
| `kdna license show <license.json>`
|
|
110
|
-
| `kdna license status [domain] [--json]`
|
|
101
|
+
| Command | Status | Description |
|
|
102
|
+
| ----------------------------------------------------------- | ------------ | -------------------------------------------------------------- |
|
|
103
|
+
| `kdna license generate <domain> --to <email>` | Experimental | Generate signed license |
|
|
104
|
+
| `kdna license install <license.json>` | Experimental | Register license for auto-decrypt |
|
|
105
|
+
| `kdna license activate <domain> --key <key> --server <url>` | Experimental | Activate a license from entitlement source |
|
|
106
|
+
| `kdna license sync [domain] [--server <url>]` | Experimental | Refresh entitlement and revocation status |
|
|
107
|
+
| `kdna license verify <license.json>` | Experimental | Verify license signature and validity |
|
|
108
|
+
| `kdna license bind <license.json>` | Experimental | Bind license to this machine |
|
|
109
|
+
| `kdna license show <license.json>` | Experimental | Display license details |
|
|
110
|
+
| `kdna license status [domain] [--json]` | Experimental | Show installed license activation status without exposing keys |
|
|
111
111
|
|
|
112
112
|
### Cluster Composition
|
|
113
113
|
|
|
114
|
-
| Command
|
|
115
|
-
|
|
114
|
+
| Command | Status | Description |
|
|
115
|
+
| -------------------------- | ------- | ------------------------- |
|
|
116
116
|
| `kdna cluster lint <path>` | Planned | Validate cluster manifest |
|
|
117
117
|
|
|
118
118
|
### Registry & Distribution
|
|
119
119
|
|
|
120
|
-
| Command
|
|
121
|
-
|
|
122
|
-
| `kdna install <name>`
|
|
123
|
-
| `kdna install file.kdna`
|
|
124
|
-
| `kdna remove <name>`
|
|
125
|
-
| `kdna update <name>`
|
|
126
|
-
| `kdna info <name>`
|
|
127
|
-
| `kdna list [--available]` | Beta
|
|
128
|
-
| `kdna search <keyword>`
|
|
129
|
-
| `kdna registry refresh`
|
|
120
|
+
| Command | Status | Description |
|
|
121
|
+
| ------------------------- | ------ | ------------------------------------- |
|
|
122
|
+
| `kdna install <name>` | Beta | Install domain from registry |
|
|
123
|
+
| `kdna install file.kdna` | Beta | Install from local .kdna asset |
|
|
124
|
+
| `kdna remove <name>` | Beta | Uninstall a domain |
|
|
125
|
+
| `kdna update <name>` | Beta | Update installed domain |
|
|
126
|
+
| `kdna info <name>` | Beta | Show domain metadata and trust status |
|
|
127
|
+
| `kdna list [--available]` | Beta | List installed or available domains |
|
|
128
|
+
| `kdna search <keyword>` | Beta | Search registry |
|
|
129
|
+
| `kdna registry refresh` | Beta | Refresh registry cache |
|
|
130
130
|
|
|
131
131
|
### Identity & Signing
|
|
132
132
|
|
|
133
|
-
| Command
|
|
134
|
-
|
|
135
|
-
| `kdna identity init`
|
|
136
|
-
| `kdna identity show`
|
|
137
|
-
| `kdna identity export [--out]` | Experimental | Backup private key (encrypted)
|
|
138
|
-
| `kdna identity import <file>`
|
|
133
|
+
| Command | Status | Description |
|
|
134
|
+
| ------------------------------ | ------------ | ------------------------------- |
|
|
135
|
+
| `kdna identity init` | Experimental | Generate Ed25519 signing key |
|
|
136
|
+
| `kdna identity show` | Experimental | Display public key and buyer ID |
|
|
137
|
+
| `kdna identity export [--out]` | Experimental | Backup private key (encrypted) |
|
|
138
|
+
| `kdna identity import <file>` | Experimental | Restore identity from backup |
|
|
139
139
|
|
|
140
140
|
### Setup
|
|
141
141
|
|
|
142
|
-
| Command
|
|
143
|
-
|
|
144
|
-
| `kdna setup` | Beta
|
|
142
|
+
| Command | Status | Description |
|
|
143
|
+
| ------------ | ------ | ------------------------------------------ |
|
|
144
|
+
| `kdna setup` | Beta | One-command setup: CLI + skill + data root |
|
|
145
145
|
|
|
146
146
|
---
|
|
147
147
|
|
|
@@ -205,25 +205,25 @@ KDNA 同时支持开放判断资产和授权/私有判断资产。开放资产
|
|
|
205
205
|
|
|
206
206
|
## Environment Variables
|
|
207
207
|
|
|
208
|
-
| Variable
|
|
209
|
-
|
|
210
|
-
| `KDNA_AGENT`
|
|
211
|
-
| `KDNA_REGISTRY_URL` | Override canonical registry URL
|
|
212
|
-
| `KDNA_IDENTITY_DIR` | Override identity key directory
|
|
208
|
+
| Variable | Purpose |
|
|
209
|
+
| ------------------- | --------------------------------------------------------------------------- |
|
|
210
|
+
| `KDNA_AGENT` | Override agent name in trace logs (e.g. `claude_code`, `codex`, `opencode`) |
|
|
211
|
+
| `KDNA_REGISTRY_URL` | Override canonical registry URL |
|
|
212
|
+
| `KDNA_IDENTITY_DIR` | Override identity key directory |
|
|
213
213
|
|
|
214
214
|
## Exit Codes
|
|
215
215
|
|
|
216
|
-
| Code | Name
|
|
217
|
-
|
|
218
|
-
| 0
|
|
219
|
-
| 1
|
|
220
|
-
| 2
|
|
221
|
-
| 3
|
|
222
|
-
| 4
|
|
223
|
-
| 5
|
|
224
|
-
| 6
|
|
225
|
-
| 7
|
|
226
|
-
| 8
|
|
216
|
+
| Code | Name | Meaning |
|
|
217
|
+
| ---- | ------------------------- | -------------------------------------------------- |
|
|
218
|
+
| 0 | `OK` | Success |
|
|
219
|
+
| 1 | `VALIDATION_FAILED` | Structure or schema validation failed |
|
|
220
|
+
| 2 | `INPUT_ERROR` | Invalid input, missing argument, not found |
|
|
221
|
+
| 3 | `TRUST_FAILED` | Signature or trust verification failed |
|
|
222
|
+
| 4 | `JUDGMENT_QUALITY_FAILED` | Judgment governance fields missing or insufficient |
|
|
223
|
+
| 5 | `REGISTRY_ERROR` | Registry lookup or network error |
|
|
224
|
+
| 6 | `PROVIDER_ERROR` | LLM provider (API key, rate limit) error |
|
|
225
|
+
| 7 | `POLICY_VIOLATION` | Publishing or governance policy violation |
|
|
226
|
+
| 8 | `HUMAN_LOCK_REQUIRED` | Human lock required but not present |
|
|
227
227
|
|
|
228
228
|
## JSON Output
|
|
229
229
|
|
|
@@ -240,15 +240,15 @@ kdna license verify --json <file>
|
|
|
240
240
|
|
|
241
241
|
## Product Matrix
|
|
242
242
|
|
|
243
|
-
| Layer
|
|
244
|
-
|
|
245
|
-
| Protocol
|
|
246
|
-
| Core Library | @aikdna/kdna-core
|
|
247
|
-
| Runtime
|
|
248
|
-
| Authoring
|
|
249
|
-
| Consumption
|
|
250
|
-
| Governance
|
|
251
|
-
| Distribution | Registry
|
|
243
|
+
| Layer | Product | Responsibility |
|
|
244
|
+
| ------------ | ----------------------- | ----------------------------------------------------------- |
|
|
245
|
+
| Protocol | KDNA SPEC | Define judgment asset format |
|
|
246
|
+
| Core Library | @aikdna/kdna-core | load / validate / compose / render |
|
|
247
|
+
| Runtime | @aikdna/kdna-cli | Agent runtime + compile + verify + test + publish + license |
|
|
248
|
+
| Authoring | KDNA Studio | Human-led judgment production |
|
|
249
|
+
| Consumption | KDNAChat | Load, use, compare |
|
|
250
|
+
| Governance | KDNA Governance Console | Approve, release, audit |
|
|
251
|
+
| Distribution | Registry | Discover, install, license, distribute |
|
|
252
252
|
|
|
253
253
|
## Development
|
|
254
254
|
|
package/SECURITY.md
CHANGED
|
@@ -31,7 +31,7 @@ We will acknowledge within 5 business days and provide a timeline for a fix.
|
|
|
31
31
|
|
|
32
32
|
## Out of Scope
|
|
33
33
|
|
|
34
|
-
- Domain content files (
|
|
34
|
+
- Domain content files (KDNA\_\*.json) — these are user-authored judgment assets
|
|
35
35
|
- Network-level attacks (man-in-the-middle on registry fetch) — use HTTPS
|
|
36
36
|
- Local filesystem access — CLI runs with user privileges
|
|
37
37
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aikdna/kdna-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "KDNA CLI — create, validate, install, and manage domain judgment packages for AI agents.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"test": "node --test tests/v07-commands.test.js tests/v012-commands.test.js",
|
|
25
25
|
"test:integration": "node --test tests/integration.test.js",
|
|
26
26
|
"test:all": "node --test tests/*.test.js",
|
|
27
|
+
"release:preflight": "node scripts/release-preflight.js",
|
|
27
28
|
"pretest": "npm install --ignore-scripts"
|
|
28
29
|
},
|
|
29
30
|
"keywords": [
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
"node": ">=18"
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
|
-
"@aikdna/kdna-core": "^0.
|
|
51
|
+
"@aikdna/kdna-core": "^0.6.0"
|
|
51
52
|
},
|
|
52
53
|
"optionalDependencies": {
|
|
53
54
|
"ajv": "^8.17.1",
|
|
@@ -135,7 +135,7 @@ After evaluating, you should usually have:
|
|
|
135
135
|
> "Two installed domains could apply here: @aikdna/writing
|
|
136
136
|
> (structural diagnosis) and @yourorg/copy_polish (line-level
|
|
137
137
|
> polish). Which judgment frame should I use?"
|
|
138
|
-
Do **not** silently blend.
|
|
138
|
+
> Do **not** silently blend.
|
|
139
139
|
|
|
140
140
|
Never load more than one domain as primary. A secondary domain can
|
|
141
141
|
constrain (e.g. `@aikdna/agent_safety` always advises on irreversible
|
|
@@ -181,8 +181,8 @@ stages.
|
|
|
181
181
|
You have now internalized the domain's judgment surface. From this
|
|
182
182
|
point on:
|
|
183
183
|
|
|
184
|
-
1. **Adopt the axioms as your reasoning frame** — reason
|
|
185
|
-
them, not
|
|
184
|
+
1. **Adopt the axioms as your reasoning frame** — reason _from_
|
|
185
|
+
them, not _around_ them.
|
|
186
186
|
2. **Honour the boundaries** — for each axiom you'd apply, confirm
|
|
187
187
|
the task is in `applies_when` AND not in `does_not_apply_when`.
|
|
188
188
|
3. **Pre-check failure_risk** — before producing output, ask:
|
|
@@ -222,6 +222,7 @@ KDNA domains influence agent judgment. The loader MUST apply safety rules before
|
|
|
222
222
|
### Loading Priority
|
|
223
223
|
|
|
224
224
|
When KDNA is loaded, the agent MUST respect this priority order:
|
|
225
|
+
|
|
225
226
|
1. System safety policy (highest — cannot be overridden)
|
|
226
227
|
2. Legal and compliance requirements
|
|
227
228
|
3. User's explicit intent
|
|
@@ -234,12 +235,12 @@ KDNA MUST NOT override system safety policies, legal requirements, or the user's
|
|
|
234
235
|
|
|
235
236
|
Before loading a KDNA domain, check its risk level in `kdna.json` or `KDNA_CARD.json`:
|
|
236
237
|
|
|
237
|
-
| Risk Level
|
|
238
|
-
|
|
239
|
-
| **R0** (Low)
|
|
240
|
-
| **R1** (Medium)
|
|
241
|
-
| **R2** (High)
|
|
242
|
-
| **R3** (Restricted) | Reject loading unless explicitly authorized
|
|
238
|
+
| Risk Level | Loading Behavior |
|
|
239
|
+
| ------------------- | ---------------------------------------------- |
|
|
240
|
+
| **R0** (Low) | Load silently |
|
|
241
|
+
| **R1** (Medium) | Load silently; log |
|
|
242
|
+
| **R2** (High) | Warn user before loading; require confirmation |
|
|
243
|
+
| **R3** (Restricted) | Reject loading unless explicitly authorized |
|
|
243
244
|
|
|
244
245
|
### Signature & Trust Checks
|
|
245
246
|
|
|
@@ -251,6 +252,7 @@ Before loading a KDNA domain, check its risk level in `kdna.json` or `KDNA_CARD.
|
|
|
251
252
|
### Runtime Logging
|
|
252
253
|
|
|
253
254
|
Every KDNA load MUST be logged with:
|
|
255
|
+
|
|
254
256
|
- Domain name and version
|
|
255
257
|
- Risk level
|
|
256
258
|
- Signature status
|
|
@@ -262,13 +264,13 @@ This enables audit and accountability.
|
|
|
262
264
|
|
|
263
265
|
## Failure handling
|
|
264
266
|
|
|
265
|
-
| Situation
|
|
266
|
-
|
|
267
|
-
| `kdna` CLI not installed
|
|
268
|
-
| `kdna available --json` returns `[]`
|
|
269
|
-
| `kdna load <name>` exits non-zero
|
|
270
|
-
| User explicitly asks for a domain that isn't installed | Tell them, suggest `kdna install <name>`. Do not fabricate the domain.
|
|
271
|
-
| Two domains' stances directly conflict on the task
|
|
267
|
+
| Situation | What to do |
|
|
268
|
+
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
269
|
+
| `kdna` CLI not installed | Skip KDNA. Answer normally. Mention installation only if user asks about KDNA itself. |
|
|
270
|
+
| `kdna available --json` returns `[]` | No domains installed. Skip KDNA. |
|
|
271
|
+
| `kdna load <name>` exits non-zero | That domain is broken (yanked, missing files, parse error). Try next candidate or skip KDNA. The error message tells you why. |
|
|
272
|
+
| User explicitly asks for a domain that isn't installed | Tell them, suggest `kdna install <name>`. Do not fabricate the domain. |
|
|
273
|
+
| Two domains' stances directly conflict on the task | Surface to user. Do not blend. |
|
|
272
274
|
|
|
273
275
|
---
|
|
274
276
|
|