Skip to main content
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

  1. Look before you write. Run penumbra shapes for the Shapes of the project and penumbra 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.
  2. Know your credential: penumbra whoami. An editor writes drafts. An owner or an admin publishes. A project API key needs the scope shapes.draft.publish. Its publish waits for approval only if the project’s policy holds shape_change (card rule shape-draft.7).
  3. 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).
  4. 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).
  5. 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

  1. 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; add sources (File ids) and reference_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 and pending first (problem change-waits-for-approval).
  2. For a brief, wait until the draft is open. Run penumbra shapes show <draft-id> until it prints Draft <id>: open and an outline, instead of generating. It takes one to ten minutes, depending on the brief. MCP: shape.read() shows the progress.
    • pull, check, diff and publish on a generating draft stop with draft_generating and exit code 4. This is not an approval. Wait, then try again.
    • Generation stopped; nothing was authored means the run failed. Discard the draft with penumbra shapes drop <draft-id> and start again with a clearer brief or a blank draft.
  3. 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.json in 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 with file_invalid.
  4. Edit the definition in 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.
    • description and telos.purpose: the question, and who asks it.
    • Each type: a description that tells it apart from similar things, and the properties that the answer needs.
    • Each property: a schema whose description says what the value holds. Reading a File relies on it, and on the type’s semantics.extraction_guidance.
    • Each relationship: from_type_ref, to_type_ref and a cardinality.
    • 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.
  5. Push the file: penumbra shapes push <name>.shape.json. MCP: shape.define or shape.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.
  6. 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.property or a relationship) and what is missing. The CLI prints the first five, and penumbra shapes check <draft-id> --json holds all of them.
  7. 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.
  8. 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 and pending. 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.
  9. 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.
  10. 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

  1. penumbra shapes log <name> shows the new version first, with your message.
  2. penumbra shapes show <name> outlines the types that you meant. Each one serves the question, and nothing that the question needs is missing.
  3. The run from step 9 names its Shape, and its items use types of this Shape. You can say which types found items.
  4. 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 improving that 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.

Keep going

Shape · Shape draft · Approval · Extraction · File · Change a Shape and publish it · Check that a File’s text arrived intact · Extract entities from Files · Review a workspace and submit it · A change returned pending · Write better descriptions