@llblab/pi-kit 0.5.1 → 0.6.0
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 +8 -0
- package/README.md +3 -3
- package/node_modules/@llblab/pi-grow-loop/AGENTS.md +2 -2
- package/node_modules/@llblab/pi-grow-loop/CHANGELOG.md +4 -0
- package/node_modules/@llblab/pi-grow-loop/README.md +6 -6
- package/node_modules/@llblab/pi-grow-loop/index.ts +6 -3
- package/node_modules/@llblab/pi-grow-loop/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/AGENTS.md +1 -1
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +20 -0
- package/node_modules/@llblab/pi-telegram/README.md +1 -1
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +2 -2
- package/node_modules/@llblab/pi-telegram/docs/multi-instance-bus.md +4 -0
- package/node_modules/@llblab/pi-telegram/docs/outbound.md +27 -5
- package/node_modules/@llblab/pi-telegram/docs/public-api.md +1 -0
- package/node_modules/@llblab/pi-telegram/index.ts +24 -19
- package/node_modules/@llblab/pi-telegram/lib/activity-verbosity.ts +43 -25
- package/node_modules/@llblab/pi-telegram/lib/activity.ts +79 -6
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +110 -91
- package/node_modules/@llblab/pi-telegram/lib/config.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/delivery.ts +18 -18
- package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +14 -3
- package/node_modules/@llblab/pi-telegram/lib/menu-settings.ts +2 -2
- package/node_modules/@llblab/pi-telegram/lib/outbound-attachments.ts +41 -37
- package/node_modules/@llblab/pi-telegram/lib/outbound-voice.ts +39 -42
- package/node_modules/@llblab/pi-telegram/lib/outbound.ts +28 -17
- package/node_modules/@llblab/pi-telegram/lib/preview.ts +134 -73
- package/node_modules/@llblab/pi-telegram/lib/queue.ts +113 -72
- package/node_modules/@llblab/pi-telegram/lib/replies.ts +46 -38
- package/node_modules/@llblab/pi-telegram/lib/routing.ts +192 -58
- package/node_modules/@llblab/pi-telegram/lib/telegram-api.ts +36 -3
- package/node_modules/@llblab/pi-telegram/lib/updates.ts +27 -35
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/node_modules/@llblab/skills/abcd-context/AGENTS.md +1 -0
- package/node_modules/@llblab/skills/abcd-context/CHANGELOG.md +6 -2
- package/node_modules/@llblab/skills/abcd-context/SKILL.md +1 -1
- package/node_modules/@llblab/skills/abcd-context/docs/validation-design.md +11 -5
- package/node_modules/@llblab/skills/abcd-context/scripts/_self-test.mjs +61 -0
- package/node_modules/@llblab/skills/abcd-context/scripts/validate-context.mjs +67 -0
- package/node_modules/@llblab/skills/package.json +1 -1
- package/node_modules/@llblab/skills/release-flow/SKILL.md +2 -4
- package/package.json +4 -4
|
@@ -23,6 +23,7 @@ const missingPathOutput = run([path.join(fixtureRoot, "missing")], {
|
|
|
23
23
|
const jsonOptionOutput = run(["--json"]);
|
|
24
24
|
const invalidLineRefRoot = createInvalidLineRefFixture();
|
|
25
25
|
const tableRoot = createTableFixture();
|
|
26
|
+
const listRoot = createListFixture();
|
|
26
27
|
try {
|
|
27
28
|
const invalidLineRefOutput = run([invalidLineRefRoot], {
|
|
28
29
|
withoutRootEnv: true,
|
|
@@ -49,6 +50,12 @@ try {
|
|
|
49
50
|
.replace("|------------|---:|", "| --- | ---: |"),
|
|
50
51
|
);
|
|
51
52
|
const wideTableOutput = run([tableRoot], { withoutRootEnv: true });
|
|
53
|
+
const tightListOutput = run([listRoot], { withoutRootEnv: true });
|
|
54
|
+
fs.appendFileSync(
|
|
55
|
+
path.join(listRoot, "docs/lists.md"),
|
|
56
|
+
"\n- First loose item.\n Continued detail.\n\n- Second loose item.\n - Nested item.\n\n - Nested sibling.\n",
|
|
57
|
+
);
|
|
58
|
+
const looseListOutput = run([listRoot], { withoutRootEnv: true });
|
|
52
59
|
|
|
53
60
|
checkSuccess("default fixture", defaultOutput);
|
|
54
61
|
checkSuccess("fixture path arg", pathOutput);
|
|
@@ -59,9 +66,12 @@ try {
|
|
|
59
66
|
checkCompactTableAndLatex(compactTableOutput);
|
|
60
67
|
checkNonCompactTable(nonCompactTableOutput);
|
|
61
68
|
checkWideTable(wideTableOutput);
|
|
69
|
+
checkTightLists(tightListOutput);
|
|
70
|
+
checkLooseLists(looseListOutput);
|
|
62
71
|
} finally {
|
|
63
72
|
fs.rmSync(invalidLineRefRoot, { recursive: true, force: true });
|
|
64
73
|
fs.rmSync(tableRoot, { recursive: true, force: true });
|
|
74
|
+
fs.rmSync(listRoot, { recursive: true, force: true });
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
console.log("PASS: validate-context fixture + self-reference regression");
|
|
@@ -146,6 +156,57 @@ function checkWideTable(result) {
|
|
|
146
156
|
);
|
|
147
157
|
}
|
|
148
158
|
|
|
159
|
+
function checkTightLists(result) {
|
|
160
|
+
assert(result.status === 0, "contiguous lists and fenced examples pass");
|
|
161
|
+
assert(
|
|
162
|
+
result.stdout.includes("Markdown list checks passed"),
|
|
163
|
+
"contiguous list check reports success",
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function checkLooseLists(result) {
|
|
168
|
+
assert(result.status !== 0, "blank lines inside lists fail validation");
|
|
169
|
+
assert(
|
|
170
|
+
result.stdout.includes("Blank line inside Markdown list: docs/lists.md"),
|
|
171
|
+
"loose list failure identifies its file",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function createListFixture() {
|
|
176
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "abcd-context-list-"));
|
|
177
|
+
fs.mkdirSync(path.join(root, "docs"));
|
|
178
|
+
fs.writeFileSync(
|
|
179
|
+
path.join(root, "README.md"),
|
|
180
|
+
"# Probe\n\n[Context](./AGENTS.md) [Backlog](./BACKLOG.md) [History](./CHANGELOG.md) [Docs](./docs/README.md)\n",
|
|
181
|
+
);
|
|
182
|
+
fs.writeFileSync(
|
|
183
|
+
path.join(root, "AGENTS.md"),
|
|
184
|
+
"# Context\n\n## Meta-Protocol Principles\n\n- First rule.\n- Second rule.\n\n## Operating Principles\n\n- Rule.\n",
|
|
185
|
+
);
|
|
186
|
+
fs.writeFileSync(path.join(root, "BACKLOG.md"), "# Backlog\n\nNo open work.\n");
|
|
187
|
+
fs.writeFileSync(path.join(root, "CHANGELOG.md"), "# Changelog\n\nNo releases.\n");
|
|
188
|
+
fs.writeFileSync(path.join(root, "docs/README.md"), "# Docs\n\n- [Lists](./lists.md)\n");
|
|
189
|
+
fs.writeFileSync(
|
|
190
|
+
path.join(root, "docs/lists.md"),
|
|
191
|
+
[
|
|
192
|
+
"# Lists",
|
|
193
|
+
"",
|
|
194
|
+
"1. First item.",
|
|
195
|
+
"2. Second item.",
|
|
196
|
+
" - Nested item.",
|
|
197
|
+
" - Nested sibling.",
|
|
198
|
+
"",
|
|
199
|
+
"```markdown",
|
|
200
|
+
"- Fenced item.",
|
|
201
|
+
"",
|
|
202
|
+
"- Fenced loose item.",
|
|
203
|
+
"```",
|
|
204
|
+
"",
|
|
205
|
+
].join("\n"),
|
|
206
|
+
);
|
|
207
|
+
return root;
|
|
208
|
+
}
|
|
209
|
+
|
|
149
210
|
function createTableFixture() {
|
|
150
211
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "abcd-context-table-"));
|
|
151
212
|
fs.mkdirSync(path.join(root, "docs"));
|
|
@@ -16,6 +16,7 @@ for (let index = 0; index < args.length; index += 1) {
|
|
|
16
16
|
"Validates the current directory by default, VALIDATE_CONTEXT_ROOT when set,",
|
|
17
17
|
"or the explicit project-root argument when provided.",
|
|
18
18
|
"",
|
|
19
|
+
"Markdown list items must be contiguous; blank separators fail validation.",
|
|
19
20
|
"Markdown table formatting is always checked. Rows over 120 characters warn.",
|
|
20
21
|
].join("\n"),
|
|
21
22
|
);
|
|
@@ -167,6 +168,53 @@ function markdownLines(text) {
|
|
|
167
168
|
});
|
|
168
169
|
}
|
|
169
170
|
|
|
171
|
+
function markdownIndent(line) {
|
|
172
|
+
const leading = line.match(/^[ \t]*/)?.[0] || "";
|
|
173
|
+
return [...leading].reduce((width, char) => width + (char === "\t" ? 4 : 1), 0);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function findLooseListBlankLines(text) {
|
|
177
|
+
const lines = markdownLines(text);
|
|
178
|
+
const listIndents = [];
|
|
179
|
+
let pendingBlankLine;
|
|
180
|
+
const violations = [];
|
|
181
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
182
|
+
const { line, outsideFence } = lines[index];
|
|
183
|
+
if (!outsideFence) {
|
|
184
|
+
listIndents.length = 0;
|
|
185
|
+
pendingBlankLine = undefined;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (/^\s*$/.test(line)) {
|
|
189
|
+
if (listIndents.length > 0 && pendingBlankLine === undefined) {
|
|
190
|
+
pendingBlankLine = index + 1;
|
|
191
|
+
}
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const item = line.match(/^([ \t]*)(?:[-+*]|\d+[.)])[ \t]+\S/);
|
|
195
|
+
if (item) {
|
|
196
|
+
const indent = markdownIndent(item[1]);
|
|
197
|
+
if (pendingBlankLine !== undefined) violations.push(pendingBlankLine);
|
|
198
|
+
while (listIndents.length > 0 && listIndents.at(-1) > indent) listIndents.pop();
|
|
199
|
+
if (listIndents.at(-1) !== indent) listIndents.push(indent);
|
|
200
|
+
pendingBlankLine = undefined;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (pendingBlankLine !== undefined) {
|
|
204
|
+
if (markdownIndent(line) > (listIndents.at(-1) ?? 0)) {
|
|
205
|
+
violations.push(pendingBlankLine);
|
|
206
|
+
pendingBlankLine = undefined;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
listIndents.length = 0;
|
|
210
|
+
pendingBlankLine = undefined;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (/^ {0,3}(?:#{1,6}\s|>|\|)/.test(line)) listIndents.length = 0;
|
|
214
|
+
}
|
|
215
|
+
return violations;
|
|
216
|
+
}
|
|
217
|
+
|
|
170
218
|
function stripFences(text) {
|
|
171
219
|
return markdownLines(text)
|
|
172
220
|
.filter(({ outsideFence }) => outsideFence)
|
|
@@ -392,6 +440,25 @@ if (contextFile) {
|
|
|
392
440
|
|
|
393
441
|
const docsDir = path.join(root, "docs");
|
|
394
442
|
|
|
443
|
+
progress("Checking Markdown lists...");
|
|
444
|
+
let listIssue = false;
|
|
445
|
+
for (const file of mdFiles) {
|
|
446
|
+
const sourceSize = fs.statSync(file).size;
|
|
447
|
+
if (sourceSize > markdownLinkScanMaxBytes) {
|
|
448
|
+
info(
|
|
449
|
+
`Skipped list validation for large Markdown file: ${rel(file)} (${sourceSize} bytes > ${markdownLinkScanMaxBytes})`,
|
|
450
|
+
);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
for (const line of findLooseListBlankLines(read(file))) {
|
|
454
|
+
fail(
|
|
455
|
+
`Blank line inside Markdown list: ${rel(file)}:${line} (keep adjacent list items contiguous)`,
|
|
456
|
+
);
|
|
457
|
+
listIssue = true;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (!listIssue) pass("Markdown list checks passed");
|
|
461
|
+
|
|
395
462
|
progress("Checking Markdown tables...");
|
|
396
463
|
let tableIssue = false;
|
|
397
464
|
for (const file of mdFiles) {
|
|
@@ -210,7 +210,6 @@ After the hard gate passes:
|
|
|
210
210
|
1. Reconfirm immediately before push that local `dev` and `origin/dev` remain absent. Stop if either now exists or the remote check fails.
|
|
211
211
|
2. Push the release commit from local `main` to `origin/main` without creating a pull request.
|
|
212
212
|
3. Verify that `origin/main` resolves to the pushed local `main` commit.
|
|
213
|
-
|
|
214
213
|
4. Confirm the version on `main` matches the intended release version and that the current `main` commit is the released commit on `origin/main`.
|
|
215
214
|
5. Create and push exactly one release tag for the confirmed version on the current `main` commit:
|
|
216
215
|
|
|
@@ -268,9 +267,8 @@ npm view <package-name> version
|
|
|
268
267
|
Treat an explicit npm not-found response as package absence. Authentication, authorization, network, registry-resolution, and other lookup failures are not absence; stop and report them. Automation-owned npm publication already performed this lookup before the hard gate and must not defer it until after tagging.
|
|
269
268
|
|
|
270
269
|
15. Publish only when both conditions are true:
|
|
271
|
-
|
|
272
|
-
- The
|
|
273
|
-
- The `main` version matches the intended release version and is newer than the npm version established before publication.
|
|
270
|
+
- The package already exists on npm.
|
|
271
|
+
- The `main` version matches the intended release version and is newer than the npm version established before publication.
|
|
274
272
|
|
|
275
273
|
When repository automation owns npm publication, never run `npm publish` manually. After all owning tag workflows succeed, require `npm view <package-name>@<version> version` to resolve to the intended version; stop if the package remains absent or mismatched.
|
|
276
274
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"@llblab/pi-actors": "0.52.1",
|
|
44
44
|
"@llblab/pi-clean-room": "0.1.1",
|
|
45
45
|
"@llblab/pi-codex-usage": "0.9.4",
|
|
46
|
-
"@llblab/pi-grow-loop": "0.7.
|
|
46
|
+
"@llblab/pi-grow-loop": "0.7.5",
|
|
47
47
|
"@llblab/pi-state-flow": "0.3.0",
|
|
48
|
-
"@llblab/pi-telegram": "0.
|
|
49
|
-
"@llblab/skills": "1.14.
|
|
48
|
+
"@llblab/pi-telegram": "0.44.0",
|
|
49
|
+
"@llblab/skills": "1.14.1"
|
|
50
50
|
},
|
|
51
51
|
"bundledDependencies": [
|
|
52
52
|
"@llblab/pi-actors",
|