plotcoder-board 0.1.7 → 0.1.8
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/package.json
CHANGED
|
@@ -1161,7 +1161,7 @@ server.registerTool(
|
|
|
1161
1161
|
{
|
|
1162
1162
|
title: "Read the wall",
|
|
1163
1163
|
description:
|
|
1164
|
-
"Read the board back: the beats in wall order (rows top to bottom, cards left to right), the pages of scenes between consecutive beats with the cards in each, every setup with the distance to its payoff, and the questions the wall raises — no beat marked yet; a run out of proportion with the others; beats back to back with nothing between them (a chain of them is one question); a card with a placeholder headline or no change line; a card no arrow touches; two headlines that read like the same scene; a group too long to be one sequence; a person in the cast on no card; a person gone for more than a third of the story and ten pages; a payoff before its setup on the wall; a folded card no setup arrow pays off; cards that say no place once any card has one. These are questions, not fixes: put them to the writer and do not act on them unasked. It says nothing about how many beats there should be, and neither should you.",
|
|
1164
|
+
"Read the board back: the beats in wall order (rows top to bottom, cards left to right), the pages of scenes between consecutive beats with the cards in each, every setup with the distance to its payoff, and the questions the wall raises — no beat marked yet; a run out of proportion with the others; beats back to back with nothing between them (a chain of them is one question); a card with a placeholder headline or no change line; a card no arrow touches; two headlines that read like the same scene; a group too long to be one sequence; a person in the cast on no card; a person gone for more than a third of the story and ten pages; a payoff before its setup on the wall; a folded card no setup arrow pays off; cards that say no place once any card has one. These are questions, not fixes: put them to the writer and do not act on them unasked. It says nothing about how many beats there should be, and neither should you. The prose carries every id; the JSON after it is the same reading for a program, and PLOTCODER_JSON=0 in the server's environment drops it.",
|
|
1165
1165
|
inputSchema: {},
|
|
1166
1166
|
},
|
|
1167
1167
|
async () => {
|
|
@@ -1185,12 +1185,12 @@ server.registerTool(
|
|
|
1185
1185
|
.map((group) => {
|
|
1186
1186
|
const members = state.notes.filter((note) => group.noteIds.includes(note.id));
|
|
1187
1187
|
const act = /^act\b/i.test((group.title ?? "").trim());
|
|
1188
|
-
return `"${group.title || "(untitled)"}" — ${members.length} card(s), about ${formatPages(members.reduce((sum, note) => sum + noteEighths(note), 0))} pages${act ? ", read as an act
|
|
1188
|
+
return `"${group.title || "(untitled)"}" — ${members.length} card(s), about ${formatPages(members.reduce((sum, note) => sum + noteEighths(note), 0))} pages${act ? ", read as an act, so its length is not questioned" : ", read as a sequence"}`;
|
|
1189
1189
|
})
|
|
1190
1190
|
.join("; ")
|
|
1191
1191
|
: "(none)"
|
|
1192
1192
|
}`,
|
|
1193
|
-
`pages: ${written === 0 ? "all estimates — no scene is written yet, so every card is the writer's guess" : written === state.notes.length ? "measured — every scene is written" : `estimates — ${written} of ${state.notes.length} cards are written, the rest are guesses`}`,
|
|
1193
|
+
`pages: ${written === 0 ? "all estimates — no scene is written yet, so every card is the writer's guess" : written === state.notes.length ? "measured — every scene is written" : `estimates — ${written} of ${state.notes.length} cards are written${written <= 5 ? ` (${state.notes.filter((note) => isMeasured(note)).map((note) => `"${note.headline}"`).join(", ")})` : ""}, the rest are guesses`}`,
|
|
1194
1194
|
`beats in wall order: ${
|
|
1195
1195
|
reading.beats.length
|
|
1196
1196
|
? reading.beats.map((beat) => `"${beat.headline}"`).join(", ")
|
|
@@ -2628,7 +2628,7 @@ server.registerTool(
|
|
|
2628
2628
|
{
|
|
2629
2629
|
title: "Save the project as a file",
|
|
2630
2630
|
description:
|
|
2631
|
-
"The project the server is working, as the file Save project writes and Open project takes: the record, every board with its cards, the reminders and the writer's structures. Pass path to write it (a .json); without a path, the reply's JSON is the file. Pictures and takes on the account are not in the file. Works through every door.",
|
|
2631
|
+
"The project the server is working, as the file Save project writes and Open project takes: the record, every board with its cards, the reminders and the writer's structures. Pass path to write it (a .json) — an absolute path, since a relative one resolves from the server's own folder, not yours; without a path, the reply's JSON is the file. Pictures and takes on the account are not in the file. Works through every door.",
|
|
2632
2632
|
inputSchema: { path: z.string().optional() },
|
|
2633
2633
|
},
|
|
2634
2634
|
async (args) => {
|
|
@@ -2640,7 +2640,7 @@ server.registerTool(
|
|
|
2640
2640
|
if (args.path) {
|
|
2641
2641
|
fs.mkdirSync(path.dirname(path.resolve(args.path)), { recursive: true });
|
|
2642
2642
|
fs.writeFileSync(args.path, JSON.stringify(file, null, 2));
|
|
2643
|
-
return ok(`Saved ${what}. Written to ${args.path}: Open project in the app takes it, import_project brings it onto an account.`, { path: args.path, boards: project.boards.length, cards });
|
|
2643
|
+
return ok(`Saved ${what}. Written to ${path.resolve(args.path)}: Open project in the app takes it, import_project brings it onto an account.`, { path: path.resolve(args.path), boards: project.boards.length, cards });
|
|
2644
2644
|
}
|
|
2645
2645
|
return ok(`The project as a file — ${what}. The JSON below is the file; write it to a .json for Open project or import_project.`, file);
|
|
2646
2646
|
},
|
package/src/board/agents.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
export const AGENTS = {
|
|
9
9
|
lead:
|
|
10
|
-
"A storyline wall. Cards are scenes, beats are the big turns, arrows say what follows or pays off what. An agent driven by a person has every tool a person here has; the person directs, the agent operates. Call the tools; never fake a mouse.",
|
|
10
|
+
"A storyline wall. Cards are scenes, beats are the big turns, arrows say what follows or pays off what. An agent driven by a person has every tool a person here has; the person directs, the agent operates. Call the tools; never fake a mouse. Already have the plotcoder-board tools in front of you? Skip the doors and go to Call these first.",
|
|
11
11
|
doors: [
|
|
12
12
|
{
|
|
13
13
|
id: "mcp",
|
|
@@ -42,7 +42,7 @@ export const AGENTS = {
|
|
|
42
42
|
text: "Skip this when the account is the wall. Without an account, a wall is a folder: any folder, empty is fine — choose one that will outlive your session, never a scratch one. The app run from that folder shows the wall, and the server writes it there (PLOTCODER_ROOT, or the folder it is run from). A fresh folder holds the sample; new_board for the writer's wall, then rename_project. No app running? export_fountain is the wall in order, as text.",
|
|
43
43
|
},
|
|
44
44
|
],
|
|
45
|
-
firstNote: "These four are about the wall you will work, so after open_project or
|
|
45
|
+
firstNote: "These four are about the wall you will work, so after open_project, open_board, new_project or empty_account, read_wall again. On an account with no project yet, read_wall has nothing to read and says so, and list_reminders gives the house principles every project starts with; new_project, then the four again. No server in front of you, and no shell to take the shell door? Nothing gets you in from inside the session: say so, and ask the person to wire the server and start a new session.",
|
|
46
46
|
first: [
|
|
47
47
|
{ tool: "list_words", why: "the room's words, the app's meaning." },
|
|
48
48
|
{ tool: "read_wall", why: "what is here, and what it asks. A fresh folder holds a sample wall (Maya, Tom, the letter) and says so; it is not the writer's." },
|
|
@@ -64,7 +64,7 @@ export const AGENTS = {
|
|
|
64
64
|
|
|
65
65
|
/** The on-ramp as one text: the file at /llms.txt, and what an agent reads. */
|
|
66
66
|
export function agentsAsText() {
|
|
67
|
-
const lines = ["# PlotCoder — for agents", "", AGENTS.lead, "", `The guide, read once before anything: ${AGENTS.guide}.`, "", "## Doors"];
|
|
67
|
+
const lines = ["# PlotCoder — for agents", "", AGENTS.lead, "", `The guide, read once before anything: ${AGENTS.guide}. The guide is the whole and this page is its first page; where the two differ, the guide wins.`, "", "## Doors"];
|
|
68
68
|
for (const door of AGENTS.doors) {
|
|
69
69
|
lines.push(`- ${door.name}: ${door.text}`);
|
|
70
70
|
if (door.code) lines.push("", "```", door.code, "```", "");
|