Guide · shapes
Use when
A person wants a Shape for a domain, and no Shape in the project or in the public library fits.
Looking for something else?
A change to a Shape the project has (recipe change-a-shape). A public Shape you adopt as it is (card Shape). Extracting with a Shape that exists (recipe extract-files).
Outcome
The project has a new Shape that the person’s question shaped. Its first version has a message. One extraction from one File ran with it, so the person and you can see which types the Shape finds in real text. Nothing is in the Graph yet.Before you start
-
Look before you write. Run
penumbra shapesfor the Shapes of the project andpenumbra shapes library "<words>"for the public ones. If a public Shape fits, adopt it (card rule shape.7). If a Shape of the project nearly fits, change it (recipe change-a-shape). Create a new Shape only when neither fits. -
Know your credential:
penumbra whoami. An editor writes drafts. An owner or an admin publishes. A project API key needs the scopeshapes.draft.publish. Its publish waits for approval only if the project’s policy holdsshape_change(card rule shape-draft.7). - Ask what the Shape is for. A Shape is an expert’s lens on the person’s Files. It names the kinds of things that the expert looks for, what each one means, and how they connect. Write down the question that the expert asks of these Files, in one sentence. Each type must serve that question. Penumbra does not choose the types for you (card shape).
-
Choose how to start. Use one of these three.
Prefer a brief when you can describe the domain. You then edit a draft, and you do not write one from nothing. To change a Shape the project has, use
penumbra shapes edit <shape>(recipe change-a-shape). -
For a brief, choose what else the draft reads. The brief always says what
the Shape is for. It holds at most 4,096 characters. To read a longer brief
from a file, use
--brief-from <path>, or--brief-from -for stdin.A<file>is a Workspace path, a File id or a name. Together the Files can be 64 at most, with at most 2 MiB of text. The draft fits the Files that you give, so state the general purpose in the brief when the Shape must serve more than these Files.
Steps
-
Start the draft with the command that you chose in step 4. MCP, in
execute:penumbra.shapes.open({ name })with a name that no Shape has starts a new Shape.penumbra.shapes.generate({ brief, name })starts from a brief; addsources(File ids) andreference_shapes(Shape names or ids) for step 5.penumbra.shapes.copy({ from, name })starts from a Shape in use.- Expect, for a blank draft or a fork:
Draft <id> is open at revision 1. Keep the draft id. - Expect, for a brief:
Draft <id> started: generating (queued). A key or a connected agent gets exit code 4 andpendingfirst (problem change-waits-for-approval).
- Expect, for a blank draft or a fork:
-
For a brief, wait until the draft is open. Run
penumbra shapes show <draft-id>until it printsDraft <id>: openand an outline, instead ofgenerating. It takes one to ten minutes, depending on the brief. MCP:shape.read()shows the progress.pull,check,diffandpublishon a generating draft stop withdraft_generatingand exit code 4. This is not an approval. Wait, then try again.Generation stopped; nothing was authoredmeans the run failed. Discard the draft withpenumbra shapes drop <draft-id>and start again with a clearer brief or a blank draft.
-
Pull the definition file:
penumbra shapes pull <draft-id>. MCP:shape.read({ part: "model" }).- Expect:
Wrote <path> from draft <id> at revision <n>.The default file is<name>.shape.jsonin the current directory. - Edit this file. Do not edit a saved published artifact or the output of
penumbra shapes library show. Both carry IDs and digests, and a push refuses them withfile_invalid.
- Expect:
-
Edit the
definitionin the file. Write it from the question of step 3. Use recipe write-better-descriptions to clarify the meanings and keep them consistent across the Shape.descriptionandtelos.purpose: the question, and who asks it.- Each type: a
descriptionthat tells it apart from similar things, and the properties that the answer needs. - Each property: a
schemawhosedescriptionsays what the value holds. Reading a File relies on it, and on the type’ssemantics.extraction_guidance. - Each relationship:
from_type_ref,to_type_refand acardinality. - Keep the source field and every
*_ref. The source field makes the next push go to the same draft (card rule shape-draft.3).
MCP:shape.define({ name, description, telos, types, relationships })sets the whole model. It saves each part that it can, and returns what to fix for each part that it cannot. -
Push the file:
penumbra shapes push <name>.shape.json. MCP:shape.defineorshape.modify.- Expect:
Synced draft <id> to <file>: revision <n>and<file> now follows draft <id> at revision <n>.Exit code 0. - If the push prints
Some of <file> could not be saved, read each line- <declaration>: not saved.and its message. Fix those parts and push again. What was saved stays.
- Expect:
-
Check the draft:
penumbra shapes check <draft-id>. MCP:shape.validate().- Expect:
Draft <id> is valid at revision <n>and exit code 0. Otherwise it exits with code 3 and lists diagnostics. Fix them, push and check again (card rule shape-draft.4). - A valid draft can still print
Worth improving (N gaps; advice only…). Each line names a target (the Shape, a type,type.propertyor a relationship) and what is missing. The CLI prints the first five, andpenumbra shapes check <draft-id> --jsonholds all of them.
- Expect:
-
Fix the gaps that the person’s question needs, such as a type without a
description. Push and check again. Say which gaps you left, and why. Advice never blocks a save. -
Publish with a message:
penumbra shapes publish <draft-id> -m "<what the Shape is for>". MCP:shape.submit({ note }).- Expect, for a person’s own session:
Published version <n> of Shape <id>.and exit code 0. - If the policy holds
shape_change, a key or a connected agent gets exit code 4 andpending. Give the person the approval URL and follow the handle (problem change-waits-for-approval). Nothing is published until it is approved. - A publish adds the Shape to the project. Do not run
penumbra shapes add: it adopts public Shapes only.
- Expect, for a person’s own session:
- Try the Shape on one File. Pick a File that states what the question asks about. Check its text (recipe check-file-text). Then follow recipe extract-files with that one File and the new Shape. The plan is free. The run is paid, so give the person the cost range and wait for a clear yes.
-
Read the items in the workspace that the run opened:
penumbra graph workspace show "<workspace>". Compare them with the question of step 3. Name the types that found items and the types that found none.- If a type is missing, a property is empty or the items miss the point, change the Shape (recipe change-a-shape). Then run again on the same File.
- Submit the review only if the person wants these entities in the Graph (recipe review-and-submit).
Check
penumbra shapes log <name>shows the new version first, with your message.penumbra shapes show <name>outlines the types that you meant. Each one serves the question, and nothing that the question needs is missing.- The run from step 9 names its Shape, and its items use types of this Shape. You can say which types found items.
- You told the person that nothing is in the Graph until a submit is approved (card rule workspace.2).
If it goes wrong
Worth offering
- Offer to extract the rest of the Files, or a collection, when the first run reads well (recipe extract-files).
- Offer to change the Shape when the first run shows a missing type or an empty property (recipe change-a-shape).
Report
Tell the person:- The name of the Shape, its version and your message.
- How you started it (brief, blank or fork). For a brief, say that it spent credits, and name the Files and Shapes that it read.
- The question that the Shape answers, in the person’s words.
- The gaps in
Worth improvingthat you left, and why. - The File you tried, the cost of the run, and which types found items.
- That nothing is in the Graph until a submit is approved, and who must approve it.