naive-framework 0.3.0 → 0.4.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/interface/cli/naive.mjs +1 -1
- package/interface/layer.json +4 -0
- package/interface/skills/choosing-artifacts/SKILL.md +113 -0
- package/package.json +1 -1
- package/schema/check-data-packages.mjs +1 -1
- package/schema/init-venture.mjs +14 -4
- package/schema/port-venture.mjs +3 -3
- package/schema/venture-paths.mjs +17 -5
package/interface/cli/naive.mjs
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// naive typegen write .naive/types/ from the route table and the MCP tools
|
|
18
18
|
// naive upgrade [<venture dir>] [--framework] move a venture onto the next Naive layout; --framework first
|
|
19
19
|
// updates the installed framework with the venture's package manager (I-29)
|
|
20
|
-
// naive port <folder> --venture <dir> [--to <path>] plan moving a folder into the venture as it is (
|
|
20
|
+
// naive port <folder> --venture <dir> [--to <path>] plan moving a folder into the venture as it is (codebase/<name>)
|
|
21
21
|
// naive port --venture <dir> --apply --confirm port
|
|
22
22
|
// carry out that plan (EE-076)
|
|
23
23
|
// naive migrate --from <project> --venture <dir> an agent rewrites the project as Naive records, as a plan and decisions
|
package/interface/layer.json
CHANGED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: knowledge
|
|
3
|
+
tags: [everything-ecosystem, naive, skills, interface, artifacts, records, views]
|
|
4
|
+
ai-model: claude-opus-5.5
|
|
5
|
+
created: 2026-10-29T20:12:08Z
|
|
6
|
+
source: hybrid
|
|
7
|
+
name: choosing-artifacts
|
|
8
|
+
description: >
|
|
9
|
+
Decide whether a venture action should build an artifact (a rendered view a
|
|
10
|
+
person reads, presents, shares or fills in) and which kind, and keep records,
|
|
11
|
+
the source of truth in k-base/, separate from artifacts, which are views built
|
|
12
|
+
from records and cite them. General for any agent, with a section for Claude's
|
|
13
|
+
own artifacts in Claude Code and claude.ai.
|
|
14
|
+
MANDATORY TRIGGERS: make an artifact, build a page, make a deck, make a
|
|
15
|
+
dashboard, pitch deck, investor update, show me, visualize, one-pager, which
|
|
16
|
+
artifact, should this be a doc, render this record.
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Choosing artifacts
|
|
20
|
+
|
|
21
|
+
Interface layer. An artifact is a rendered view; a record is the source of truth. Build an artifact from records when a person needs to look at, present, share or fill in something. Never let the artifact become the record.
|
|
22
|
+
|
|
23
|
+
## The core rule: records are not artifacts
|
|
24
|
+
|
|
25
|
+
- A **record** is a file in the venture's `k-base/` with a schema. It is what agents read, what decisions cite and what `naive check` tests.
|
|
26
|
+
- An **artifact** is a page, deck, dashboard or file made from one or more records for a reader. A marketing site describes the company, but the company's facts live in its records, not on the site.
|
|
27
|
+
- Every artifact names the records it was built from (route and revision or date), so a reader can trace each claim.
|
|
28
|
+
- When a record changes, rebuild the artifact. Never hand-edit an artifact to change a fact.
|
|
29
|
+
- What people type into an artifact (a form, a docket, comments) is input. Write it back through the router as a proposal or a draft in `_drafts/`; a person settles it. The artifact's own stored state is never the source of truth.
|
|
30
|
+
- Outside a Naive venture the same rule holds: name what the view was made from, and keep the facts where they already live.
|
|
31
|
+
|
|
32
|
+
## Should this be an artifact at all?
|
|
33
|
+
|
|
34
|
+
Answer in the conversation when the result is short, read once and acted on now. Build an artifact when any of these is true:
|
|
35
|
+
|
|
36
|
+
1. Someone other than the requester will read or use it.
|
|
37
|
+
2. It will be presented, printed, exported or sent.
|
|
38
|
+
3. A person needs to fill it in, decide on it or come back to it.
|
|
39
|
+
4. It is longer than about fifteen lines, or a picture explains it better than prose.
|
|
40
|
+
|
|
41
|
+
If it belongs in the venture's code (a README, a spec that ships, code docs), write a file in `codebase/` instead.
|
|
42
|
+
|
|
43
|
+
## Kinds of artifact
|
|
44
|
+
|
|
45
|
+
| Kind | Use it for |
|
|
46
|
+
|---|---|
|
|
47
|
+
| Document | Writing people keep editing or pass around: memo, plan, spec, brief, report, notes |
|
|
48
|
+
| Deck | Something to present or page through: pitch, investor update, demo-day talk |
|
|
49
|
+
| Dashboard | Numbers people read: KPIs, runway, scorecards. Every number shows its source record |
|
|
50
|
+
| Design | Visual work: landing pages, screens, mockups, ads, social posts |
|
|
51
|
+
| Design system | The brand's tokens, type, components and assets, built from the brand record |
|
|
52
|
+
| Page | Explainers, diagrams, interactive tools, trackers, forms |
|
|
53
|
+
| File | Only when a format is named (.pptx, .docx, .xlsx, PDF) or an existing file is to be changed |
|
|
54
|
+
|
|
55
|
+
## Decide in order
|
|
56
|
+
|
|
57
|
+
1. Is it an artifact at all? (above)
|
|
58
|
+
2. Did the person name a format? Use it.
|
|
59
|
+
3. Writing to edit: document. To present: deck. Data to read: dashboard. A visual: design. A brand: design system.
|
|
60
|
+
4. Otherwise a page. Add a diagram, charts or interactivity only when each earns its place.
|
|
61
|
+
5. List the records it reads, and put that source list in the artifact.
|
|
62
|
+
6. Read the records through Naive (`mentura_read`, or `naive` routes), never from memory. A record that is missing, a draft or stale is shown as such, never filled in.
|
|
63
|
+
|
|
64
|
+
## Actions and their artifacts
|
|
65
|
+
|
|
66
|
+
Each function's skills say which of its actions build which artifact. This is the starting map; it is a proposal until the founder confirms it in `naive.config.json` or the function's own skill.
|
|
67
|
+
|
|
68
|
+
| Function | Action | Artifact | Built from |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| Foundation | Review the strategic foundation | Document (brief) | foundation/problem, foundation/icp, telos, the phase in venture.json |
|
|
71
|
+
| Foundation | Decide pending decisions | Page that collects answers (the docket) | decisions/; answers go back as decisions a person settles |
|
|
72
|
+
| Validation | Plan or report an experiment | Document | validation records and evidence/ |
|
|
73
|
+
| Validation | Track evidence over time | Dashboard | evidence/ and metric records |
|
|
74
|
+
| Validation | Run interviews | Page that collects answers (intake form) | the interview schema; answers become records |
|
|
75
|
+
| Marketing | Draft a landing page or ad | Design | positioning and marketing/brand |
|
|
76
|
+
| Marketing | Set up the brand | Design system | marketing/brand |
|
|
77
|
+
| Marketing | Plan content | Document | positioning and calendar records |
|
|
78
|
+
| Product | Write a spec or roadmap | Document | product/ and decisions/ |
|
|
79
|
+
| Product | Show a flow or architecture | Page with a diagram | product/ |
|
|
80
|
+
| Product | Prototype a screen | Design | product specs |
|
|
81
|
+
| Money | Show runway, burn, revenue | Dashboard | money/ (from the bank or accounting source in sources.json) |
|
|
82
|
+
| Money | Build a model or budget | File (.xlsx) when asked, else dashboard | money/ and finance/ |
|
|
83
|
+
| Investors | Pitch or investor update | Deck | foundation/, evidence/ (traction) and money/ |
|
|
84
|
+
| Any | Release notes for a release | Document | the release in meta/releases/ |
|
|
85
|
+
|
|
86
|
+
## Checks before you publish
|
|
87
|
+
|
|
88
|
+
- [ ] The artifact names its source records.
|
|
89
|
+
- [ ] No fact appears that is missing from a record. If one is needed, write the record first (as a draft) or mark the claim as a proposal.
|
|
90
|
+
- [ ] Agent-drafted content is marked as a proposal, never as the founder's words.
|
|
91
|
+
- [ ] Input the artifact collects has a path back to records.
|
|
92
|
+
- [ ] Nothing from `_private/`, no secrets, keys or `.env` contents.
|
|
93
|
+
- [ ] Nothing imitates a real person or organization.
|
|
94
|
+
|
|
95
|
+
## In Claude (Claude Code and claude.ai)
|
|
96
|
+
|
|
97
|
+
Claude publishes artifacts with its `Artifact` tool. The kinds above map onto the artifact types on the person's account, which change, so always start a new artifact with `Artifact` `action: "quickstart"` and the fitting `intent`; it names the type to start from and the default design system.
|
|
98
|
+
|
|
99
|
+
| Kind | Claude artifact type | Intent |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| Document | Docs (through the Claude Docs connector) | `document` |
|
|
102
|
+
| Deck | Slides | `slides` |
|
|
103
|
+
| Dashboard | Dashboard | `other` |
|
|
104
|
+
| Design | Design | `design` |
|
|
105
|
+
| Design system | Design System | `other` |
|
|
106
|
+
| Page | plain HTML page, after loading `artifact-design` | `other` |
|
|
107
|
+
| File | the matching file skill (docx, pptx, xlsx, pdf) | none |
|
|
108
|
+
|
|
109
|
+
- **Diagram:** load `artifact-diagramming` when a picture shows the real mechanism.
|
|
110
|
+
- **Charts:** load `dataviz` before drawing any chart; prefer the Dashboard type when the page is mostly data.
|
|
111
|
+
- **Collecting input:** load `artifact-capabilities` and declare the smallest set: `db` and `user` for answers from several people (the docket, an intake form), `artifact` for a page that saves its own versions. Sync what it holds back to records through Naive; never treat the page's store as the record.
|
|
112
|
+
- **Updating:** republish to the same URL when the records change, so the link people hold stays current.
|
|
113
|
+
- Publish privately and give the link. Sharing it further is the founder's call.
|
package/package.json
CHANGED
|
@@ -36,7 +36,7 @@ for (const v of walk(dir)) {
|
|
|
36
36
|
const base = ventureFile(v, pack);
|
|
37
37
|
if (!existsSync(base)) continue;
|
|
38
38
|
for (const name of readdirSync(base)) {
|
|
39
|
-
if (name.startsWith("_") || name.startsWith(".")) continue;
|
|
39
|
+
if (name.startsWith("_") || name.startsWith(".") || name === "README.md" || name === "AGENTS.md") continue;
|
|
40
40
|
const p = join(base, name);
|
|
41
41
|
if (!statSync(p).isFile() || !name.endsWith(".json")) errors.push(`${id}/${pack}/${name}: a master record is <id>.json`);
|
|
42
42
|
}
|
package/schema/init-venture.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import { spawnSync } from "node:child_process";
|
|
|
19
19
|
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
20
20
|
import { dirname, join, relative } from "node:path";
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
|
-
import { ventureFile } from "./venture-paths.mjs";
|
|
22
|
+
import { KBASE, ventureFile } from "./venture-paths.mjs";
|
|
23
23
|
|
|
24
24
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
25
25
|
const repo = join(here, "..");
|
|
@@ -50,13 +50,13 @@ Object.assign(venture, { owner: "self", status: "active", profile: structured ?
|
|
|
50
50
|
// The package folders (EE-070); a typed venture gets its type's packages.
|
|
51
51
|
const packageDirs = vtype ? vtype.packages : ["foundation", "validation", "product", "marketing", "finance", "people", "customers", "investors", "money"];
|
|
52
52
|
if (structured) {
|
|
53
|
-
// venture.json first, so every path below resolves into
|
|
53
|
+
// venture.json first, so every path below resolves into k-base/ and meta/. The org chart starts flat:
|
|
54
54
|
// one function per package, owned by no one until create-venture or the founder names the owner.
|
|
55
55
|
venture.layout = "structured";
|
|
56
56
|
venture.functions = Object.fromEntries(packageDirs.map((p) => [p, { owner: null }]));
|
|
57
|
-
for (const layer of ALL) venture.layers[layer] = on.includes(layer) ? { location:
|
|
57
|
+
for (const layer of ALL) venture.layers[layer] = on.includes(layer) ? { location: `${KBASE}/` } : false;
|
|
58
58
|
writeFileSync(join(dir, "venture.json"), JSON.stringify(venture, null, 2) + "\n");
|
|
59
|
-
for (const sub of [
|
|
59
|
+
for (const sub of [KBASE, "meta"]) mkdirSync(join(dir, sub), { recursive: true });
|
|
60
60
|
}
|
|
61
61
|
for (const layer of structured ? [] : ALL) {
|
|
62
62
|
if (!on.includes(layer)) { if (only !== null || !["governance", "interface"].includes(layer)) venture.layers[layer] = false; continue; }
|
|
@@ -70,6 +70,16 @@ if (!structured) for (const sub of ["products", "accounts"]) { mkdirSync(venture
|
|
|
70
70
|
for (const sub of ["raw/dump", "raw/sources", "ideas", ...packageDirs, "decisions", "evidence", ...(structured ? [] : ["public"]), "_private", "_drafts", ".release"]) {
|
|
71
71
|
mkdirSync(ventureFile(dir, sub), { recursive: true });
|
|
72
72
|
}
|
|
73
|
+
// Every package folder explains itself (EE-086): a README.md from its package, for people. GitHub and
|
|
74
|
+
// editors show it when the folder is opened; an AGENTS.md beside it is the founder's, for agents.
|
|
75
|
+
if (structured) for (const pkg of packageDirs) {
|
|
76
|
+
const f = join(repo, "packages", pkg, "package.json");
|
|
77
|
+
if (!existsSync(f)) continue;
|
|
78
|
+
const p = JSON.parse(readFileSync(f, "utf8"));
|
|
79
|
+
const lines = [`# ${p.title ?? pkg}`, "", p.purpose ?? "", ...(p.required?.length ? ["", `What goes in it first: ${p.required.join(", ")}.`] : []), ...(p.optional?.length ? [`Also: ${p.optional.join(", ")}.`] : []),
|
|
80
|
+
...(p.gates?.length ? ["", `It is ready when ${p.gates.join("; ")}.`] : []), "", `Owner: whoever owns the ${pkg} function in venture.json.`, ""];
|
|
81
|
+
writeFileSync(join(ventureFile(dir, pkg), "README.md"), lines.join("\n"));
|
|
82
|
+
}
|
|
73
83
|
if (!structured) mkdirSync(join(ventureFile(dir, "pillars")), { recursive: true });
|
|
74
84
|
for (const [name, what] of Object.entries(structured ? {} : pillars.stubs)) {
|
|
75
85
|
const guide = relative(join(ventureFile(dir, "pillars")), join(repo, pillars.guides, `${name}.md`));
|
package/schema/port-venture.mjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
//
|
|
8
8
|
// node schema/port-venture.mjs <folder> --venture <dir> [--to <path>] [--links <dir> ...]
|
|
9
9
|
// adds the move to the plan at <venture>/.release/port-plan.json and prints it; moves nothing.
|
|
10
|
-
// The folder goes to <venture>/
|
|
10
|
+
// The folder goes to <venture>/codebase/<its name> unless --to says where (relative to the venture
|
|
11
11
|
// or absolute). Run once per folder: each run adds or replaces that folder's item.
|
|
12
12
|
// node schema/port-venture.mjs --venture <dir> --apply --confirm port [--even-if-busy]
|
|
13
13
|
// carries out every planned move the founder left as move; any item can be set to leave first
|
|
@@ -24,7 +24,7 @@ import { createHash } from "node:crypto";
|
|
|
24
24
|
import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, realpathSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
25
25
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
26
26
|
import { agentFromEnv, record } from "../interface/provenance.mjs";
|
|
27
|
-
import { ventureFile } from "./venture-paths.mjs";
|
|
27
|
+
import { CODEBASE, ventureFile } from "./venture-paths.mjs";
|
|
28
28
|
|
|
29
29
|
export const PLAN = ".release/port-plan.json";
|
|
30
30
|
export const TRACE = ".release/port-trace.json";
|
|
@@ -112,7 +112,7 @@ export function planOne(folder, dir, { to, links = [] } = {}) {
|
|
|
112
112
|
const src = real(folder);
|
|
113
113
|
const v = real(dir);
|
|
114
114
|
if (inside(v, src)) throw new Error("the venture cannot sit inside the folder it ports");
|
|
115
|
-
const dest = resolve(v, to ?? join(
|
|
115
|
+
const dest = resolve(v, to ?? join(CODEBASE, basename(src)));
|
|
116
116
|
const s = statSync(src);
|
|
117
117
|
const item = { action: "move", from: src, to: dest, source: slug(basename(src)), identity: { dev: s.dev, ino: s.ino }, ...measure(src) };
|
|
118
118
|
const warnings = [];
|
package/schema/venture-paths.mjs
CHANGED
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
// structured (venture.json layout: "structured"):
|
|
7
7
|
// venture.json, AGENTS.md, README.md, package.json at the top (profile.md is README.md)
|
|
8
8
|
// provenance.jsonl, sources.json, naive.config.json in meta/; .release/ is meta/releases/
|
|
9
|
-
// every package (foundation/, people/, _drafts/ ...) in
|
|
9
|
+
// every package (foundation/, people/, _drafts/ ...) in k-base/, or in k-base/(group)/ when the
|
|
10
10
|
// founder mirrors a function as a folder
|
|
11
|
+
// code the venture keeps (a marketing site, a ported repository) in codebase/
|
|
12
|
+
// A structured venture made by 0.3.0 has knowledge/ where k-base/ now is; it is read where it is
|
|
13
|
+
// until naive upgrade renames it.
|
|
11
14
|
//
|
|
12
15
|
// `logical` goes the other way, for code that walks the disk and matches files against the data model.
|
|
13
16
|
|
|
@@ -17,6 +20,13 @@ import { join, relative, sep } from "node:path";
|
|
|
17
20
|
const TOP = new Set(["venture.json", "AGENTS.md", "README.md", "package.json", "package-lock.json", ".gitignore"]);
|
|
18
21
|
const META = { "provenance.jsonl": "meta/provenance.jsonl", "knowledge/sources.json": "meta/sources.json", "sources.json": "meta/sources.json", "naive.config.json": "meta/naive.config.json" };
|
|
19
22
|
const cache = new Map();
|
|
23
|
+
export const KBASE = "k-base";
|
|
24
|
+
export const CODEBASE = "codebase";
|
|
25
|
+
|
|
26
|
+
/** The venture's knowledge-base folder: k-base/, or knowledge/ in a structured venture made before it was renamed. */
|
|
27
|
+
export function kbaseOf(dir) {
|
|
28
|
+
return !existsSync(join(dir, KBASE)) && existsSync(join(dir, "knowledge", "foundation")) ? "knowledge" : KBASE;
|
|
29
|
+
}
|
|
20
30
|
|
|
21
31
|
/** The venture's layout: "structured" (EE-086) or "flat". Read once per venture.json change. */
|
|
22
32
|
export function layoutOf(dir) {
|
|
@@ -33,7 +43,7 @@ export function layoutOf(dir) {
|
|
|
33
43
|
|
|
34
44
|
// The (group)/ folder a package sits in, when the founder mirrors functions on disk.
|
|
35
45
|
function groupOf(dir, pkg) {
|
|
36
|
-
const kb = join(dir,
|
|
46
|
+
const kb = join(dir, kbaseOf(dir));
|
|
37
47
|
if (!pkg || existsSync(join(kb, pkg)) || !existsSync(kb)) return null;
|
|
38
48
|
for (const g of readdirSync(kb)) if (/^\(.+\)$/.test(g) && existsSync(join(kb, g, pkg))) return g;
|
|
39
49
|
return null;
|
|
@@ -48,10 +58,11 @@ export function physical(dir, rel) {
|
|
|
48
58
|
if (META[r]) return META[r];
|
|
49
59
|
if (r === ".release" || r.startsWith(".release/")) return "meta/releases" + r.slice(".release".length);
|
|
50
60
|
if (r.startsWith(".naive/") || r === ".naive" || r.startsWith("node_modules") || r.startsWith(".git")) return r;
|
|
51
|
-
|
|
61
|
+
const kb = kbaseOf(dir);
|
|
62
|
+
if (r.startsWith(`${kb}/`) || r === kb || r.startsWith("meta/") || r.startsWith(`${CODEBASE}/`) || r.startsWith("repo/")) return r;
|
|
52
63
|
const pkg = r.split("/")[0];
|
|
53
64
|
const g = groupOf(dir, pkg);
|
|
54
|
-
return
|
|
65
|
+
return `${kb}/${g ? `${g}/` : ""}${r}`;
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
/** The absolute path of a logical path in a venture. */
|
|
@@ -64,7 +75,8 @@ export function logical(dir, rel) {
|
|
|
64
75
|
if (r === "README.md") return "profile.md";
|
|
65
76
|
for (const [l, p] of Object.entries(META)) if (r === p) return l === "sources.json" ? "knowledge/sources.json" : l;
|
|
66
77
|
if (r === "meta/releases" || r.startsWith("meta/releases/")) return ".release" + r.slice("meta/releases".length);
|
|
67
|
-
|
|
78
|
+
const kb = kbaseOf(dir);
|
|
79
|
+
if (r.startsWith(`${kb}/`)) return r.slice(kb.length + 1).replace(/^\([^/]+\)\//, "");
|
|
68
80
|
return r;
|
|
69
81
|
}
|
|
70
82
|
|