@ericrisco/rsc 3.1.4 → 3.3.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/README.md +11 -7
- package/manifest.json +17 -68
- package/package.json +6 -1
- package/scripts/design-upstream.js +92 -0
- package/scripts/doctor.js +0 -24
- package/scripts/lib/default-skill-floor.js +5 -1
- package/scripts/lib/domains.js +2 -2
- package/scripts/lib/recommend.js +1 -3
- package/scripts/lib/retired-skills.js +7 -1
- package/skills/design/IMPECCABLE-LICENSE.txt +191 -0
- package/skills/design/SKILL.md +79 -328
- package/skills/design/THIRD_PARTY.md +26 -0
- package/skills/design/engine/LICENSE +21 -0
- package/skills/design/engine/RUN.md +515 -0
- package/skills/design/engine/UPSTREAM.json +4 -0
- package/skills/design/engine/assets/app.css +216 -0
- package/skills/design/engine/assets/base.css +105 -0
- package/skills/design/engine/assets/base.js +37 -0
- package/skills/design/engine/assets/charts.js +617 -0
- package/skills/design/engine/assets/scenes/stage.css +28 -0
- package/skills/design/engine/assets/scenes/stage.js +133 -0
- package/skills/design/engine/library/app.json +1327 -0
- package/skills/design/engine/library/directions.json +1078 -0
- package/skills/design/engine/library/heroes.json +1086 -0
- package/skills/design/engine/library/motions.json +92 -0
- package/skills/design/engine/library/palettes.json +1485 -0
- package/skills/design/engine/library/photos.json +7240 -0
- package/skills/design/engine/library/sections.json +4429 -0
- package/skills/design/engine/library/sites.json +8350 -0
- package/skills/design/engine/library/type.json +2024 -0
- package/skills/design/engine/references/app-screens.md +1199 -0
- package/skills/design/engine/references/colour.md +141 -0
- package/skills/design/engine/references/copy.md +177 -0
- package/skills/design/engine/references/critique.md +182 -0
- package/skills/design/engine/references/imagery.md +791 -0
- package/skills/design/engine/references/layout.md +292 -0
- package/skills/design/engine/references/motion.md +980 -0
- package/skills/design/engine/references/research.md +356 -0
- package/skills/design/engine/references/scenes.md +174 -0
- package/skills/design/engine/references/tells.md +115 -0
- package/skills/design/engine/references/type.md +170 -0
- package/skills/design/engine/scripts/assets.mjs +865 -0
- package/skills/design/engine/scripts/draw.mjs +584 -0
- package/skills/design/engine/scripts/inspect.mjs +303 -0
- package/skills/design/engine/scripts/lib/app-draw.mjs +203 -0
- package/skills/design/engine/scripts/lib/cdp.mjs +248 -0
- package/skills/design/engine/scripts/lib/probe.mjs +909 -0
- package/skills/design/engine/scripts/lib/rules.mjs +243 -0
- package/skills/design/engine/scripts/lint.mjs +119 -0
- package/skills/design/engine/scripts/scenes.mjs +124 -0
- package/skills/design/evals/cases.yaml +35 -46
- package/skills/design/references/design-md.md +49 -0
- package/skills/design/references/finish-review.md +46 -0
- package/skills/design/references/modes.md +51 -0
- package/skills/expo/SKILL.md +3 -4
- package/skills/marketing/references/landing-copy.md +2 -2
- package/skills/react/SKILL.md +2 -2
- package/skills/react-native/SKILL.md +3 -3
- package/skills/suggest/SKILL.md +12 -8
- package/skills/suggest/evals/cases.yaml +6 -0
- package/skills/swift-ios/SKILL.md +1 -1
- package/skills/ui-engineering/SKILL.md +3 -4
- package/skills/ui-engineering/evals/cases.yaml +2 -2
- package/skills/variant-explorer/SKILL.md +4 -4
- package/skills/variant-explorer/evals/cases.yaml +1 -1
- package/targets/clone-bootstrap.mjs +1 -1
- package/scripts/lib/design-identity.js +0 -117
- package/scripts/lib/starting-point.js +0 -314
- package/skills/design/evals/README.md +0 -53
- package/skills/design/references/ai-tells.md +0 -75
- package/skills/design/references/brand-grounding.md +0 -197
- package/skills/design/references/copywriting-frameworks.md +0 -138
- package/skills/design/references/design-systems.md +0 -49
- package/skills/design/references/inspiration-sources.md +0 -96
- package/skills/design/references/landing-anatomy-and-cro.md +0 -202
- package/skills/design/references/motion-and-interaction.md +0 -232
- package/skills/design/references/research-method.md +0 -154
- package/skills/design/references/signature-and-craft.md +0 -148
- package/skills/design/references/starting-point.md +0 -75
- package/skills/design/references/trends-2026.md +0 -80
- package/skills/design/references/visual-system.md +0 -237
- package/skills/design/scripts/verify.sh +0 -357
- package/skills/design-dna/PROMPT.md +0 -211
- package/skills/design-dna/SKILL.md +0 -162
- package/skills/design-dna/design-dna.schema.json +0 -230
- package/skills/design-dna/evals/README.md +0 -64
- package/skills/design-dna/evals/cases.yaml +0 -68
- package/skills/design-dna/references/method.md +0 -436
- package/skills/design-dna/scripts/emit.py +0 -164
- package/skills/design-dna/templates/PROMPT.md.tmpl +0 -42
- package/skills/design-dna/templates/SKILL.md.tmpl +0 -42
- package/skills/design-dna/templates/check.py.tmpl +0 -143
- package/skills/design-loop/SKILL.md +0 -160
- package/skills/design-loop/evals/README.md +0 -56
- package/skills/design-loop/evals/cases.yaml +0 -60
- package/skills/motion-craft/SKILL.md +0 -125
- package/skills/motion-craft/evals/cases.yaml +0 -38
- package/skills/motion-craft/scripts/verify.sh +0 -75
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@ericrisco/rsc)
|
|
10
10
|
[](https://www.npmjs.com/package/@ericrisco/rsc)
|
|
11
|
-
[](#the-catalog)
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
[](https://github.com/ericrisco/rsc-harness/stargazers)
|
|
14
14
|
|
|
@@ -60,7 +60,7 @@ The model is the brain your agent rents, and you already have it. rsc adds the r
|
|
|
60
60
|
| --- | --- | --- |
|
|
61
61
|
| **Memory** | `02-DOCS/` | A wiki the agent reads before it works and keeps up to date while it works. |
|
|
62
62
|
| **Hands** | `01-TOOLS/` | One folder per tool, with a test that proves the connection works. |
|
|
63
|
-
| **Trade** | skills | Only the skills your project needs:
|
|
63
|
+
| **Trade** | skills | Only the skills your project needs: 269 available, a handful installed. |
|
|
64
64
|
| **Reflexes** | hooks | Rules that hold even when the agent forgets them mid-session. |
|
|
65
65
|
|
|
66
66
|
### Why documentation comes first
|
|
@@ -405,6 +405,9 @@ file, and `rsc agents reset <name>` takes rsc's version back after a backup.
|
|
|
405
405
|
|
|
406
406
|
## CLI
|
|
407
407
|
|
|
408
|
+
`rsc` below is short for `npx @ericrisco/rsc`. Without a global install (`npm i -g @ericrisco/rsc`),
|
|
409
|
+
the bare `rsc` answers `command not found`: type the `npx` form.
|
|
410
|
+
|
|
408
411
|
```bash
|
|
409
412
|
# Setup
|
|
410
413
|
rsc onboard # plain-language onboarding; writes nothing until you accept
|
|
@@ -429,7 +432,7 @@ rsc ingest notas.md --topic crm # move a file into 02-DOCS/raw/ (verified c
|
|
|
429
432
|
rsc copy rules | check ad.txt # the phrases this project forbids, and a check before publishing
|
|
430
433
|
|
|
431
434
|
# Memory and diagnostics
|
|
432
|
-
rsc memory status | off | resume
|
|
435
|
+
rsc memory status | off | resume # session continuity; «recuerda esto» goes to 02-DOCS/wiki/
|
|
433
436
|
rsc doctor # harness health and onboarding readiness
|
|
434
437
|
rsc repair # put the harness back to what is declared
|
|
435
438
|
rsc backups | restore latest # project-local snapshots
|
|
@@ -468,7 +471,7 @@ snapshots the project first, so `rsc restore latest` undoes a bad update.
|
|
|
468
471
|
|
|
469
472
|
## The catalog
|
|
470
473
|
|
|
471
|
-
|
|
474
|
+
269 skills, grouped by what you are trying to do. Click any skill to read its `SKILL.md`. It fires on
|
|
472
475
|
its own when a task matches.
|
|
473
476
|
|
|
474
477
|
### 🧭 Core & control plane
|
|
@@ -561,11 +564,11 @@ whether, what and which platform.
|
|
|
561
564
|
|
|
562
565
|
### 🌀 Motion & interface craft
|
|
563
566
|
|
|
564
|
-
[
|
|
567
|
+
[ui-engineering](skills/ui-engineering/) · [variant-explorer](skills/variant-explorer/) · [scroll-film](skills/scroll-film/)
|
|
565
568
|
|
|
566
569
|
### 🎨 Design & content craft
|
|
567
570
|
|
|
568
|
-
[design
|
|
571
|
+
[design](skills/design/) · [presentations](skills/presentations/) · [course-storytelling](skills/course-storytelling/) · [course-builder](skills/course-builder/) · [technical-writing](skills/technical-writing/) · [translation-l10n](skills/translation-l10n/)
|
|
569
572
|
|
|
570
573
|
### 🧠 Knowledge & meta
|
|
571
574
|
|
|
@@ -626,7 +629,8 @@ Most of this catalog is written here. These are not, and they keep their author'
|
|
|
626
629
|
| Skills | Source | License |
|
|
627
630
|
| --- | --- | --- |
|
|
628
631
|
| `design-eng` · `animate` · `animate-expo` · `review-animations` · `improve-animations` · `find-animation-opportunities` · `animation-vocabulary` · `apple-design` · `prototype` · `pick-ui-library` · `write-swift` · `ask-sonner` | [emilkowalski/skills](https://github.com/emilkowalski/skills) by Emil Kowalski, commit `d23d7f8` | MIT |
|
|
629
|
-
|
|
|
632
|
+
| the engine of `design` (`skills/design/engine/`: direction draw, browser inspector, study library), shipped unmodified | [Leonxlnx/taste-skill](https://github.com/Leonxlnx/taste-skill) v2.1.4 | MIT |
|
|
633
|
+
| the four modes, the fresh review and the `DESIGN.md` record in `design` (text rewritten) | [pbakaus/impeccable](https://github.com/pbakaus/impeccable) by Paul Bakaus, `skill-v4.7.0` | Apache-2.0 |
|
|
630
634
|
| the answer-first habits in `orient` | [ayghri/i-have-adhd](https://github.com/ayghri/i-have-adhd) | MIT |
|
|
631
635
|
| the scroll-scrubbed camera flight, the frame handoff between clips and the phone fixes behind `scroll-film` (prose and engine rewritten) | [oso95/scroll-world](https://github.com/oso95/scroll-world) | MIT |
|
|
632
636
|
|
package/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.1
|
|
2
|
+
"version": "3.3.1",
|
|
3
3
|
"counts": {
|
|
4
|
-
"skills":
|
|
4
|
+
"skills": 269,
|
|
5
5
|
"agents": 34,
|
|
6
6
|
"commands": 53,
|
|
7
7
|
"fixedCommands": 20
|
|
@@ -1311,62 +1311,29 @@
|
|
|
1311
1311
|
},
|
|
1312
1312
|
{
|
|
1313
1313
|
"id": "design",
|
|
1314
|
-
"description": "Use when designing or
|
|
1314
|
+
"description": "Use when designing, redesigning, restyling or reviewing a web page or app screen (landing, product site, portfolio, dashboard, docs) or when a UI looks generic or AI-made. Deals a researched direction, takes the idea from the subject, uses real pictures, proves it in a browser. NOT the words (landing-copy), NOT component state (ui-engineering).",
|
|
1315
1315
|
"tags": [
|
|
1316
1316
|
"design",
|
|
1317
|
-
"ux",
|
|
1318
1317
|
"ui",
|
|
1318
|
+
"ux",
|
|
1319
1319
|
"landing",
|
|
1320
|
-
"
|
|
1320
|
+
"dashboard",
|
|
1321
|
+
"frontend",
|
|
1322
|
+
"taste"
|
|
1321
1323
|
],
|
|
1322
1324
|
"recommends": [
|
|
1323
|
-
"
|
|
1324
|
-
"
|
|
1325
|
-
"
|
|
1326
|
-
"
|
|
1325
|
+
"landing-copy",
|
|
1326
|
+
"ui-engineering",
|
|
1327
|
+
"accessibility",
|
|
1328
|
+
"brand-identity",
|
|
1329
|
+
"nextjs"
|
|
1327
1330
|
],
|
|
1328
1331
|
"profiles": [
|
|
1332
|
+
"minimal",
|
|
1333
|
+
"core",
|
|
1329
1334
|
"full"
|
|
1330
1335
|
]
|
|
1331
1336
|
},
|
|
1332
|
-
{
|
|
1333
|
-
"id": "design-dna",
|
|
1334
|
-
"description": "Use when a design has won and its look must survive: codify it into a permanent style skill with measured ratios, bans and tests that can fail, then build new pieces in that exact look. Fires on 'turn this into a skill', 'keep the same style', 'my output drifted'. NOT finding the winner (that is `design-loop`), NOT the words (that is `marketing`).",
|
|
1335
|
-
"tags": [
|
|
1336
|
-
"design",
|
|
1337
|
-
"style",
|
|
1338
|
-
"dna",
|
|
1339
|
-
"codify",
|
|
1340
|
-
"skill-factory",
|
|
1341
|
-
"consistency"
|
|
1342
|
-
],
|
|
1343
|
-
"recommends": [
|
|
1344
|
-
"design-loop",
|
|
1345
|
-
"design",
|
|
1346
|
-
"nextjs",
|
|
1347
|
-
"marketing"
|
|
1348
|
-
],
|
|
1349
|
-
"profiles": []
|
|
1350
|
-
},
|
|
1351
|
-
{
|
|
1352
|
-
"id": "design-loop",
|
|
1353
|
-
"description": "Use when something must be built well and there is a real reference it should beat: turn what makes the reference good into measured mechanisms, then run a builder and three fresh-context critics until all three pass. Fires on 'design loop', 'make it as good as <site>', 'it looks generic'. NOT keeping an already-won look (that is `design-dna`).",
|
|
1354
|
-
"tags": [
|
|
1355
|
-
"design",
|
|
1356
|
-
"critique",
|
|
1357
|
-
"loop",
|
|
1358
|
-
"reference",
|
|
1359
|
-
"quality",
|
|
1360
|
-
"convergence"
|
|
1361
|
-
],
|
|
1362
|
-
"recommends": [
|
|
1363
|
-
"design",
|
|
1364
|
-
"design-dna",
|
|
1365
|
-
"marketing",
|
|
1366
|
-
"nextjs"
|
|
1367
|
-
],
|
|
1368
|
-
"profiles": []
|
|
1369
|
-
},
|
|
1370
1337
|
{
|
|
1371
1338
|
"id": "digitalocean",
|
|
1372
1339
|
"description": "Use when deploying or operating a workload on DigitalOcean — Droplet vs App Platform vs Functions, doctl, app spec YAML, Managed Postgres/MySQL/Valkey on the VPC, S3-compatible Spaces + CDN. NOT host-agnostic CI/CD or rollback strategy (that is `deployment`), NOT a bare Hetzner VPS (that is `hetzner`), NOT another managed PaaS (that is `railway`).",
|
|
@@ -3131,23 +3098,6 @@
|
|
|
3131
3098
|
],
|
|
3132
3099
|
"profiles": []
|
|
3133
3100
|
},
|
|
3134
|
-
{
|
|
3135
|
-
"id": "motion-craft",
|
|
3136
|
-
"description": "Use when an interface moves and the movement has to feel right — durations and easing, what must never animate, fixing motion that reads sluggish, cheap or janky, and reduced-motion. Web and native. NOT the visual system (that is `design`), NOT the graded critique (that is `design-loop`).",
|
|
3137
|
-
"tags": [
|
|
3138
|
-
"motion",
|
|
3139
|
-
"animation",
|
|
3140
|
-
"interface",
|
|
3141
|
-
"craft",
|
|
3142
|
-
"frontend"
|
|
3143
|
-
],
|
|
3144
|
-
"recommends": [
|
|
3145
|
-
"design"
|
|
3146
|
-
],
|
|
3147
|
-
"profiles": [
|
|
3148
|
-
"full"
|
|
3149
|
-
]
|
|
3150
|
-
},
|
|
3151
3101
|
{
|
|
3152
3102
|
"id": "mysql",
|
|
3153
3103
|
"description": "Use when designing, querying, indexing or operating a MySQL or MariaDB database and engine-specific behaviour matters — schema and type choices, index design, reading EXPLAIN, online schema change, replication and replica lag, locking and InnoDB deadlocks, charset traps, and server config. NOT portable SELECT/JOIN/window-function craft (that is `sql`), NOT PostgreSQL engine behaviour like VACUUM or JSONB (that is `postgresdb`), NOT the PlanetScale/Vitess branch-and-deploy workflow (that is `planetscale`).",
|
|
@@ -5170,8 +5120,7 @@
|
|
|
5170
5120
|
"craft"
|
|
5171
5121
|
],
|
|
5172
5122
|
"recommends": [
|
|
5173
|
-
"design"
|
|
5174
|
-
"motion-craft"
|
|
5123
|
+
"design"
|
|
5175
5124
|
],
|
|
5176
5125
|
"profiles": [
|
|
5177
5126
|
"core",
|
|
@@ -5295,7 +5244,7 @@
|
|
|
5295
5244
|
},
|
|
5296
5245
|
{
|
|
5297
5246
|
"id": "variant-explorer",
|
|
5298
|
-
"description": "Use when someone wants OPTIONS rather than an answer — 'show me a few versions', picking between approaches by seeing them. Genuinely different candidates, cheap to throw away, trade-off named. NOT the critique that judges one (`design
|
|
5247
|
+
"description": "Use when someone wants OPTIONS rather than an answer — 'show me a few versions', picking between approaches by seeing them. Genuinely different candidates, cheap to throw away, trade-off named. NOT the critique that judges one (`design`), NOT the spec (`specify`).",
|
|
5299
5248
|
"tags": [
|
|
5300
5249
|
"prototyping",
|
|
5301
5250
|
"divergence",
|
|
@@ -5304,7 +5253,7 @@
|
|
|
5304
5253
|
"decision"
|
|
5305
5254
|
],
|
|
5306
5255
|
"recommends": [
|
|
5307
|
-
"design
|
|
5256
|
+
"design"
|
|
5308
5257
|
],
|
|
5309
5258
|
"profiles": [
|
|
5310
5259
|
"full"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ericrisco/rsc",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"description": "A guided harness builder that turns your goal into a minimal, verified AI-agent setup using strict best practices.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"knowledge:doctor": "node scripts/knowledge-doctor.js",
|
|
20
20
|
"spec:gate": "node scripts/spec-gate.js",
|
|
21
21
|
"routing:audit": "node scripts/routing-audit.js",
|
|
22
|
+
"design:upstream": "node scripts/design-upstream.js",
|
|
22
23
|
"originality:check": "node scripts/originality-check.js",
|
|
23
24
|
"test": "node --test",
|
|
24
25
|
"coverage": "c8 --reporter=text node --test",
|
|
@@ -115,6 +116,10 @@
|
|
|
115
116
|
{
|
|
116
117
|
"fixedIn": "2.1.0",
|
|
117
118
|
"symptom": "Answers were long and leaned on hidden reasoning, and onboarding asked an accompaniment level few could answer; now: short stand-alone sentences, one question"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"fixedIn": "3.3.0",
|
|
122
|
+
"symptom": "Pages and screens designed with rsc came out generic and AI-looking, and most projects had no design skill installed at all (found by Carlos del Corral)"
|
|
118
123
|
}
|
|
119
124
|
]
|
|
120
125
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// design-upstream.js — is the `design` engine behind the projects it comes from?
|
|
3
|
+
//
|
|
4
|
+
// `skills/design/engine/` is taste-skill shipped unmodified, and three of its references adapt
|
|
5
|
+
// impeccable's text. Both upstreams ship weekly. Nothing reminded anyone, so the previous design
|
|
6
|
+
// skill drifted into the state that got it rebuilt (spec design-from-scratch). This is the reminder.
|
|
7
|
+
//
|
|
8
|
+
// node scripts/design-upstream.js report: silent and exit 0 when current,
|
|
9
|
+
// one line per upstream that moved and exit 1
|
|
10
|
+
// node scripts/design-upstream.js --sync DIR copy a REVIEWED taste-skill checkout over engine/
|
|
11
|
+
//
|
|
12
|
+
// It never downloads code to apply it. Bringing a new version in is a person reading the diff and
|
|
13
|
+
// running --sync on a checkout they cloned themselves (a public skill is untrusted input).
|
|
14
|
+
import { readFileSync, writeFileSync, rmSync, cpSync, existsSync } from 'node:fs';
|
|
15
|
+
import { join, dirname } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { execFileSync } from 'node:child_process';
|
|
18
|
+
|
|
19
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
20
|
+
export const ENGINE = join(ROOT, 'skills', 'design', 'engine');
|
|
21
|
+
const RUNTIME = ['scripts', 'library', 'assets', 'references'];
|
|
22
|
+
|
|
23
|
+
export function readUpstream(engine = ENGINE) {
|
|
24
|
+
return JSON.parse(readFileSync(join(engine, 'UPSTREAM.json'), 'utf8'));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function getJson(fetchImpl, url) {
|
|
28
|
+
const res = await fetchImpl(url, { headers: { accept: 'application/vnd.github+json', 'user-agent': 'rsc-design-upstream' } });
|
|
29
|
+
if (!res.ok) throw new Error(`${url} → HTTP ${res.status}`);
|
|
30
|
+
return res.json();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** One entry per upstream that moved; an empty list means the engine is current. */
|
|
34
|
+
export async function checkUpstream({ upstream = readUpstream(), fetchImpl = fetch } = {}) {
|
|
35
|
+
const moved = [];
|
|
36
|
+
const t = upstream['taste-skill'];
|
|
37
|
+
const commits = await getJson(fetchImpl, `https://api.github.com/repos/${t.repo}/commits?path=${t.path}&per_page=1`);
|
|
38
|
+
const latest = commits[0]?.sha;
|
|
39
|
+
// Different ids do not mean newer: the shipped commit is often a merge that already contains the
|
|
40
|
+
// latest commit on the path. Only a latest commit AHEAD of what shipped is news.
|
|
41
|
+
const ahead = latest && latest !== t.commit
|
|
42
|
+
&& ['ahead', 'diverged'].includes((await getJson(fetchImpl, `https://api.github.com/repos/${t.repo}/compare/${t.commit}...${latest}`)).status);
|
|
43
|
+
if (ahead) {
|
|
44
|
+
moved.push({ id: 'taste-skill', shipped: t.commit.slice(0, 7), latest: latest.slice(0, 7), url: `https://github.com/${t.repo}/compare/${t.commit}...${latest}` });
|
|
45
|
+
}
|
|
46
|
+
const i = upstream.impeccable;
|
|
47
|
+
const releases = await getJson(fetchImpl, `https://api.github.com/repos/${i.repo}/releases?per_page=30`);
|
|
48
|
+
const skill = releases.find((r) => typeof r.tag_name === 'string' && r.tag_name.startsWith('skill-v'));
|
|
49
|
+
if (skill && skill.tag_name !== i.version) {
|
|
50
|
+
moved.push({ id: 'impeccable', shipped: i.version, latest: skill.tag_name, url: `https://github.com/${i.repo}/releases/tag/${skill.tag_name}` });
|
|
51
|
+
}
|
|
52
|
+
return moved;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Copy a reviewed taste-skill checkout over engine/, and record which commit it was. */
|
|
56
|
+
export function syncTaste(checkout, engine = ENGINE) {
|
|
57
|
+
const src = join(checkout, 'skills', 'taste-skill');
|
|
58
|
+
if (!existsSync(join(src, 'SKILL.md'))) throw new Error(`${checkout} is not a taste-skill checkout (no skills/taste-skill/SKILL.md)`);
|
|
59
|
+
for (const dir of RUNTIME) {
|
|
60
|
+
rmSync(join(engine, dir), { recursive: true, force: true });
|
|
61
|
+
if (existsSync(join(src, dir))) cpSync(join(src, dir), join(engine, dir), { recursive: true });
|
|
62
|
+
}
|
|
63
|
+
cpSync(join(checkout, 'LICENSE'), join(engine, 'LICENSE'));
|
|
64
|
+
// RUN.md is the upstream SKILL.md without its front matter, so it is never discovered as a skill.
|
|
65
|
+
writeFileSync(join(engine, 'RUN.md'), readFileSync(join(src, 'SKILL.md'), 'utf8').replace(/^---\n[\s\S]*?\n---\n/, ''));
|
|
66
|
+
const upstream = readUpstream(engine);
|
|
67
|
+
// The last commit that touched the skill folder; checkUpstream asks GitHub whether anything newer
|
|
68
|
+
// on that path is ahead of it.
|
|
69
|
+
upstream['taste-skill'].commit = execFileSync('git', ['-C', checkout, 'log', '-1', '--format=%H', '--', 'skills/taste-skill'], { encoding: 'utf8' }).trim();
|
|
70
|
+
const changelog = join(checkout, 'CHANGELOG.md');
|
|
71
|
+
const version = existsSync(changelog) && /^## (\d+\.\d+\.\d+)/m.exec(readFileSync(changelog, 'utf8'));
|
|
72
|
+
if (version) upstream['taste-skill'].version = version[1];
|
|
73
|
+
writeFileSync(join(engine, 'UPSTREAM.json'), `${JSON.stringify(upstream, null, 2)}\n`);
|
|
74
|
+
return upstream['taste-skill'];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function main() {
|
|
78
|
+
const at = process.argv.indexOf('--sync');
|
|
79
|
+
if (at !== -1) {
|
|
80
|
+
const synced = syncTaste(process.argv[at + 1]);
|
|
81
|
+
console.log(`engine synced to taste-skill ${synced.version} (${synced.commit.slice(0, 7)}). Run the tests and read the diff before committing.`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const moved = await checkUpstream();
|
|
85
|
+
for (const m of moved) console.log(`${m.id}: shipped ${m.shipped}, upstream ${m.latest} → ${m.url}`);
|
|
86
|
+
if (moved.length) {
|
|
87
|
+
console.log('Review the change, clone it yourself, then: node scripts/design-upstream.js --sync <taste-skill checkout>');
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (import.meta.url === `file://${process.argv[1]}`) main().catch((e) => { console.error(e.message); process.exitCode = 2; });
|
package/scripts/doctor.js
CHANGED
|
@@ -11,8 +11,6 @@ import { readManifest as readProjectManifest } from './lib/manifest-file.js';
|
|
|
11
11
|
import { listBackups } from './lib/backups.js';
|
|
12
12
|
import { SDD_GATE_TEXT } from '../targets/hook-once.mjs';
|
|
13
13
|
import { isEnabled, checkSello, readSello, countFindings, readEffectiveConfig, validateRiskConfig } from '../targets/sello.mjs';
|
|
14
|
-
import { designIdentity } from './lib/design-identity.js';
|
|
15
|
-
import { startingPointSummary } from './lib/starting-point.js';
|
|
16
14
|
import { countGaps, listSkills, listAgents } from './lib/capabilities.js';
|
|
17
15
|
import { resolveCommands, commandPath, targetHasCommands } from '../targets/commands.js';
|
|
18
16
|
import { inspectMemoryWiring } from '../targets/memory.js';
|
|
@@ -104,17 +102,6 @@ export function missingHookScripts({ target, home = homedir(), cwd = process.cwd
|
|
|
104
102
|
// Is the post-merge trigger actually armed in this clone? Three states, because they need three
|
|
105
103
|
// different answers: armed, absent (repair it), or someone else's (leave it — chaining is our job
|
|
106
104
|
// at install time, and overwriting a husky hook to fix a convenience would be indefensible).
|
|
107
|
-
// The skills that read or write a design identity (02-DOCS/wiki/brand/) or a starting point. The
|
|
108
|
-
// state is always reported; the FIX — "run design-loop, then design-dna" — is advice, and advice needs
|
|
109
|
-
// evidence. A todo web app with none of these installed was told to run two skills it does not have
|
|
110
|
-
// and never asked for (E2E 2026-10-07).
|
|
111
|
-
const DESIGN_SKILLS = new Set(['design', 'design-loop', 'design-dna', 'brand-voice', 'content-engine', 'marketing', 'presentations', 'make']);
|
|
112
|
-
function withoutUnfoundedFix(summary, inPlay) {
|
|
113
|
-
if (inPlay || !summary || !summary.fix) return summary;
|
|
114
|
-
const { fix, ...rest } = summary;
|
|
115
|
-
return { ...rest, note: 'no design skill is installed here, so nothing is recommended' };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
105
|
function worktreeCleanupStatus(root, policy) {
|
|
119
106
|
if (!existsSync(join(root, '.git'))) return { state: 'not-a-repo' };
|
|
120
107
|
if (existsSync(join(root, '.rsc', '.no-worktree-cleanup'))) return { state: 'off-by-choice' };
|
|
@@ -250,9 +237,6 @@ export function doctor({ target, home, cwd }) {
|
|
|
250
237
|
const path = agentPath(target, root, id);
|
|
251
238
|
return path && !existsSync(path);
|
|
252
239
|
}).map((id) => ({ id, path: agentPath(target, root, id), action: 'Run `npx @ericrisco/rsc sync` to restore this managed agent.' }));
|
|
253
|
-
// What THIS harness installed, not every skill visible from here: a design skill in the user's
|
|
254
|
-
// global scope is how a todo app's doctor came to recommend design-dna (E2E 2026-10-07).
|
|
255
|
-
const designInPlay = Object.keys(state.skills || {}).some((id) => DESIGN_SKILLS.has(id));
|
|
256
240
|
const report = {
|
|
257
241
|
target,
|
|
258
242
|
installed: Object.keys(state.skills),
|
|
@@ -273,14 +257,6 @@ export function doctor({ target, home, cwd }) {
|
|
|
273
257
|
worktreeHygiene: worktreeHygiene(root),
|
|
274
258
|
ownSkills: ownSkillsIn(paths, readProjectManifest(root)?.ownSkills || []),
|
|
275
259
|
sello: selloStatus(root),
|
|
276
|
-
// Whether this harness has a design identity at all. `design` has always DECLARED that it
|
|
277
|
-
// stops without one; until lib/design-identity.js nothing checked it (P2). Reported here,
|
|
278
|
-
// never nagged about and never blocking: a missing identity is low risk (P7).
|
|
279
|
-
designIdentity: withoutUnfoundedFix(designIdentity(root), designInPlay),
|
|
280
|
-
// The other half of the same question: an identity is what this project settled on, a starting
|
|
281
|
-
// point is what it has to settle FROM. Three skills promise to propose one and none could look;
|
|
282
|
-
// this is the look. One field, not a section — a report grows for every user who runs it (P5).
|
|
283
|
-
designStartingPoint: withoutUnfoundedFix(startingPointSummary(root), designInPlay),
|
|
284
260
|
// An inert gate must never read as an armed one (the same rule the sello follows):
|
|
285
261
|
// the gitmoji guard has a per-project kill switch, so say which state it is in.
|
|
286
262
|
gitmojiGuard: state.policy?.gitmojiGuard === false
|
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
// `connect-tool` joined in 3.0.13 (issue #303): rsc ships no ready-made connections, so "connect my
|
|
15
15
|
// Holded" is answered by a method, not a list, and that method has to be there the first time the
|
|
16
16
|
// user asks, in any kind of project. Like `unslop`, only its description is paid for on other turns.
|
|
17
|
-
|
|
17
|
+
//
|
|
18
|
+
// `design` joined in 3.3.0 (spec design-from-scratch): it was `full`-only, so most projects designed
|
|
19
|
+
// with no design skill at all. Only its description is paid for on other turns; the engine it ships
|
|
20
|
+
// (scripts and data) is never loaded into context.
|
|
21
|
+
export const DEFAULT_SKILL_FLOOR = Object.freeze(['orient', 'suggest', 'unslop', 'ftd', 'connect-tool', 'design']);
|
|
18
22
|
|
|
19
23
|
export function withDefaultSkillFloor(skillIds = []) {
|
|
20
24
|
return [...new Set([...DEFAULT_SKILL_FLOOR, ...skillIds])];
|
package/scripts/lib/domains.js
CHANGED
|
@@ -24,8 +24,8 @@ export const DOMAINS = [
|
|
|
24
24
|
{ title: 'Ship & operate — platforms', ids: ['vercel', 'netlify', 'cloudflare', 'railway', 'render', 'fly-io', 'coolify', 'hetzner', 'digitalocean', 'aws-essentials', 'gcp-essentials'] },
|
|
25
25
|
{ title: 'Ship & operate — devops', ids: ['docker', 'github-actions', 'git-workflow', 'domains-dns', 'monitoring', 'email-deliverability', 'scaling', 'deployment', 'deprecation'] },
|
|
26
26
|
{ title: 'Ship & operate — quality & security', ids: ['code-review', 'security-scan', 'secure-coding', 'testing-py', 'testing-web', 'testing-go', 'e2e-testing', 'accessibility', 'performance', 'error-handling', 'observability'] },
|
|
27
|
-
{ title: 'Motion & interface craft', ids: ['
|
|
28
|
-
{ title: 'Design & content craft', ids: ['design
|
|
27
|
+
{ title: 'Motion & interface craft', ids: ['ui-engineering', 'variant-explorer', 'scroll-film'] },
|
|
28
|
+
{ title: 'Design & content craft', ids: ['design', 'presentations', 'course-storytelling', 'course-builder', 'technical-writing', 'translation-l10n'] },
|
|
29
29
|
{ title: 'Knowledge & meta', ids: ['knowledge-ops', 'codebase-onboarding', 'research-ops', 'decision-records', 'continuous-learning', 'skill-scout', 'context-budget', 'roast-me', 'fable-operator'] },
|
|
30
30
|
];
|
|
31
31
|
|
package/scripts/lib/recommend.js
CHANGED
|
@@ -10,9 +10,7 @@ const OUTCOMES = {
|
|
|
10
10
|
fastapi: 'Your API / Python backend',
|
|
11
11
|
go: 'Your Go backend service',
|
|
12
12
|
postgresdb: 'Store your data reliably',
|
|
13
|
-
design: '
|
|
14
|
-
'design-loop': 'Make it as good as the site you admire',
|
|
15
|
-
'design-dna': 'Keep every page looking like yours',
|
|
13
|
+
design: 'Pages and screens that look designed, not generated',
|
|
16
14
|
marketing: 'Copy that sells',
|
|
17
15
|
presentations: 'On-brand presentations',
|
|
18
16
|
'course-storytelling': 'Teach so it actually lands',
|
|
@@ -8,7 +8,13 @@
|
|
|
8
8
|
//
|
|
9
9
|
// `targets/clone-bootstrap.mjs` is committed into user repos and cannot import this file; it carries
|
|
10
10
|
// an inline copy, and tests/retired-skills.test.js holds the two equal in behaviour.
|
|
11
|
-
|
|
11
|
+
//
|
|
12
|
+
// `design-loop`, `design-dna` and `motion-craft` folded into the rebuilt `design` in 3.3.0 (spec
|
|
13
|
+
// design-from-scratch): its engine deals the direction, measures the render and owns the motion layer.
|
|
14
|
+
export const RETIRED_SKILLS = Object.freeze({
|
|
15
|
+
eli5: 'orient', 'show-me': 'orient', bro: 'unslop',
|
|
16
|
+
'design-loop': 'design', 'design-dna': 'design', 'motion-craft': 'design',
|
|
17
|
+
});
|
|
12
18
|
|
|
13
19
|
const retiredTo = (id) => (Object.hasOwn(RETIRED_SKILLS, id) ? RETIRED_SKILLS[id] : id);
|
|
14
20
|
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to the Licensor for inclusion in the Work by the copyright
|
|
52
|
+
owner or by an individual or Legal Entity authorized to submit on
|
|
53
|
+
behalf of the copyright owner. For the purposes of this definition,
|
|
54
|
+
"submitted" means any form of electronic, verbal, or written
|
|
55
|
+
communication sent to the Licensor or its representatives, including
|
|
56
|
+
but not limited to communication on electronic mailing lists, source
|
|
57
|
+
code control systems, and issue tracking systems that are managed by,
|
|
58
|
+
or on behalf of, the Licensor for the purpose of discussing and
|
|
59
|
+
improving the Work, but excluding communication that is conspicuously
|
|
60
|
+
marked or otherwise designated in writing by the copyright owner as
|
|
61
|
+
"Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
Copyright 2025 Paul Bakaus
|
|
180
|
+
|
|
181
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
182
|
+
you may not use this file except in compliance with the License.
|
|
183
|
+
You may obtain a copy of the License at
|
|
184
|
+
|
|
185
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
186
|
+
|
|
187
|
+
Unless required by applicable law or agreed to in writing, software
|
|
188
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
189
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
190
|
+
See the License for the specific language governing permissions and
|
|
191
|
+
limitations under the License.
|