@flowriki/agent 0.1.0-beta.50 → 0.1.0-beta.52
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.
|
@@ -17,7 +17,7 @@ import path3 from "path";
|
|
|
17
17
|
import fs4 from "fs";
|
|
18
18
|
import path4 from "path";
|
|
19
19
|
|
|
20
|
-
// ../test-model/dist/chunk-
|
|
20
|
+
// ../test-model/dist/chunk-I5COYCQ5.js
|
|
21
21
|
import { z as z2 } from "zod";
|
|
22
22
|
import { z } from "zod";
|
|
23
23
|
var PLATFORMS = ["web", "android", "ios"];
|
|
@@ -86,8 +86,8 @@ var DeviceChoiceSchema = z.discriminatedUnion("kind", [
|
|
|
86
86
|
}).strict()
|
|
87
87
|
]);
|
|
88
88
|
var MobileConfigSchema = z.object({
|
|
89
|
-
android: AndroidAppSchema.optional(),
|
|
90
|
-
ios: IosAppSchema.optional(),
|
|
89
|
+
android: AndroidAppSchema.partial({ appPackage: true }).optional(),
|
|
90
|
+
ios: IosAppSchema.partial({ bundleId: true }).optional(),
|
|
91
91
|
/** Between runs: keep the app's data (stays signed in), or start clean. */
|
|
92
92
|
reset: z.enum(["keepData", "fresh"]).default("keepData"),
|
|
93
93
|
/** Where runs go when nobody says — absent means whatever is available. */
|
|
@@ -98,6 +98,10 @@ var mobileOf = (config) => {
|
|
|
98
98
|
const parsed = MobileConfigSchema.safeParse(config?.mobile ?? {});
|
|
99
99
|
return parsed.success ? parsed.data : MobileConfigSchema.parse({});
|
|
100
100
|
};
|
|
101
|
+
var EnvironmentAppsSchema = z.object({
|
|
102
|
+
android: AndroidAppSchema.optional(),
|
|
103
|
+
ios: IosAppSchema.optional()
|
|
104
|
+
});
|
|
101
105
|
var DeviceInfoSchema = z.object({
|
|
102
106
|
id: z.string(),
|
|
103
107
|
name: z.string(),
|
|
@@ -1684,6 +1688,14 @@ var BugSchema = z7.object({
|
|
|
1684
1688
|
updatedAt: z7.string()
|
|
1685
1689
|
}).strict();
|
|
1686
1690
|
var STOP = new Set("a an the and or of to in on for with by is are be as at it this that from user users can should must shall will when then given".split(" "));
|
|
1691
|
+
function exploreSummary(markdown) {
|
|
1692
|
+
const screens = /^Screens:\s*(\d+)\s*$/im.exec(markdown)?.[1];
|
|
1693
|
+
return {
|
|
1694
|
+
exploredAt: /^Explored:\s*(\S+)\s*$/im.exec(markdown)?.[1] ?? null,
|
|
1695
|
+
environment: /^Environment:\s*(.+?)\s*$/im.exec(markdown)?.[1] ?? null,
|
|
1696
|
+
screens: screens ? Number(screens) : null
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1687
1699
|
var CODEBASE_TAGS = ["all", "web", "android", "ios", "mobile", "other"];
|
|
1688
1700
|
var CODEBASE_TAG_NAME = { all: "All combined", web: "Web", android: "Android", ios: "iOS", mobile: "Mobile", other: "Other" };
|
|
1689
1701
|
var CodebaseIndexSchema = z8.object({
|
|
@@ -2518,11 +2530,11 @@ var CLOUD_HUBS = {
|
|
|
2518
2530
|
function appOf(target) {
|
|
2519
2531
|
if (target.platform === "android") {
|
|
2520
2532
|
const app2 = target.mobile.android;
|
|
2521
|
-
if (!app2) throw new Error("This
|
|
2533
|
+
if (!app2?.appPackage) throw new Error("This environment has not named its Android app \u2014 add its package in Settings \u2192 Environments.");
|
|
2522
2534
|
return { id: app2.appPackage, ...app2.appActivity ? { activity: app2.appActivity } : {}, ...app2.build ? { build: app2.build } : {} };
|
|
2523
2535
|
}
|
|
2524
2536
|
const app = target.mobile.ios;
|
|
2525
|
-
if (!app) throw new Error("This
|
|
2537
|
+
if (!app?.bundleId) throw new Error("This environment has not named its iOS app \u2014 add its bundle ID in Settings \u2192 Environments.");
|
|
2526
2538
|
return { id: app.bundleId, ...app.build ? { build: app.build } : {} };
|
|
2527
2539
|
}
|
|
2528
2540
|
async function localBuild(build) {
|
|
@@ -4053,6 +4065,8 @@ export {
|
|
|
4053
4065
|
isMobile,
|
|
4054
4066
|
stepRefusedOn,
|
|
4055
4067
|
platformsOf,
|
|
4068
|
+
AndroidAppSchema,
|
|
4069
|
+
IosAppSchema,
|
|
4056
4070
|
CLOUD_PROVIDERS,
|
|
4057
4071
|
CLOUD_PROVIDER_NAME,
|
|
4058
4072
|
DeviceChoiceSchema,
|
|
@@ -4086,6 +4100,7 @@ export {
|
|
|
4086
4100
|
PrerequisiteProblem,
|
|
4087
4101
|
expandForRun,
|
|
4088
4102
|
DeliveredHelperSchema,
|
|
4103
|
+
exploreSummary,
|
|
4089
4104
|
CODEBASE_TAG_NAME,
|
|
4090
4105
|
codebaseIndexOf,
|
|
4091
4106
|
runWhereOf,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
AndroidAppSchema,
|
|
3
4
|
ArtifactPolicySchema,
|
|
4
5
|
AuthReferenceSchema,
|
|
5
6
|
CHECKS,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
ExecutionEnvironmentSchema,
|
|
14
15
|
FeatureSchema,
|
|
15
16
|
FlowDocumentSchema,
|
|
17
|
+
IosAppSchema,
|
|
16
18
|
MobileLane,
|
|
17
19
|
PrerequisiteProblem,
|
|
18
20
|
RecordedAssertionSchema,
|
|
@@ -65,7 +67,7 @@ import {
|
|
|
65
67
|
textIndependent,
|
|
66
68
|
validateActors,
|
|
67
69
|
webCloudOf
|
|
68
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-KDW65RBE.js";
|
|
69
71
|
|
|
70
72
|
// src/engine/machine.ts
|
|
71
73
|
import fs from "fs";
|
|
@@ -73,7 +75,7 @@ import os from "os";
|
|
|
73
75
|
import path from "path";
|
|
74
76
|
import { createRequire } from "module";
|
|
75
77
|
import { spawnSync } from "child_process";
|
|
76
|
-
var AGENT_VERSION = "0.1.0-beta.
|
|
78
|
+
var AGENT_VERSION = "0.1.0-beta.52";
|
|
77
79
|
async function prepareBrowsers() {
|
|
78
80
|
if (browsersReady()) {
|
|
79
81
|
return { ok: true, already: true, message: "chromium is already installed" };
|
|
@@ -133,7 +135,7 @@ async function checkMachine() {
|
|
|
133
135
|
}
|
|
134
136
|
} catch {
|
|
135
137
|
}
|
|
136
|
-
const { mobileDoctor: mobileDoctor2 } = await import("./dist-
|
|
138
|
+
const { mobileDoctor: mobileDoctor2 } = await import("./dist-R2I4D66B.js");
|
|
137
139
|
return {
|
|
138
140
|
agentVersion: AGENT_VERSION,
|
|
139
141
|
node: process.versions.node,
|
|
@@ -6157,7 +6159,7 @@ function toSummary(row) {
|
|
|
6157
6159
|
};
|
|
6158
6160
|
}
|
|
6159
6161
|
|
|
6160
|
-
// ../repository-store/dist/chunk-
|
|
6162
|
+
// ../repository-store/dist/chunk-QF7BTHZB.js
|
|
6161
6163
|
var FLOWRIKI_DIR = ".flowriki";
|
|
6162
6164
|
var FEATURES_DIR = `${FLOWRIKI_DIR}/features`;
|
|
6163
6165
|
var CONFIG_PATH = `${FLOWRIKI_DIR}/config.json`;
|
|
@@ -6219,12 +6221,18 @@ function readEnvironments(raw) {
|
|
|
6219
6221
|
const seen = /* @__PURE__ */ new Set();
|
|
6220
6222
|
for (const entry of raw) {
|
|
6221
6223
|
if (!entry || typeof entry !== "object") continue;
|
|
6222
|
-
const { name, baseUrl } = entry;
|
|
6224
|
+
const { name, baseUrl, android, ios } = entry;
|
|
6223
6225
|
if (typeof name !== "string" || !name.trim()) continue;
|
|
6224
6226
|
const key = name.trim().toLowerCase();
|
|
6225
6227
|
if (seen.has(key)) continue;
|
|
6226
6228
|
seen.add(key);
|
|
6227
|
-
|
|
6229
|
+
const app = { android: AndroidAppSchema.safeParse(android), ios: IosAppSchema.safeParse(ios) };
|
|
6230
|
+
out.push({
|
|
6231
|
+
name: name.trim(),
|
|
6232
|
+
baseUrl: typeof baseUrl === "string" ? baseUrl : "",
|
|
6233
|
+
...app.android.success ? { android: app.android.data } : {},
|
|
6234
|
+
...app.ios.success ? { ios: app.ios.data } : {}
|
|
6235
|
+
});
|
|
6228
6236
|
}
|
|
6229
6237
|
return out;
|
|
6230
6238
|
}
|
|
@@ -9726,6 +9734,7 @@ function assistantHandlers({ deps }) {
|
|
|
9726
9734
|
const askId = randomUUID();
|
|
9727
9735
|
const linked = foldersFor(project.id).filter((f) => f.exists).map((f) => f.path);
|
|
9728
9736
|
const mode = command.args["mode"] === "ask" ? "ask" : command.args["mode"] === "do" ? "do" : void 0;
|
|
9737
|
+
const brief = typeof command.args["brief"] === "string" && command.args["brief"].trim() ? command.args["brief"].slice(0, 4e4) : void 0;
|
|
9729
9738
|
const started = assistant.ask({
|
|
9730
9739
|
askId,
|
|
9731
9740
|
prompt,
|
|
@@ -9733,6 +9742,7 @@ function assistantHandlers({ deps }) {
|
|
|
9733
9742
|
projectName: project.name,
|
|
9734
9743
|
...linked.length ? { folders: linked } : {},
|
|
9735
9744
|
...mode ? { mode } : {},
|
|
9745
|
+
...brief ? { brief } : {},
|
|
9736
9746
|
...typeof sessionId === "string" ? { sessionId } : {},
|
|
9737
9747
|
emit
|
|
9738
9748
|
});
|
|
@@ -10068,10 +10078,13 @@ var ASK_MODE_TOOLS = [
|
|
|
10068
10078
|
function buildAskArgs(opts) {
|
|
10069
10079
|
const ask = opts.mode === "ask";
|
|
10070
10080
|
const folders = opts.folders ?? [];
|
|
10081
|
+
const brief = opts.brief?.trim();
|
|
10071
10082
|
const guidance = [
|
|
10072
|
-
`You are the Flowriki assistant for the project "${opts.projectName}" (id ${opts.projectId}). Use the Flowriki tools, and pass projectId "${opts.projectId}" wherever a tool takes one. Start with project_brief: it is this project's memory
|
|
10083
|
+
`You are the Flowriki assistant for the project "${opts.projectName}" (id ${opts.projectId}). Use the Flowriki tools, and pass projectId "${opts.projectId}" wherever a tool takes one. ` + (brief ? "The project brief below is this project's memory for this job: read it first." : "Start with project_brief: it is this project's memory."),
|
|
10073
10084
|
ask ? "ASK MODE: answer the question; change nothing. Cite what you rely on as [[testCase:<its id, tc_\u2026>]], [[knowledge:features/checkout.md]] or [[file:path/in/repo.ts]]." : "DO MODE: do what is asked, on Claude's working branch, for a person to review. Ask in the chat and wait before publishing, deleting, or sending anything to another system. End by writing a short summary of what you did with write_knowledge (memory/sessions/<date>-<topic>.md, append) so the next session knows.",
|
|
10074
|
-
folders.length ? `The project's code is in ${folders.join(" and ")}. Read it with Read, Grep and Glob when it helps; you cannot change it.` : ""
|
|
10085
|
+
folders.length ? `The project's code is in ${folders.join(" and ")}. Read it with Read, Grep and Glob when it helps; you cannot change it.` : "",
|
|
10086
|
+
brief ? `
|
|
10087
|
+
${brief}` : ""
|
|
10075
10088
|
].filter(Boolean).join("\n");
|
|
10076
10089
|
const flowriki = ask ? ASK_MODE_TOOLS.map((t) => `mcp__${MCP_SERVER_NAME}__${t}`) : [`mcp__${MCP_SERVER_NAME}`];
|
|
10077
10090
|
const files = folders.length ? ["Read", "Grep", "Glob"] : [];
|
package/dist/cli.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
runtimeValue,
|
|
24
24
|
start,
|
|
25
25
|
status
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-Z3SL46OX.js";
|
|
27
27
|
import {
|
|
28
28
|
CLOUD_PROVIDERS,
|
|
29
29
|
CLOUD_PROVIDER_NAME,
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
RecordedStepSchema,
|
|
33
33
|
checkMobileAssertion,
|
|
34
34
|
codebaseIndexOf,
|
|
35
|
+
exploreSummary,
|
|
35
36
|
isMobile,
|
|
36
37
|
listDevices,
|
|
37
38
|
locate,
|
|
@@ -48,7 +49,7 @@ import {
|
|
|
48
49
|
screenLines,
|
|
49
50
|
stepRefusedOn,
|
|
50
51
|
targetFor
|
|
51
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-KDW65RBE.js";
|
|
52
53
|
|
|
53
54
|
// src/cli.ts
|
|
54
55
|
import { parseArgs } from "util";
|
|
@@ -325,6 +326,10 @@ var ServiceClient = class {
|
|
|
325
326
|
return this.call(this.scoped(`/bugs/${encodeURIComponent(id)}`, projectId), { method: "PATCH", body: JSON.stringify(body) });
|
|
326
327
|
}
|
|
327
328
|
// ── Knowledge, sources, requirements ──────────────────────
|
|
329
|
+
/** The project's brief for a job: its slice of the knowledge. */
|
|
330
|
+
brief(projectId, scope) {
|
|
331
|
+
return this.call(this.scoped("/brief", projectId, { ...scope.platform ? { platform: scope.platform } : {}, ...scope.features?.length ? { features: scope.features.join(",") } : {} }));
|
|
332
|
+
}
|
|
328
333
|
knowledgePages(projectId) {
|
|
329
334
|
return this.call(this.scoped("/knowledge", projectId));
|
|
330
335
|
}
|
|
@@ -985,7 +990,7 @@ Review and publish it here: ${review}`;
|
|
|
985
990
|
async startMobile(platform, catalog) {
|
|
986
991
|
const draft = this.draft;
|
|
987
992
|
const mobile = catalog.mobile;
|
|
988
|
-
if (!mobile) throw new Error("this project has no phone apps set up \u2014 turn on Android or iOS in Settings \u2192
|
|
993
|
+
if (!mobile) throw new Error("this project has no phone apps set up \u2014 turn on Android or iOS in Settings \u2192 Platforms");
|
|
989
994
|
const resolvers = draft.signIn || draft.device?.kind === "cloud" ? await this.prepare() : null;
|
|
990
995
|
this.mobile = await openMobileSession({
|
|
991
996
|
platform,
|
|
@@ -1233,7 +1238,10 @@ codebase/<folder>.md, which must start "# <folder>", then "Commit: <full sha>"
|
|
|
1233
1238
|
and "Learned: <yyyy-mm-dd>" lines: that is how the Knowledge screen shows it
|
|
1234
1239
|
as learned. codebase.json says which platform's code each folder holds (Web,
|
|
1235
1240
|
Android, iOS, Mobile, All combined, Other): read the web folder's page for a
|
|
1236
|
-
website test and the phone folder's for an app test.
|
|
1241
|
+
website test and the phone folder's for an app test. explore/<platform>.md is
|
|
1242
|
+
what the assistant saw WALKING that platform \u2014 screens, the words on them,
|
|
1243
|
+
journeys, rules it saw refused, vocabulary: read it before writing a test for
|
|
1244
|
+
that platform, because it says what a person sees; the code does not. Keep what you learn with write_knowledge (features/<name>.md,
|
|
1237
1245
|
memory/decisions.md, a session summary), on Claude's branch for review \u2014
|
|
1238
1246
|
never a password, key or token.
|
|
1239
1247
|
|
|
@@ -1412,7 +1420,7 @@ It is now the project these tools work on. Open it: ${service.origin}/projects/$
|
|
|
1412
1420
|
const here = phones.filter((d) => d.platform === p);
|
|
1413
1421
|
const farms = (c.mobile?.cloud ?? []).map((f) => CLOUD_PROVIDER_NAME[f.provider]);
|
|
1414
1422
|
const chosen = c.mobile?.devices[p];
|
|
1415
|
-
return `${p === "android" ? "Android" : "iOS"} app: ${app ?? "(not
|
|
1423
|
+
return `${p === "android" ? "Android" : "iOS"} app: ${app ?? "(not named \u2014 Settings \u2192 Environments)"}
|
|
1416
1424
|
Phones on this computer: ${here.length ? here.map((d) => `${d.name}${d.state === "ready" ? "" : ` (${d.state})`}`).join(", ") : "none"}` + (farms.length ? `
|
|
1417
1425
|
Cloud device farms: ${farms.join(", ")}` : "") + `
|
|
1418
1426
|
Runs: ${c.runWhere?.[p] === "cloud" ? "in the cloud" : "on this computer"}` + (chosen ? ` \u2014 ${chosen.kind === "local" ? chosen.name || chosen.id : `${CLOUD_PROVIDER_NAME[chosen.provider]}: ${chosen.device}`}` : "");
|
|
@@ -2009,11 +2017,19 @@ Use it with start_flow signIn {"profileId": "\u2026", "accountId": "${made.accou
|
|
|
2009
2017
|
{
|
|
2010
2018
|
name: "project_brief",
|
|
2011
2019
|
title: "Read the project's memory",
|
|
2012
|
-
description: "The project's own knowledge, in one call: About the product (product.md, and product/<web|android|ios>.md where a platform differs), memory/decisions.md, what each linked codebase folder was learned as and which platform's code it holds, and the list of feature pages and session summaries. Call it first in every conversation.",
|
|
2013
|
-
inputSchema: { type: "object", properties: { projectId: { type: "string" } }, additionalProperties: false },
|
|
2020
|
+
description: "The project's own knowledge, in one call: About the product (product.md, and product/<web|android|ios>.md where a platform differs), memory/decisions.md, what each linked codebase folder was learned as and which platform's code it holds, what each platform looked like when explored (explore/<platform>.md), and the list of feature pages and session summaries. Call it first in every conversation. With platform and/or features, the brief is the slice for that job: that platform's part and exploration, those features' notes, the code tagged for the platform, and who can sign in.",
|
|
2021
|
+
inputSchema: { type: "object", properties: { projectId: { type: "string" }, platform: { type: "string", enum: ["web", "android", "ios"], description: "The platform the job is about." }, features: { type: "array", items: { type: "string" }, description: "The features (or case folders) the job is about, by name." } }, additionalProperties: false },
|
|
2014
2022
|
annotations: { readOnlyHint: true },
|
|
2015
2023
|
run: async (args) => {
|
|
2016
2024
|
const projectId = await projectFor(args["projectId"]);
|
|
2025
|
+
const platform = str(args["platform"]);
|
|
2026
|
+
const features = Array.isArray(args["features"]) ? args["features"].filter((f) => typeof f === "string") : [];
|
|
2027
|
+
if (platform || features.length) {
|
|
2028
|
+
try {
|
|
2029
|
+
return text((await service.brief(projectId, { ...platform ? { platform } : {}, features })).brief);
|
|
2030
|
+
} catch {
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2017
2033
|
const { pages } = await service.knowledgePages(projectId);
|
|
2018
2034
|
const read = async (path2) => pages.some((p) => p.path === path2) ? (await service.knowledgePage(projectId, path2)).content : null;
|
|
2019
2035
|
const [product, glossary, decisions, web, android, ios, tagged] = await Promise.all(["product.md", "glossary.md", "memory/decisions.md", "product/web.md", "product/android.md", "product/ios.md", "codebase.json"].map(read));
|
|
@@ -2023,7 +2039,12 @@ Use it with start_flow signIn {"profileId": "\u2026", "accountId": "${made.accou
|
|
|
2023
2039
|
const holds = tags[p.path.slice("codebase/".length, -".md".length)]?.tags ?? [];
|
|
2024
2040
|
return `- ${p.path}${holds.length ? ` (${holds.map((t) => CODEBASE_TAG_NAME[t]).join(", ")} code)` : ""}: ${(await read(p.path))?.split("\n").filter((l) => l.trim()).slice(0, 3).join(" \xB7 ") ?? ""}`;
|
|
2025
2041
|
}));
|
|
2026
|
-
const
|
|
2042
|
+
const explored = pages.filter((p) => p.path.startsWith("explore/"));
|
|
2043
|
+
const walks = await Promise.all(explored.map(async (p) => {
|
|
2044
|
+
const s = exploreSummary(await read(p.path) ?? "");
|
|
2045
|
+
return `- ${p.path}: explored ${s.exploredAt ?? "?"}${s.environment ? ` in ${s.environment}` : ""}${s.screens !== null ? `, ${s.screens} screens` : ""} \u2014 read it with knowledge_read before testing that platform`;
|
|
2046
|
+
}));
|
|
2047
|
+
const shown = /* @__PURE__ */ new Set(["product.md", "glossary.md", "memory/decisions.md", "product/web.md", "product/android.md", "product/ios.md", "codebase.json", ...codebases.map((p) => p.path), ...explored.map((p) => p.path)]);
|
|
2027
2048
|
const parts = [
|
|
2028
2049
|
product ? `## About the product (product.md)
|
|
2029
2050
|
${product}` : "No About the product yet \u2014 the person writes it on the Knowledge screen; offer to help draft it.",
|
|
@@ -2039,6 +2060,8 @@ ${glossary}` : "",
|
|
|
2039
2060
|
${decisions}` : "",
|
|
2040
2061
|
codebases.length ? `## Codebase, as learned
|
|
2041
2062
|
${headers.join("\n")}` : "No codebase learned yet.",
|
|
2063
|
+
walks.length ? `## The product, as explored
|
|
2064
|
+
${walks.join("\n")}` : "",
|
|
2042
2065
|
`## Other pages
|
|
2043
2066
|
${pages.filter((p) => !shown.has(p.path)).map((p) => `- ${p.path}`).join("\n") || "none"}`
|
|
2044
2067
|
];
|
|
@@ -2074,7 +2097,7 @@ ${pages.filter((p) => !shown.has(p.path)).map((p) => `- ${p.path}`).join("\n") |
|
|
|
2074
2097
|
{
|
|
2075
2098
|
name: "write_knowledge",
|
|
2076
2099
|
title: "Write a knowledge page",
|
|
2077
|
-
description: `Write what the project should remember, on Claude's working branch for review: product.md (About the product \u2014 the person's own description; write it only when they ask) and product/<web|android|ios>.md (what is particular to that platform's app), codebase/<folder>.md (what a linked folder holds \u2014 starting with "# <folder>", "Commit: <sha>" and "Learned: <yyyy-mm-dd>" lines, then routes, screens, forms and their validation, roles, APIs, flags; summarised, never copied code), features/<name>.md (screens, rules, quirks), memory/decisions.md (decisions and conventions), memory/sessions/<yyyy-mm-dd>-<topic>.md (what a job did). append: true adds to the end instead of replacing. Never a password, key or token \u2014 those are refused.`,
|
|
2100
|
+
description: `Write what the project should remember, on Claude's working branch for review: product.md (About the product \u2014 the person's own description; write it only when they ask) and product/<web|android|ios>.md (what is particular to that platform's app), explore/<web|android|ios>.md (what you saw walking that platform: "# Explored: <Platform>", "Explored: <yyyy-mm-dd>", "Environment: <name>", "Screens: <n>" lines, then Screens, Journeys, Rules observed, Vocabulary, Suggested features), codebase/<folder>.md (what a linked folder holds \u2014 starting with "# <folder>", "Commit: <sha>" and "Learned: <yyyy-mm-dd>" lines, then routes, screens, forms and their validation, roles, APIs, flags; summarised, never copied code), features/<name>.md (screens, rules, quirks), memory/decisions.md (decisions and conventions), memory/sessions/<yyyy-mm-dd>-<topic>.md (what a job did). append: true adds to the end instead of replacing. Never a password, key or token \u2014 those are refused.`,
|
|
2078
2101
|
inputSchema: {
|
|
2079
2102
|
type: "object",
|
|
2080
2103
|
properties: { projectId: { type: "string" }, path: { type: "string" }, content: { type: "string" }, append: { type: "boolean" }, branch: { type: "string" } },
|
package/dist/engine.js
CHANGED
package/package.json
CHANGED