@nanopm/cli 0.1.1 → 0.1.3
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/dist/index.js +61 -64
- package/package.json +1 -1
- package/skills/onboard/SKILL.md +2 -2
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Command } from "commander";
|
|
|
5
5
|
|
|
6
6
|
// ../daemon/src/adapters/claude-code/index.ts
|
|
7
7
|
import { execFile, spawn } from "child_process";
|
|
8
|
+
import { randomUUID } from "crypto";
|
|
8
9
|
import { createInterface } from "readline";
|
|
9
10
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
10
11
|
import { join as join3 } from "path";
|
|
@@ -862,22 +863,14 @@ var CHAINED = {
|
|
|
862
863
|
// (`mapping_completion_hook`): the opportunity map follows the market read below, and
|
|
863
864
|
// the founder confirms what the scan proposed on the card while it is drawn.
|
|
864
865
|
//
|
|
865
|
-
//
|
|
866
|
-
//
|
|
867
|
-
//
|
|
868
|
-
//
|
|
869
|
-
//
|
|
870
|
-
//
|
|
871
|
-
// the
|
|
872
|
-
|
|
873
|
-
//
|
|
874
|
-
// It does not close the gap — nothing chained can, while the read itself takes 161s — which
|
|
875
|
-
// is why the mission is asked for on the way in and the vision is drawn as *coming*
|
|
876
|
-
// (docs/nanopm-56-the-required-set.md). This makes that wait honest rather than shorter
|
|
877
|
-
// than it looks.
|
|
878
|
-
// Since 2026-09-30 the direction is queued only when the onboarding left the mission or the
|
|
879
|
-
// vision empty (`WRITTEN_BY_PARENT`): with both written, it had nothing to fill.
|
|
880
|
-
onboard: ["market", "direction"],
|
|
866
|
+
// **The direction crew does not follow an onboarding** (Nicolas, 2026-10-01, docs/ACTIVATION.md
|
|
867
|
+
// row 27). It was queued here, in the background, whenever the read left the mission or the
|
|
868
|
+
// vision empty, and it landed 9 to 24 minutes later — after the market, the map and the
|
|
869
|
+
// solutions — while the card's Direction step, right after the pitch, promised *a few
|
|
870
|
+
// minutes*. Direction now works like the card's other sections: the read writes what the
|
|
871
|
+
// repository states, the card asks the founder for a mission it did not find (`missionAsk`),
|
|
872
|
+
// and the crew runs when the founder asks for it from the business card.
|
|
873
|
+
onboard: ["market"],
|
|
881
874
|
// A problem list is what solutions hang under, so a fresh list is followed by fresh
|
|
882
875
|
// solutions. **The problem crew itself is retired** (docs/nanopm-59-opportunity-map.md,
|
|
883
876
|
// Guillaume, 2026-09-25): the opportunity map replaced it, and nothing queues it any more —
|
|
@@ -890,10 +883,8 @@ var CHAINED = {
|
|
|
890
883
|
// proposes beside a confirmed pitch and never over it (docs/nanopm-52-pitch-crew.md).
|
|
891
884
|
//
|
|
892
885
|
// The direction crew **was** chained here too, for the same reason — a vision rests on who
|
|
893
|
-
// else exists —
|
|
894
|
-
//
|
|
895
|
-
// the onboarding starts only once the market, queued a hair before it, has finished. All
|
|
896
|
-
// it gave up was waiting behind the pitch, which it never read. See the note on `onboard`.
|
|
886
|
+
// else exists — then after `onboard`, and since 2026-10-01 after nothing: see the note on
|
|
887
|
+
// `onboard`.
|
|
897
888
|
//
|
|
898
889
|
// Neither follows a personas run the founder started: they pressed one button, for one
|
|
899
890
|
// crew, with a note meant for it (Guillaume, 2026-09-22). A founder who wants both runs asks
|
|
@@ -947,16 +938,6 @@ var ONLY_AFTER = {
|
|
|
947
938
|
var NEVER_AFTER = {
|
|
948
939
|
market: { pitch: ["onboard"] }
|
|
949
940
|
};
|
|
950
|
-
var WRITTEN_BY_PARENT = {
|
|
951
|
-
onboard: { direction: ["mission", "vision"] }
|
|
952
|
-
};
|
|
953
|
-
function stillOwed(skill, next2, written) {
|
|
954
|
-
const needs2 = WRITTEN_BY_PARENT[skill] ?? {};
|
|
955
|
-
return next2.filter((n) => !needs2[n] || needs2[n].some((topic) => !written.has(topic)));
|
|
956
|
-
}
|
|
957
|
-
var BACKGROUND_EDGES = {
|
|
958
|
-
onboard: ["direction"]
|
|
959
|
-
};
|
|
960
941
|
var AFTER_DEEP = {
|
|
961
942
|
needs: ["opportunities"]
|
|
962
943
|
};
|
|
@@ -3792,7 +3773,26 @@ var ClaudeCodeAdapter = class {
|
|
|
3792
3773
|
else args.push("--session-id", spec.sessionId);
|
|
3793
3774
|
return args;
|
|
3794
3775
|
}
|
|
3776
|
+
/**
|
|
3777
|
+
* One session, and one more when the model asked for is newer than this Claude Code: a
|
|
3778
|
+
* skill names `claude-opus-5-5`, a Claude Code older than 2.1.280 refuses it, and the run
|
|
3779
|
+
* used to end there with no roadmap (activation row 36). The second session asks for the
|
|
3780
|
+
* family alias under a fresh id and says so, so the run works on the Opus the machine has.
|
|
3781
|
+
* Any other failure stays a failure.
|
|
3782
|
+
*/
|
|
3795
3783
|
async *run(spec) {
|
|
3784
|
+
for await (const event of this.runOnce(spec)) {
|
|
3785
|
+
const alias = event.type === "failed" ? olderAlias(spec.model, event.message) : null;
|
|
3786
|
+
if (!alias) {
|
|
3787
|
+
yield event;
|
|
3788
|
+
continue;
|
|
3789
|
+
}
|
|
3790
|
+
yield { type: "text", text: `This Claude Code does not know ${spec.model} yet; using ${alias}. \`claude update\` brings the newer model.` };
|
|
3791
|
+
yield* this.runOnce({ ...spec, model: alias, sessionId: randomUUID(), resumeSessionId: void 0 });
|
|
3792
|
+
return;
|
|
3793
|
+
}
|
|
3794
|
+
}
|
|
3795
|
+
async *runOnce(spec) {
|
|
3796
3796
|
const mcpConfigPath = join3(spec.runDir, "mcp.json");
|
|
3797
3797
|
const mcpServers = Object.fromEntries(
|
|
3798
3798
|
spec.mcp.map((s) => [s.name, { command: s.command, args: s.args, env: s.env }])
|
|
@@ -3839,6 +3839,10 @@ var ClaudeCodeAdapter = class {
|
|
|
3839
3839
|
}
|
|
3840
3840
|
}
|
|
3841
3841
|
};
|
|
3842
|
+
function olderAlias(model, message) {
|
|
3843
|
+
if (!model || !/does not support this model/i.test(message)) return null;
|
|
3844
|
+
return ["opus", "sonnet", "haiku"].find((family) => model.includes(family) && model !== family) ?? null;
|
|
3845
|
+
}
|
|
3842
3846
|
function appendExit(message, code) {
|
|
3843
3847
|
return code === null || code === 0 ? message : `${message} (exit ${code})`;
|
|
3844
3848
|
}
|
|
@@ -5200,7 +5204,7 @@ async function clonelessSkills(skillsDir = findSkillsDir()) {
|
|
|
5200
5204
|
}
|
|
5201
5205
|
|
|
5202
5206
|
// ../daemon/src/problem-mapping-harness.ts
|
|
5203
|
-
import { randomUUID } from "crypto";
|
|
5207
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
5204
5208
|
function mappingHarnessRunner(options) {
|
|
5205
5209
|
return async (input) => {
|
|
5206
5210
|
const skill = await loadSkill(`problem-${input.role}`);
|
|
@@ -5209,7 +5213,7 @@ function mappingHarnessRunner(options) {
|
|
|
5209
5213
|
for await (const event of options.adapter.run({
|
|
5210
5214
|
cwd: options.runDir,
|
|
5211
5215
|
runDir: options.runDir,
|
|
5212
|
-
sessionId:
|
|
5216
|
+
sessionId: randomUUID2(),
|
|
5213
5217
|
systemPrompt: `${skill.body}
|
|
5214
5218
|
|
|
5215
5219
|
Output schema:
|
|
@@ -5500,7 +5504,7 @@ function mappingUsage(checkpoints) {
|
|
|
5500
5504
|
}
|
|
5501
5505
|
|
|
5502
5506
|
// ../daemon/src/persona-job.ts
|
|
5503
|
-
import { randomUUID as
|
|
5507
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
5504
5508
|
|
|
5505
5509
|
// ../daemon/src/crew-retry.ts
|
|
5506
5510
|
async function askAgainIfUnanswered(attempt7, say, role7) {
|
|
@@ -5813,7 +5817,7 @@ async function attempt({
|
|
|
5813
5817
|
await onEvent({ type: "text", text: say });
|
|
5814
5818
|
for await (const event of adapter.run({
|
|
5815
5819
|
...spec,
|
|
5816
|
-
sessionId:
|
|
5820
|
+
sessionId: randomUUID3(),
|
|
5817
5821
|
resumeSessionId: void 0,
|
|
5818
5822
|
capabilities: [],
|
|
5819
5823
|
mcp: [],
|
|
@@ -6034,7 +6038,7 @@ async function collect2(client, projectId, cwd, replace) {
|
|
|
6034
6038
|
}
|
|
6035
6039
|
|
|
6036
6040
|
// ../daemon/src/direction-job.ts
|
|
6037
|
-
import { randomUUID as
|
|
6041
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
6038
6042
|
|
|
6039
6043
|
// ../daemon/src/crew-no-downgrade.ts
|
|
6040
6044
|
function keepsTheLine(job, live, confidence) {
|
|
@@ -6229,7 +6233,7 @@ ${renderTests()}` : skill.body;
|
|
|
6229
6233
|
await onEvent({ type: "text", text: say });
|
|
6230
6234
|
for await (const event of adapter.run({
|
|
6231
6235
|
...spec,
|
|
6232
|
-
sessionId:
|
|
6236
|
+
sessionId: randomUUID4(),
|
|
6233
6237
|
resumeSessionId: void 0,
|
|
6234
6238
|
capabilities: [],
|
|
6235
6239
|
mcp: [],
|
|
@@ -6358,7 +6362,7 @@ async function collect3(client, projectId) {
|
|
|
6358
6362
|
}
|
|
6359
6363
|
|
|
6360
6364
|
// ../daemon/src/pitch-job.ts
|
|
6361
|
-
import { randomUUID as
|
|
6365
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
6362
6366
|
async function runPitchJob({ client, job, adapter, spec, onEvent }) {
|
|
6363
6367
|
if (!job.project_id) throw new Error("A pitch needs a project.");
|
|
6364
6368
|
const projectId = job.project_id;
|
|
@@ -6463,7 +6467,7 @@ async function attempt3({
|
|
|
6463
6467
|
await onEvent({ type: "text", text: say });
|
|
6464
6468
|
for await (const event of adapter.run({
|
|
6465
6469
|
...spec,
|
|
6466
|
-
sessionId:
|
|
6470
|
+
sessionId: randomUUID5(),
|
|
6467
6471
|
resumeSessionId: void 0,
|
|
6468
6472
|
capabilities: [],
|
|
6469
6473
|
mcp: [],
|
|
@@ -6575,7 +6579,7 @@ async function collect4(client, projectId) {
|
|
|
6575
6579
|
}
|
|
6576
6580
|
|
|
6577
6581
|
// ../daemon/src/market-job.ts
|
|
6578
|
-
import { randomUUID as
|
|
6582
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
6579
6583
|
|
|
6580
6584
|
// ../daemon/src/web-journal.ts
|
|
6581
6585
|
var HARNESS_WEB_TOOLS = ["WebSearch", "WebFetch"];
|
|
@@ -6816,7 +6820,7 @@ async function attempt4({ adapter, spec, onEvent, role: which, prompt, say }) {
|
|
|
6816
6820
|
await onEvent({ type: "text", text: say });
|
|
6817
6821
|
for await (const event of adapter.run({
|
|
6818
6822
|
...spec,
|
|
6819
|
-
sessionId:
|
|
6823
|
+
sessionId: randomUUID6(),
|
|
6820
6824
|
resumeSessionId: void 0,
|
|
6821
6825
|
capabilities,
|
|
6822
6826
|
mcp: which === "scout" ? spec.mcp : [],
|
|
@@ -6899,7 +6903,7 @@ async function collect5(client, projectId, ask6) {
|
|
|
6899
6903
|
}
|
|
6900
6904
|
|
|
6901
6905
|
// ../daemon/src/needs-job.ts
|
|
6902
|
-
import { randomUUID as
|
|
6906
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
6903
6907
|
var SIGNALS_MAX = 40;
|
|
6904
6908
|
var SIGNAL_CHARS = 3e3;
|
|
6905
6909
|
async function runNeedsJob({ client, job, adapter, spec, onEvent }) {
|
|
@@ -7478,7 +7482,7 @@ async function attempt5({ adapter, spec, onEvent, role: which, schema: shape2, t
|
|
|
7478
7482
|
await onEvent({ type: "text", text: say });
|
|
7479
7483
|
for await (const event of adapter.run({
|
|
7480
7484
|
...spec,
|
|
7481
|
-
sessionId:
|
|
7485
|
+
sessionId: randomUUID7(),
|
|
7482
7486
|
resumeSessionId: void 0,
|
|
7483
7487
|
capabilities: granted,
|
|
7484
7488
|
mcp: granted.length ? spec.mcp : [],
|
|
@@ -7700,7 +7704,7 @@ function opportunitiesOutputSchema(which) {
|
|
|
7700
7704
|
}
|
|
7701
7705
|
|
|
7702
7706
|
// ../daemon/src/crew.ts
|
|
7703
|
-
import { randomUUID as
|
|
7707
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
7704
7708
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
7705
7709
|
import { join as join7 } from "path";
|
|
7706
7710
|
var READ_ONLY = {
|
|
@@ -7727,7 +7731,7 @@ async function attempt6({ adapter, spec, onEvent, skill: skillName, name, schema
|
|
|
7727
7731
|
// A role that may not read the code does not stand in it (docs/nanopm-71-deep-dive-lenses.md).
|
|
7728
7732
|
cwd: grant.includes("read_repo") ? spec.cwd : runDir,
|
|
7729
7733
|
runDir,
|
|
7730
|
-
sessionId:
|
|
7734
|
+
sessionId: randomUUID8(),
|
|
7731
7735
|
resumeSessionId: void 0,
|
|
7732
7736
|
capabilities: [...grant],
|
|
7733
7737
|
mcp: grant.includes("read_data") ? spec.mcp : [],
|
|
@@ -9229,7 +9233,7 @@ async function readRoadmap(client, projectId) {
|
|
|
9229
9233
|
}
|
|
9230
9234
|
|
|
9231
9235
|
// ../daemon/src/reword-job.ts
|
|
9232
|
-
import { randomUUID as
|
|
9236
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
9233
9237
|
async function runRewordJob({ client, job, adapter, spec, onEvent }) {
|
|
9234
9238
|
if (!job.project_id) throw new Error("A rewrite needs a project.");
|
|
9235
9239
|
const asked = RewordParams.safeParse(job.params);
|
|
@@ -9291,7 +9295,7 @@ async function session({ adapter, spec, onEvent, prompt }) {
|
|
|
9291
9295
|
let usage;
|
|
9292
9296
|
for await (const event of adapter.run({
|
|
9293
9297
|
...spec,
|
|
9294
|
-
sessionId:
|
|
9298
|
+
sessionId: randomUUID9(),
|
|
9295
9299
|
resumeSessionId: void 0,
|
|
9296
9300
|
capabilities: [],
|
|
9297
9301
|
mcp: [],
|
|
@@ -9326,7 +9330,7 @@ ${body}
|
|
|
9326
9330
|
}
|
|
9327
9331
|
|
|
9328
9332
|
// ../daemon/src/talk-job.ts
|
|
9329
|
-
import { randomUUID as
|
|
9333
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
9330
9334
|
var ALLOWED = /* @__PURE__ */ new Set([...TALK_TOOLS.map((t) => `mcp__nanopm__${t}`), "StructuredOutput"]);
|
|
9331
9335
|
async function runTalkJob({ client, job, adapter, spec, onEvent }) {
|
|
9332
9336
|
if (!job.project_id) throw new Error("A conversation needs a project.");
|
|
@@ -9358,7 +9362,7 @@ async function runTalkJob({ client, job, adapter, spec, onEvent }) {
|
|
|
9358
9362
|
let usage;
|
|
9359
9363
|
for await (const event of adapter.run({
|
|
9360
9364
|
...spec,
|
|
9361
|
-
sessionId:
|
|
9365
|
+
sessionId: randomUUID10(),
|
|
9362
9366
|
resumeSessionId: void 0,
|
|
9363
9367
|
capabilities: skill.manifest.capabilities,
|
|
9364
9368
|
harnessWeb: false,
|
|
@@ -9395,7 +9399,7 @@ var told = (r) => ({
|
|
|
9395
9399
|
|
|
9396
9400
|
// ../daemon/src/objective-definitions.ts
|
|
9397
9401
|
import { execFile as execFile4 } from "child_process";
|
|
9398
|
-
import { randomUUID as
|
|
9402
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
9399
9403
|
import { existsSync as existsSync2 } from "fs";
|
|
9400
9404
|
import { mkdir as mkdir3, readFile as readFile5 } from "fs/promises";
|
|
9401
9405
|
import { join as join8 } from "path";
|
|
@@ -9571,7 +9575,7 @@ async function readDefinitions({ adapter, spec, publish: publish5, journal, hasR
|
|
|
9571
9575
|
for await (const event of adapter.run({
|
|
9572
9576
|
...spec,
|
|
9573
9577
|
runDir,
|
|
9574
|
-
sessionId:
|
|
9578
|
+
sessionId: randomUUID11(),
|
|
9575
9579
|
resumeSessionId: void 0,
|
|
9576
9580
|
capabilities: ["read_repo"],
|
|
9577
9581
|
// No Glob: it read the folder at 15 s a search (Guillaume's suggestions took 75 s,
|
|
@@ -9895,7 +9899,7 @@ function localDate(timezone, at) {
|
|
|
9895
9899
|
}
|
|
9896
9900
|
|
|
9897
9901
|
// ../daemon/src/run-job.ts
|
|
9898
|
-
import { randomUUID as
|
|
9902
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
9899
9903
|
import { existsSync as existsSync3 } from "fs";
|
|
9900
9904
|
import { mkdir as mkdir4, readFile as readFile6, rm as rm2 } from "fs/promises";
|
|
9901
9905
|
import { homedir as homedir2, tmpdir } from "os";
|
|
@@ -10340,7 +10344,7 @@ async function execute(job, skill, ctx, events) {
|
|
|
10340
10344
|
const runDir = join9(nanopmHome(), "run", job.id);
|
|
10341
10345
|
await mkdir4(runDir, { recursive: true, mode: 448 });
|
|
10342
10346
|
const resumeSessionId = job.resume_of ? await sessionOf(ctx.client, job.resume_of) : void 0;
|
|
10343
|
-
const sessionId = resumeSessionId ??
|
|
10347
|
+
const sessionId = resumeSessionId ?? randomUUID12();
|
|
10344
10348
|
await ctx.client.from("jobs").update({ harness_session_id: sessionId }).eq("id", job.id);
|
|
10345
10349
|
const adapter = ctx.adapter ?? new ClaudeCodeAdapter();
|
|
10346
10350
|
const [project, searchProvider] = job.project_id ? await Promise.all([loadProject(ctx.client, job.project_id), loadSearchProvider(ctx.client, job.project_id)]) : [null, null];
|
|
@@ -10932,12 +10936,6 @@ async function runDaemon(options = {}) {
|
|
|
10932
10936
|
}
|
|
10933
10937
|
return { daemonId, processed };
|
|
10934
10938
|
}
|
|
10935
|
-
async function topicsWritten(auth, projectId, skill) {
|
|
10936
|
-
const topics = [...new Set(Object.values(WRITTEN_BY_PARENT[skill] ?? {}).flat())];
|
|
10937
|
-
if (!topics.length) return /* @__PURE__ */ new Set();
|
|
10938
|
-
const { data } = await auth.client.from("memory").select("topic").eq("project_id", projectId).in("topic", topics).is("superseded_by", null);
|
|
10939
|
-
return new Set((data ?? []).map((r) => r.topic));
|
|
10940
|
-
}
|
|
10941
10939
|
async function chainAfter(auth, job, outcome, log) {
|
|
10942
10940
|
if (NOT_CHAINED_BY_DAEMON.includes(job.skill)) return;
|
|
10943
10941
|
if (job.params?.chain === false) return;
|
|
@@ -10945,14 +10943,13 @@ async function chainAfter(auth, job, outcome, log) {
|
|
|
10945
10943
|
const parent = job.parent_job_id ? await parentOf(auth, job.parent_job_id) : null;
|
|
10946
10944
|
const own = job.params ?? {};
|
|
10947
10945
|
const deep = own.depth === "deep" && job.trigger === "hook";
|
|
10948
|
-
const next2 =
|
|
10946
|
+
const next2 = daemonQueues(job.skill, 0, parent?.skill ?? null, deep);
|
|
10949
10947
|
if (!next2.length) return;
|
|
10950
10948
|
if (await chainDepth(auth, job) >= CHAIN_DEPTH_MAX) return;
|
|
10951
10949
|
const from = deep ? own.repo_path : parent?.params?.repo_path;
|
|
10952
10950
|
const repo = typeof from === "string" ? { repo_path: from } : null;
|
|
10953
10951
|
for (const skill of next2) {
|
|
10954
|
-
const
|
|
10955
|
-
const params = { ...repo ?? {}, ...deep ? { depth: "deep" } : {}, ...background ? { background: true } : {} };
|
|
10952
|
+
const params = { ...repo ?? {}, ...deep ? { depth: "deep", background: true } : {} };
|
|
10956
10953
|
const { data, error } = await auth.client.from("jobs").insert({
|
|
10957
10954
|
project_id: job.project_id,
|
|
10958
10955
|
skill,
|
|
@@ -11247,7 +11244,7 @@ function contextFromEnv(env = process.env) {
|
|
|
11247
11244
|
|
|
11248
11245
|
// ../memory-mcp/src/server.ts
|
|
11249
11246
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11250
|
-
import { randomUUID as
|
|
11247
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
11251
11248
|
import { setTimeout as sleep2 } from "timers/promises";
|
|
11252
11249
|
import { z as z20 } from "zod";
|
|
11253
11250
|
|
|
@@ -13090,7 +13087,7 @@ async function talkAct(ctx, roundOf, proposed, asked, why) {
|
|
|
13090
13087
|
const [round2, world] = await Promise.all([roundOf, talkWorld(ctx.client, ctx.projectId)]);
|
|
13091
13088
|
const ref = change.kind === "add" ? change.parent : change.kind === "add_solution" ? change.leaf : change.ref;
|
|
13092
13089
|
const target = ref ? currentRow(world, ref)?.ref ?? currentSolution(world, ref)?.ref ?? ref : void 0;
|
|
13093
|
-
const base = { id:
|
|
13090
|
+
const base = { id: randomUUID13(), change, ...movesDown(change, world) ? { down: true } : {}, ...change.kind === "brainstorm" ? { cost: runCost(change.depth) } : {} };
|
|
13094
13091
|
let action;
|
|
13095
13092
|
if (!askedIn(asked, round2.words)) {
|
|
13096
13093
|
action = { ...base, state: "suggested", line: talkLine(change, world, false), ...target ? { target } : {} };
|
|
@@ -13885,7 +13882,7 @@ import { promisify as promisify7 } from "util";
|
|
|
13885
13882
|
// package.json
|
|
13886
13883
|
var package_default = {
|
|
13887
13884
|
name: "@nanopm/cli",
|
|
13888
|
-
version: "0.1.
|
|
13885
|
+
version: "0.1.3",
|
|
13889
13886
|
description: "An autonomous product manager for builders who run several small products. Runs on your machine, drives your own coding harness.",
|
|
13890
13887
|
type: "module",
|
|
13891
13888
|
license: "MIT",
|
package/package.json
CHANGED
package/skills/onboard/SKILL.md
CHANGED
|
@@ -171,8 +171,8 @@ product is.
|
|
|
171
171
|
code does is the pitch with a wider adjective, and it is exactly the row this rule exists
|
|
172
172
|
to stop (docs/nanopm-53-direction.md §3). If the product's own words do not say where the
|
|
173
173
|
company is going, write nothing under these two topics and say so in your final log: the
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
card asks the founder for the mission in their own words, and the business card drafts a
|
|
175
|
+
mission and a vision with them when they ask. Do not write a gap for it: the card asks.
|
|
176
176
|
Only when the repo states a stance in words (a README that says "maintenance mode",
|
|
177
177
|
a roadmap that says "growth"), call set_preferences with `stance_provenance:
|
|
178
178
|
"inferred"`; otherwise do not call it at all. The stance is `grow` until someone says
|