toolroll 0.9.84 → 0.9.85
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/CHANGELOG.md +42 -0
- package/README.md +94 -1193
- package/dist/agent-fence.d.ts +3 -3
- package/dist/agent-fence.js +3 -3
- package/dist/agent-onboard.d.ts +2 -0
- package/dist/agent-onboard.js +3 -0
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +31 -31
- package/dist/browser-workspace.d.ts +5 -0
- package/dist/chat-channel.d.ts +10 -1
- package/dist/chat-channel.js +35 -5
- package/dist/chat-decide.d.ts +16 -4
- package/dist/chat-decide.js +239 -31
- package/dist/chat-messages.d.ts +5 -0
- package/dist/chat-messages.js +1 -1
- package/dist/chat-quiet.js +3 -2
- package/dist/chat-review.d.ts +4 -0
- package/dist/chat-review.js +13 -4
- package/dist/chat-terms.d.ts +9 -0
- package/dist/chat-terms.js +46 -0
- package/dist/contracts/console-api.d.ts +2 -1
- package/dist/contracts/console-api.js +2 -1
- package/dist/contracts/lead-tools.d.ts +30 -0
- package/dist/contracts/lead-tools.js +3 -0
- package/dist/contracts/youiyoux-request.d.ts +248 -0
- package/dist/contracts/youiyoux-request.js +152 -0
- package/dist/flow-cadence.d.ts +8 -2
- package/dist/flow-cadence.js +16 -3
- package/dist/flow-card-task.d.ts +9 -0
- package/dist/flow-card-task.js +15 -6
- package/dist/integrations-ui.js +9 -4
- package/dist/integrations.d.ts +9 -1
- package/dist/integrations.js +43 -2
- package/dist/landed-cleanup.d.ts +4 -0
- package/dist/landed-cleanup.js +3 -2
- package/dist/lead-capabilities.js +2 -1
- package/dist/lead-cli.js +3 -1
- package/dist/lead-tools.d.ts +2 -0
- package/dist/lead-tools.js +30 -4
- package/dist/lead.d.ts +2 -0
- package/dist/lead.js +3 -3
- package/dist/operate.d.ts +1 -2
- package/dist/operate.js +11 -15
- package/dist/project-activity.d.ts +20 -0
- package/dist/project-activity.js +23 -0
- package/dist/project-cli.d.ts +1 -0
- package/dist/project-cli.js +36 -19
- package/dist/project-knowledge.d.ts +3 -3
- package/dist/project-outcomes.d.ts +119 -0
- package/dist/project-outcomes.js +79 -0
- package/dist/result-actions.d.ts +4 -0
- package/dist/result-actions.js +41 -9
- package/dist/result-review.d.ts +9 -0
- package/dist/result-review.js +45 -5
- package/dist/server/console.css +12 -0
- package/dist/server/pages.js +11 -1
- package/dist/server/render-chat.js +3 -2
- package/dist/server/render-pages.d.ts +2 -2
- package/dist/server/render-pages.js +7 -2
- package/dist/server/render-results.d.ts +2 -0
- package/dist/server/render-results.js +20 -7
- package/dist/server/render-tasks.d.ts +1 -0
- package/dist/server/render-tasks.js +15 -5
- package/dist/server/route-table.js +1 -0
- package/dist/server/settings.js +18 -1
- package/dist/server/task-views.js +6 -0
- package/dist/server/tasks.js +42 -6
- package/dist/store.d.ts +46 -3
- package/dist/store.js +165 -6
- package/dist/task-source.d.ts +13 -1
- package/dist/task-source.js +17 -1
- package/dist/telegram-lead.js +7 -5
- package/dist/telegram.js +1 -1
- package/dist/toolroll-update.js +2 -2
- package/dist/webhooks.d.ts +6 -0
- package/dist/webhooks.js +25 -0
- package/dist/work-index.d.ts +4 -0
- package/dist/work-index.js +32 -0
- package/dist/youiyoux-intake.d.ts +234 -0
- package/dist/youiyoux-intake.js +908 -0
- package/package.json +11 -8
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* youiyoux change and options requests become tasks (docs/guide/getting-started.md, "Change requests from youiyoux").
|
|
3
|
+
*
|
|
4
|
+
* youiyoux is a design-system tool: in its hub a person points at a component on a screenshot of their app and asks
|
|
5
|
+
* for a change, and it saves the request as `<project>/.youi/requests/<id>.json` (`youi.request/v1`). A project that
|
|
6
|
+
* uses youiyoux (a `youi.project.json` at its root, or a `.youi/requests` folder) has this intake on with no step of
|
|
7
|
+
* its own, unless a person turned it off in Settings → Integrations.
|
|
8
|
+
*
|
|
9
|
+
* On the worker's flow pass this reads the project's main checkout — the path from Toolroll's own records, resolved
|
|
10
|
+
* with realpath — and files each open change request with a task exactly once, keyed by the project and the request
|
|
11
|
+
* id in `youiyoux_request`: never again, whatever the file says later. Everything in the folder is outside text,
|
|
12
|
+
* written by whoever can write the project's folder:
|
|
13
|
+
*
|
|
14
|
+
* - the folders and files must be real (never a link), a file a single link to itself, at most 64 KB, read without
|
|
15
|
+
* following a link or waiting on a pipe, and at most 200 are read in one pass;
|
|
16
|
+
* - a file whose name, schema or id is wrong is counted (the integration says so) and never filed;
|
|
17
|
+
* - text that looks like a key or password is left out (recorded once, never filed), as flow triggers do;
|
|
18
|
+
* - a path the task may touch is kept only when youiyoux knew them all and every one is a plain relative path;
|
|
19
|
+
* - the task is filed through the one filing door (proposal.ts) by the "youiyoux" automation, unplanned, and waits
|
|
20
|
+
* for a person: its provenance (`filed_via = 'youiyoux'`) keeps every seal no person looked at off it (store.ts,
|
|
21
|
+
* the outside-request quarantine), so no operating mode, grant, schedule or automatic seal approves it. A person
|
|
22
|
+
* approves it in Toolroll, or with their own two taps in their paired chat where they turned approving from chat
|
|
23
|
+
* on (chat-decide.ts), bound to the exact scope the card showed.
|
|
24
|
+
*
|
|
25
|
+
* Beside each request it writes `<id>.task.json` (`youi.request-task/v1`): the task and its status, and, when the
|
|
26
|
+
* console has an address (the one the installation names, else this machine's own console where `up` serves it, on
|
|
27
|
+
* loopback), the task's link and `home`, where a person approves all waiting work. It is written when filed, whenever
|
|
28
|
+
* the status changes, and once more when that address changes. Beside an options request's options file (below), it is
|
|
29
|
+
* the only file it writes in the checkout: written whole (a temporary file in the same folder, then renamed over),
|
|
30
|
+
* refused when the folder or the target is a link, never the request itself. The status is also kept in the store;
|
|
31
|
+
* nothing Toolroll decides reads the file back.
|
|
32
|
+
*
|
|
33
|
+
* Status words (task-status.ts headline → youiyoux): Queued → queued; Planning, Building and Waiting (work going on
|
|
34
|
+
* by itself) → building; Needs you → needs-you; Ready for review → ready; Complete → done; Failed → failed;
|
|
35
|
+
* Stopped → stopped.
|
|
36
|
+
*
|
|
37
|
+
* An options request (`kind: "options"`) asks an agent for two to four options for one component, which youiyoux shows
|
|
38
|
+
* on its Screens canvas. It is filed the same way, once, waiting for a person, and only as youiyoux's contract has it:
|
|
39
|
+
* its offer names `p-<its own hex>`, that proposal's file `.youi/proposals/p-<hex>.json`, and the task may touch that
|
|
40
|
+
* one file (anything else is counted as a file that couldn't be read, and never filed). The proposal it names is kept
|
|
41
|
+
* when filed; the request is never read for it again. Then (runYouiyoux, the worker's pass):
|
|
42
|
+
*
|
|
43
|
+
* - When the task is Ready for review (or Complete), its result is read: the file at the result's commit, the commit
|
|
44
|
+
* Toolroll recorded for the build (never the checkout the agent had, which it controls and the pool hands on), read
|
|
45
|
+
* with the hardened git (teardown-git.ts). It must be a plain file in that commit (never a link), at most 64 KB, a
|
|
46
|
+
* `youi.proposal/v1` file whose id is the proposal, which answers this request, still open (an agent proposes; only a
|
|
47
|
+
* person decides), by an agent, with no key-like text. Then it is copied, byte for byte, into the project's main
|
|
48
|
+
* checkout as `.youi/proposals/<id>.json` the way the status file is written (folders real, never through a link;
|
|
49
|
+
* a temporary file, then linked into place, which never replaces a file already there: a person may have decided on
|
|
50
|
+
* it). A file missing from the result, or one that isn't safe, is said in the status file and never copied; a newer
|
|
51
|
+
* result is read again.
|
|
52
|
+
* - Only a file Toolroll copied is read for a decision: one already at that name is left as it was (a person may
|
|
53
|
+
* have decided on it) and never read for one, unless it is byte for byte the result's (an earlier pass's copy).
|
|
54
|
+
* - When that copy says a person chose an option or dismissed them all (youiyoux's hub writes that), and it is still
|
|
55
|
+
* the proposal copied (only its status, choice, decidedBy, decidedAt, request and updatedAt may differ), decided by
|
|
56
|
+
* a person, at a time, the task is marked complete by Toolroll, as landed work is (result-completion.ts LANDED_ACTOR), without
|
|
57
|
+
* merging or publishing its branch: its deliverable was the options, and youiyoux has used them. Only the exact
|
|
58
|
+
* result whose file was copied, and only through every guard a person's completion passes (landed-cleanup.ts
|
|
59
|
+
* completionProblem): otherwise it stays Ready for review and the ledger says why. The ledger keeps who decided
|
|
60
|
+
* what, as youiyoux wrote it (outside text, cleaned). A decision never approves, publishes or merges anything.
|
|
61
|
+
*/
|
|
62
|
+
import type { Store } from "./store.js";
|
|
63
|
+
import type { Headline } from "./task-status.js";
|
|
64
|
+
import { type Git } from "./landed-cleanup.js";
|
|
65
|
+
import { YOUIYOUX_FILED_VIA, type YouiyouxRequest, type YouiyouxRequestTask, type YouiyouxTaskStatus } from "./contracts/youiyoux-request.js";
|
|
66
|
+
export { YOUIYOUX_FILED_VIA };
|
|
67
|
+
/** Who files the tasks: an automation, like a flow trigger. */
|
|
68
|
+
export declare const YOUIYOUX_ACTOR = "youiyoux";
|
|
69
|
+
export declare const REQUEST_BYTES: number;
|
|
70
|
+
export declare const REQUESTS_PER_PASS = 200;
|
|
71
|
+
export declare const FILED_PER_PASS = 10;
|
|
72
|
+
/** The ledger's word for a decision youiyoux's hub made on a task's options. */
|
|
73
|
+
export declare const OPTIONS_DECIDED_ACTION = "youiyoux options decided";
|
|
74
|
+
export declare const OPTIONS_COPIED_ACTION = "youiyoux options copied";
|
|
75
|
+
/** The flow pass runs every 15 seconds; the folder is read at most this often. */
|
|
76
|
+
export declare const INTAKE_EVERY_MS = 30000;
|
|
77
|
+
export declare const STATUS_OF_HEADLINE: Readonly<Record<Headline, YouiyouxTaskStatus>>;
|
|
78
|
+
/** Whether a project uses youiyoux: a `youi.project.json` at its root, or a `.youi` folder. Only their presence is
|
|
79
|
+
* read here (a link counts, so the integration can say it is Broken); requestsFolder decides what may be read. */
|
|
80
|
+
export declare function usesYouiyoux(repo: string): boolean;
|
|
81
|
+
/** The paths a request may touch: every one a plain relative path inside the project, or none at all. */
|
|
82
|
+
export declare function safeTouches(touches: readonly string[]): string[] | null;
|
|
83
|
+
export type RequestTask = {
|
|
84
|
+
title: string;
|
|
85
|
+
goal: string;
|
|
86
|
+
outOfScope: string | null;
|
|
87
|
+
touches: string[];
|
|
88
|
+
acceptance: {
|
|
89
|
+
id: string;
|
|
90
|
+
statement: string;
|
|
91
|
+
how: null;
|
|
92
|
+
evidence: string[];
|
|
93
|
+
}[];
|
|
94
|
+
/** Where the person pointed, for the task page: the route, the component, and `file:line` when youiyoux knew a plain one. */
|
|
95
|
+
pointed: {
|
|
96
|
+
route: string;
|
|
97
|
+
component: string;
|
|
98
|
+
at: string | null;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
/** The task a request asks for, in Toolroll's terms. Text is cleaned here; whether it may be filed is decided by the caller. */
|
|
102
|
+
export declare function requestTask(request: YouiyouxRequest): RequestTask;
|
|
103
|
+
/** A person turns the intake off or back on for a project; the ledger keeps who. */
|
|
104
|
+
export declare function setYouiyouxIntake(store: Store, repo: string, on: boolean, by: string, now: Date): void;
|
|
105
|
+
export type YouiyouxState = {
|
|
106
|
+
/** The project uses youiyoux, as the worker's last pass found. */
|
|
107
|
+
uses: boolean;
|
|
108
|
+
/** Requests become tasks: it uses youiyoux and nobody turned it off. */
|
|
109
|
+
on: boolean;
|
|
110
|
+
/** A person turned it off. */
|
|
111
|
+
off: boolean;
|
|
112
|
+
/** Filed tasks not yet done, failed or stopped. */
|
|
113
|
+
queued: number;
|
|
114
|
+
filed: number;
|
|
115
|
+
invalid: number;
|
|
116
|
+
problem: string | null;
|
|
117
|
+
checkedAt: string | null;
|
|
118
|
+
};
|
|
119
|
+
/** How the intake stands for one project, from the store alone: a page reads it on every render, so it never reads the
|
|
120
|
+
* project's folder (one that doesn't answer must not hold the console). Whether it uses youiyoux is the last pass's. */
|
|
121
|
+
export declare function youiyouxState(store: Store, repo: string): YouiyouxState;
|
|
122
|
+
/** The one line `toolroll onboard` says for a project that uses youiyoux; null when it doesn't. */
|
|
123
|
+
export declare function youiyouxOnboardLine(store: Store, repo: string): string | null;
|
|
124
|
+
/** The console the links name: the address the installation names (CONSOLE_URL or the console-url file), else, with
|
|
125
|
+
* none named, this machine's own console where `up` serves it (loopback http only, never a guessed host); null without
|
|
126
|
+
* either. Either way http(s) with no credentials, query or fragment. */
|
|
127
|
+
export declare function consoleBase(env: Record<string, string | undefined>, dir: string | null): string | null;
|
|
128
|
+
/** The task's page in that console; null without one. */
|
|
129
|
+
export declare function taskLink(env: Record<string, string | undefined>, dir: string | null, taskId: string): string | null;
|
|
130
|
+
/**
|
|
131
|
+
* Write `<id>.task.json` beside its request, whole. The folders are checked again now (a link is refused), the request
|
|
132
|
+
* must still be a plain file, the target must be a plain file or absent, and the content goes to a fresh temporary file
|
|
133
|
+
* in the same folder (created exclusively, never through a link) that is then renamed over the target.
|
|
134
|
+
*/
|
|
135
|
+
export declare function writeStatusFile(repo: string, body: YouiyouxRequestTask): {
|
|
136
|
+
ok: true;
|
|
137
|
+
} | {
|
|
138
|
+
ok: false;
|
|
139
|
+
problem: string;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Put an options file into the project's main checkout as `.youi/proposals/<id>.json`, whole, and never over a file
|
|
143
|
+
* already there (a person may have decided on it). The folders are checked as the status file's are (`.youi/proposals`
|
|
144
|
+
* is made, as a real folder, when missing), the content goes to a fresh temporary file in the same folder (created
|
|
145
|
+
* exclusively, never through a link), the folders are checked again, and the temporary file is linked into place, which
|
|
146
|
+
* fails rather than replace anything at that name, a link included. `same`: that exact content was already there;
|
|
147
|
+
* `taken`: something else was, and is left as it was.
|
|
148
|
+
*/
|
|
149
|
+
export declare function writeProposalFile(repo: string, id: string, text: string): {
|
|
150
|
+
ok: true;
|
|
151
|
+
made: "written" | "same" | "taken";
|
|
152
|
+
} | {
|
|
153
|
+
ok: false;
|
|
154
|
+
problem: string;
|
|
155
|
+
};
|
|
156
|
+
/** `git`: the hardened git an options request's result is read with (landed-cleanup.ts gitOf), and `evidenceRoot`, where
|
|
157
|
+
* results' saved evidence is (a completion is bound to the receipt read with it). Without either, options wait. */
|
|
158
|
+
export type YouiyouxIo = {
|
|
159
|
+
dir: string | null;
|
|
160
|
+
env: Record<string, string | undefined>;
|
|
161
|
+
git?: Git;
|
|
162
|
+
evidenceRoot?: string | null;
|
|
163
|
+
};
|
|
164
|
+
/** `copied`: options files that went to the hub; `decided`: decisions in the hub Toolroll acted on. */
|
|
165
|
+
export type YouiyouxPass = {
|
|
166
|
+
filed: number;
|
|
167
|
+
skipped: number;
|
|
168
|
+
invalid: number;
|
|
169
|
+
updated: number;
|
|
170
|
+
copied: number;
|
|
171
|
+
decided: number;
|
|
172
|
+
problems: string[];
|
|
173
|
+
};
|
|
174
|
+
export declare const NO_YOUIYOUX_PASS: Readonly<YouiyouxPass>;
|
|
175
|
+
/** File one request's task, exactly once: the claim and the filing are one transaction (two passes, in two processes
|
|
176
|
+
* or one, make one task). */
|
|
177
|
+
export declare function fileYouiyouxRequest(store: Store, repo: string, request: YouiyouxRequest, now: Date): {
|
|
178
|
+
made: "filed";
|
|
179
|
+
taskId: string;
|
|
180
|
+
} | {
|
|
181
|
+
made: "seen";
|
|
182
|
+
} | {
|
|
183
|
+
made: "skipped";
|
|
184
|
+
note: string;
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* One message for what a pass filed, however many: the person's paired chats draw it as one card (chat-decide.ts) that
|
|
188
|
+
* lists each new task, with Approve all and each one's own Approve and Open, and a phone push links to what needs
|
|
189
|
+
* them. Keyed by the pass's first task, so a pass says it once; the tasks are the ones filed with it (one project, one
|
|
190
|
+
* moment: requestPassOf). Titles are cleaned outside text, as filed.
|
|
191
|
+
*/
|
|
192
|
+
export declare function noteYouiyouxFiled(store: Store, taskIds: readonly string[], now: Date): void;
|
|
193
|
+
/** What a pass's tasks were asked for, in a word: "change request", "options request", or "request" for both. */
|
|
194
|
+
export declare function requestKindWord(store: Store, taskIds: readonly string[]): string;
|
|
195
|
+
/** The tasks one pass filed beside this one (one project, one moment), in request order; empty for any other task. */
|
|
196
|
+
export declare function requestPassOf(store: Store, taskId: string): string[];
|
|
197
|
+
/**
|
|
198
|
+
* One project's pass: read new requests and file them, then write each filed task's status where it changed (no
|
|
199
|
+
* options moved: runYouiyoux does that too). The folder read is the project in Toolroll's records that `given`
|
|
200
|
+
* resolves to; anything else is left alone.
|
|
201
|
+
*/
|
|
202
|
+
export declare function runYouiyouxIntake(store: Store, given: string, now: Date, io: YouiyouxIo, options?: {
|
|
203
|
+
force?: boolean;
|
|
204
|
+
}): YouiyouxPass;
|
|
205
|
+
/** The worker's pass for one project (flow-cadence.ts): the intake, then each options request's options, both ways. */
|
|
206
|
+
export declare function runYouiyoux(store: Store, given: string, now: Date, io: YouiyouxIo, options?: {
|
|
207
|
+
force?: boolean;
|
|
208
|
+
}): Promise<YouiyouxPass>;
|
|
209
|
+
export type OptionsRow = {
|
|
210
|
+
request: string;
|
|
211
|
+
taskId: string;
|
|
212
|
+
proposal: string;
|
|
213
|
+
state: string | null;
|
|
214
|
+
run: number | null;
|
|
215
|
+
digest: string | null;
|
|
216
|
+
};
|
|
217
|
+
/** The digest of an options file apart from what a decision changes: the proposal itself, every other key included. */
|
|
218
|
+
export declare function proposalIdentity(raw: unknown): string | null;
|
|
219
|
+
/** Why an agent's options file can't go to the hub as it stands, or null. Toolroll checks what makes it safe to copy
|
|
220
|
+
* and this request's; youiyoux checks each option against the component's contract when it reads it. */
|
|
221
|
+
export declare function proposalProblem(text: string, proposal: string, request: string): string | null;
|
|
222
|
+
export type Decision = {
|
|
223
|
+
status: "chosen" | "dismissed";
|
|
224
|
+
choice: string | null;
|
|
225
|
+
label: string | null;
|
|
226
|
+
by: string | null;
|
|
227
|
+
at: string | null;
|
|
228
|
+
};
|
|
229
|
+
/**
|
|
230
|
+
* A person decided in the hub: mark the task complete as landed work is, bound to the exact result whose options were
|
|
231
|
+
* copied, through every guard a person's completion passes, or leave it Ready for review and say why. Once per request,
|
|
232
|
+
* in one transaction with the read. Waits (false) while the task isn't Ready, Complete or cancelled.
|
|
233
|
+
*/
|
|
234
|
+
export declare function actOnDecision(store: Store, repo: string, row: OptionsRow, decision: Decision, now: Date, root: string): boolean;
|