Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
482fe19
bug_repro vb6: report an exe the event log says faulted; a VB6 exe th…
KubaO Oct 4, 2026
d9e1385
BUGS: VB6 sides for four COM entries; Unadvise entry narrowed (VB6 al…
KubaO Oct 4, 2026
a62fc59
vb6run: a sample during which the exe ended is reported as such, with…
KubaO Oct 4, 2026
5b40be3
builder: regenerate package-api.json on twinBASIC BETA 995
KubaO Oct 4, 2026
7a4a14f
WIP.HelpAddin: drop history, shorten
KubaO Oct 4, 2026
1cfeb34
WIP.md, WIP.Authoring: drop incident history, state reasons in the pr…
KubaO Oct 4, 2026
d98156b
WIP.ExamplesBuild: drop the survey passes' history, current figures
KubaO Oct 4, 2026
99295ef
WIP.Harness: drop history, shorten
KubaO Oct 4, 2026
3378a65
WIP package notes: drop history, fix stale paths
KubaO Oct 4, 2026
5e2c89e
Remove WIP.OldJekyll.md: Jekyll-era history, kept by git
KubaO Oct 4, 2026
b9625f3
WIP.Build, Typography, Fonts, A11y: drop history, reasons in the present
KubaO Oct 4, 2026
b77b89c
WIP.Search: drop the session history and commit table, shorten
KubaO Oct 4, 2026
798be4b
Help add-in, increment 1: F1 opens the page for the name under the cu…
KubaO Oct 4, 2026
deb0d3a
Help add-in: commit its copy of the symbol index, build the tree as i…
KubaO Oct 4, 2026
c25f7c3
Build rewrites the help add-in's copy of the symbol index when it dif…
KubaO Oct 4, 2026
1bf8bee
tooling: pack and unpack in process with impexp, never the compiler's…
KubaO Oct 4, 2026
5fe15ff
Help add-in, increment 2: the help pane, with search, its page in a f…
KubaO Oct 4, 2026
34b9eac
bug_repro vb6: report an exe's fault before its missing output, not o…
KubaO Oct 4, 2026
ffe0dd7
bug_repro pack: pack in process with packTree, not by running impexp.…
KubaO Oct 4, 2026
8169dd3
tbrun: TbRun.Out tells the IDE by a flag the wrapper sets, not App.Is…
KubaO Oct 4, 2026
01ae8b9
Help add-in, increment 3: F1 asks the compiler's hover where the name…
KubaO Oct 4, 2026
c136612
try-help-addin.bat: open an IDE on the desktop with the help add-in, …
KubaO Oct 4, 2026
04945f4
Help pane pages follow the IDE's theme: the site reads ?theme=, the a…
KubaO Oct 4, 2026
ff7ae54
try-help-addin: build the add-in on a private desktop; only the IDE i…
KubaO Oct 4, 2026
6a94807
tb-cdp: refuse a call on a closed connection at once, instead of wait…
KubaO Oct 4, 2026
1e631b8
Lane runners and try-help-addin claim the first free DevTools ports w…
KubaO Oct 4, 2026
0bc91a4
ide-test export lane: run the compiler's command line on a private de…
KubaO Oct 4, 2026
fa05d5e
Help add-in, increment 4: F1 on a name with no page shows its declara…
KubaO Oct 4, 2026
7948e0b
BUGS-TO-REPORT: an enum member's [Description] is listed as a member …
KubaO Oct 4, 2026
5db4a7b
File enum-member-description-hover as twinbasic/twinbasic#2465
KubaO Oct 4, 2026
5ea89d7
WIP.md: gh is read-only for sessions; writing to GitHub is the owner's
KubaO Oct 4, 2026
47b0c8c
test.bat gate: test/ports.test.mjs tests the harness's port claims; g…
KubaO Oct 4, 2026
3ed4388
tb-ports: claim one at a time, so a lock still being written is never…
KubaO Oct 4, 2026
c8deb23
Help pane pages show without the site's navigation and header: the si…
KubaO Oct 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
# cannot be run.
wisdom/extract/workflow.mjs text eol=lf

# The help add-in's resources are checked out byte for byte: every build compares its
# copy of the symbol index with the LF file it writes (builder/addin-index.mjs).
add-in/Resources/** -text

# A bug's reproducer is checked out byte for byte: its .twinproj is packed
# from its source tree, and the two must agree in every checkout.
bugs/** -text
Expand Down
7 changes: 7 additions & 0 deletions .github/actions/run-gates/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ runs:
- name: Unit-test check_examples' batches (test/example-batches.test.mjs)
shell: bash
run: node --test test/example-batches.test.mjs
# Unit tests for scripts/lib/tb-ports.mjs, which claims the DevTools ports
# the harness's IDEs use: two claims at once are disjoint, a port in use
# and a live lock are passed over, a stale lock is taken over. Starts no
# IDE. No browser, no built tree, about 2 s.
- name: Unit-test the harness's port claims (test/ports.test.mjs)
shell: bash
run: node --test test/ports.test.mjs
# A regex that backtracks exponentially does not fail a build, it stops
# one: the corpus passes until a page happens to contain the trigger, and
# then a render worker sits inside String.replace forever. Nothing else
Expand Down
2 changes: 1 addition & 1 deletion BOOKPLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
>
> One entry under [Rendering gotchas](#build-environment) has stopped applying and is the one most likely to be acted on: **"PowerShell cannot invoke `npx` directly" no longer affects `book.bat`.** That batch file calls `node`, not `npx`, and a `.bat` is interpreted by `cmd.exe` whichever shell launches it — so no `.ps1` shim is reached and the execution policy is never consulted. The paged.js and CSS Paged Media gotchas above it still hold; the forked bundle lives at `book/lib/paged.browser.js`.
>
> **Current documentation.** The two-stage pipeline, the renderer's flags and phases, and how to triage a failed render are on the site: [PDF Generation](docs/Documentation/PDF-Generation.md) and [Book Configuration](docs/Documentation/Book-Configuration.md), with the vendored-library patches in [Fixes-PagedJS.md](docs/Documentation/Fixes-PagedJS.md) and [Fixes-PDFLib.md](docs/Documentation/Fixes-PDFLib.md). The Phase 8 specification is [builder/PLAN-8.md](builder/PLAN-8.md), and the Jekyll era as a whole is recorded in [WIP.OldJekyll.md](WIP.OldJekyll.md).
> **Current documentation.** The two-stage pipeline, the renderer's flags and phases, and how to triage a failed render are on the site: [PDF Generation](docs/Documentation/PDF-Generation.md) and [Book Configuration](docs/Documentation/Book-Configuration.md), with the vendored-library patches in [Fixes-PagedJS.md](docs/Documentation/Fixes-PagedJS.md) and [Fixes-PDFLib.md](docs/Documentation/Fixes-PDFLib.md). The Phase 8 specification is [builder/PLAN-8.md](builder/PLAN-8.md).

Currently `book.bat` produces a ~1500-page PDF that is a flat concatenation of every reference page. It works, but it doesn't read like a book — no front matter, no parts, no global TOC, every chapter is `<h1>`, and "See Also" cross-references point at standalone `file://` URLs rather than jumping within the PDF.

Expand Down
86 changes: 39 additions & 47 deletions BUGS-TO-REPORT.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ book.bat # renders the PDF book; run build.bat first
examples.bat # compiles the twinBASIC code samples in the pages (Windows + a twinBASIC install)
addin-test.bat # tests IDE add-ins by operating an IDE (Windows + a twinBASIC install)
ide-test.bat # tests the IDE itself by operating it (Windows + a twinBASIC install)
try-help-addin.bat # opens an IDE with the help add-in, to try it by hand (Windows + a twinBASIC install)
```

A clean `build.bat && check.bat` is the bar for "ready to commit"; add `test.bat` when the change touched anything outside `docs/`. Each wrapper names the gates it runs, in order, on [Tools and Scripts](https://docs.twinbasic.com/Documentation/Development/Tools). On Linux or macOS, run the `node` command inside each batch file directly --- they are thin wrappers. `examples.bat`, `addin-test.bat` and `ide-test.bat` are the exceptions to both: they drive the twinBASIC IDE, so they are Windows-only and deliberately outside every gate and outside CI.
Expand Down
51 changes: 24 additions & 27 deletions WIP.A11y.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions WIP.Assert.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ The 15 members per module (identical signatures across all three):
| `SequenceEquals(Expected, Actual, [FailMessage])` | element-by-element comparison of two sequences / arrays |
| `NotSequenceEquals(Expected, Actual, [FailMessage])` | inverse of `SequenceEquals` |

Surface each member as if it were an ordinary `Sub` (e.g. `Sub AreEqual(Expected, Actual, [Message])`); the source-side `Lib "<assert{exact,strict,permissive}>"` / `Alias "#N"` / `PreserveSig` / `DeclareWide` decoration is internal pseudo-DLL plumbing and is **not** surfaced. Call out `[DebugOnly(True)]` (assertions compile out of release builds) and `[MustBeQualified(True)]` (callers must write the module name, e.g. `Strict.IsTrue(x)`).
Show each member as an ordinary `Sub` (e.g. `Sub AreEqual(Expected, Actual, [Message])`). The source-side `Lib "<assert{exact,strict,permissive}>"` / `Alias "#N"` / `PreserveSig` / `DeclareWide` decoration is internal pseudo-DLL plumbing and is **not** shown. Call out `[DebugOnly(True)]` (assertions compile out of release builds) and `[MustBeQualified(True)]` (callers must write the module name, e.g. `Strict.IsTrue(x)`).

Layout: one page per module, listing all 15 members inline under `## <Member>` headings (deep-linkable as `…/Strict#areequal`). Replicating 15 × 3 = 45 near-duplicate pages would add noise without value.
Layout: one page per module, listing all 15 members inline under `## <Member>` headings (deep-linkable as `…/Strict#areequal`). Forty-five near-duplicate pages (15 × 3) would add noise without value.
59 changes: 28 additions & 31 deletions WIP.Authoring.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# twinBASIC Documentation --- Authoring a Page

The page-writing contract, split out of [WIP.md](WIP.md) so a session that is
not writing documentation does not carry it. **Read this before writing or
The page-writing contract, kept apart from [WIP.md](WIP.md) so a session that is
not writing documentation need not load it. **Read this before writing or
editing any page under `docs/`.** WIP.md keeps the placement rules, the
plain-English prose rules and the Don'ts; everything about the shape of a page
is here.
Expand Down Expand Up @@ -70,7 +70,7 @@ This example...

Formatting conventions:

- Heading levels: the page title is `#` (a *chapter* -- a page may legitimately have more than one). Top-level sections (Example, See Also, ...) are `##`; subsections `###`. Do **not** skip `##` with the old `# Title` -> `### Example` "house style". That pattern (h1 straight to h3) exists on many older pages only to keep GitHub's raw-markdown view at a modest heading size; it is a heading-order defect on the built site. `headingLevelNormalizePlugin` in [builder/render.mjs](builder/render.mjs) repairs those legacy pages at build time (it raises `h3`->`h2` on any page that uses h1 and h3 but no h2), so existing pages are not being churned all at once -- but new content must use correct levels, and pages that already mix `##` and `###` are left untouched. A mixed page that skips a level is a real defect the normalizer will not save you from: five were found and fixed this way, and axe's `heading-order` rule now guards the sample against more.
- Heading levels: the page title is `#` (a *chapter* -- a page may legitimately have more than one). Top-level sections (Example, See Also, ...) are `##`; subsections `###`. Do **not** skip `##` with the old `# Title` -> `### Example` "house style". That pattern (h1 straight to h3) exists on many older pages only to keep GitHub's raw-markdown view at a modest heading size; it is a heading-order defect on the built site. `headingLevelNormalizePlugin` in [builder/render.mjs](builder/render.mjs) repairs those legacy pages at build time (it raises `h3`->`h2` on any page that uses h1 and h3 but no h2), so existing pages need no mass edit -- but new content must use correct levels, and pages that already mix `##` and `###` are left untouched. A mixed page that skips a level is a real defect the normalizer does not repair; axe's `heading-order` rule guards the sample against it.
- `**...**` for keywords/literal tokens; `*...*` for placeholders/arguments.
- Code blocks use ` ```tb ` (highlighted via Shiki using the vendored `builder/twinbasic.tmLanguage.json` grammar).
- Parameter lists use the deflist `term` + `: definition` indentation pattern (NOT the MS-style markdown table).
Expand All @@ -86,8 +86,8 @@ Three keys on a package's `index.md` are **provenance for the authoring pass**.
them reaches the HTML --- `grep -r indexed_from docs/_site` returns nothing, because nothing
in `template.mjs` iterates frontmatter generically; every consumer reads a named field. The
build reads one of them, `exclude_from_docs`, for one purpose: the symbol index's count of
public symbols no page documents leaves those names out (`reportableGaps` in
[builder/symbols.mjs](builder/symbols.mjs), and `--symbol-gaps` writes the list). Leave all
public symbols that no page documents leaves those names out (`reportableGaps` in
[builder/symbols.mjs](builder/symbols.mjs); `--symbol-gaps` writes the list). Leave all
three in place.

| Key | Means |
Expand All @@ -102,8 +102,7 @@ a documentation gap.** Without them a re-index cannot tell "not yet written" fro
"deliberately omitted", which is the whole point of recording them.

The six packages carrying `indexed_from` are `AppGlobalClassObject`, `CustomControls`,
`TwinBasicAssertions`, `WinEventLogLib`, `WinNamedPipesLib` and `WinServicesLib`, all set by
the 2026-06-04 pass: `9f406eb`, `05ed96b`, `77c6a03`, `4cd4f4b`, `3429b97`, `6a68815`.
`TwinBasicAssertions`, `WinEventLogLib`, `WinNamedPipesLib` and `WinServicesLib`.
`exclude_from_docs` is on three of them (`InternalStuff`; `EventLogHelperPrivate` +
`EventLogAPIs`; `ServicesConstantsPublic`).

Expand All @@ -115,9 +114,9 @@ check was run against a build that no longer matches the package.
> yet**, covering packages beyond the six above. If you are about to document a package
> from scratch, ask first --- it may already be written and waiting to merge.

One other inert key exists, and is a different thing: `has_children` on four pages is a
just-the-docs leftover. tbdocs derives the nav tree itself and never reads it. Harmless, but
it is theme residue rather than something anyone is meant to maintain.
One other inert key is a different thing: `has_children` on four pages is a
just-the-docs leftover. tbdocs derives the nav tree itself and never reads it. Nobody
needs to maintain it.

### `symbols:` --- what a page documents, for the symbol index

Expand Down Expand Up @@ -302,10 +301,10 @@ claim that a permalink is referenced from source, not an obligation to update on
other changes. A reviewer looking at a `Description` string and at a reference page for the
same symbol will reach for that connection; there isn't one yet.

Related: **`[Documentation(...)]` is not a twinBASIC attribute.** It does not exist. It was
asserted in eight places, including a `tb` code sample teaching it, as the in-source consumer
of the `/tB/` URL contract. The real attribute is `[Description(...)]`, which is not that.
The IDE help system remains a genuine consumer of the permalinks.
Related: **`[Documentation(...)]` is not a twinBASIC attribute.** It does not exist. Never
present it, in prose or in a `tb` sample, as the in-source consumer of the `/tB/` URL
contract. The real attribute is `[Description(...)]`, which is not that. The IDE help
system remains a genuine consumer of the permalinks.

## Per-symbol workflow

Expand All @@ -322,7 +321,7 @@ The IDE help system remains a genuine consumer of the permalinks.
- WinNativeCommonCtls → single-file (`DTPicker`, `MonthView`, `ProgressBar`, `Slider`, `UpDown`) or folder-style (`ImageList/`, `ListView/`, `TreeView/`) when the control has sub-object companions. Module-level enums under `Enumerations/`; per-control nested enums fold onto the declaring control's page.
- Pick `<Mod>` from VBA's grouping (Information, Interaction, Strings, FileSystem, DateTime, Math, Financial, Conversion, ...) and the existing folders under `Reference/<Package>/`.
2. **Flag tB deviations** with a `> [!NOTE]` callout (see next section).
3. **Update the parent index** — turn an unlinked bullet into a link with a short blurb. Match the existing style of the page. If a new package is being added, also add a bullet to `docs/Reference/Built-In.md` (or `Default.md`) and bump the count on `docs/Reference/Packages.md` and `docs/Reference/index.md`. `Packages.md` itself only links to those two landing pages -- it does not enumerate packages, which is how `AppGlobalClassObject` went unlisted for months.
3. **Update the parent index** — turn an unlinked bullet into a link with a short blurb. Match the existing style of the page. If a new package is being added, also add a bullet to `docs/Reference/Built-In.md` (or `Default.md`) and bump the count on `docs/Reference/Packages.md` and `docs/Reference/index.md`. `Packages.md` itself only links to those two landing pages -- it does not enumerate packages.
4. **Add the page** to `Reference/Statements.md` or `Reference/Procedures and Functions.md` if it's a statement or callable and not already listed there.
5. **Run the [site integrity check](WIP.md#site-integrity-check)** after the batch and before committing.

Expand All @@ -342,12 +341,11 @@ When in doubt about a tB-specific behavior, check `docs/Features/` and `docs/Ref

**twinBASIC is in a long beta, so a superseded name is not history --- it is noise.**
Document the current API and nothing else. A reader cannot use a name that no longer
exists, cannot search for it, and has to carry two names in their head to read one snippet.
exists, cannot search for it, and would have to keep two names in mind to read one snippet.

Two CustomControls tutorials showed `Public Sub New(Serializer As SerializationInfo)` and
`Deserialize()`, each with a NOTE underneath explaining that the framework actually names
them `SerializeInfo` and `RuntimeUISrzDeserialize()`. Both pages now show the current names
and carry no note; the snippets are shorter and the reader has one name per thing.
Show the current name and no note about the old one. The CustomControls tutorials show
`SerializeInfo` and `RuntimeUISrzDeserialize()`, not the superseded `SerializationInfo`
and `Deserialize()` with a NOTE explaining the difference.

Version-skew notes earn their place when a reader may be *on* the older version --- a
behaviour that changed in a shipped BETA, where the page says which build changed it (see
Expand All @@ -368,22 +366,21 @@ reader's query `check_page_baseline` can never prefix-match. Measured:
| `check_page_baseline` | **0** |
| `check-page-baseline` | 420, as noise --- hyphens split, so it becomes three common words |

`build_dot_metrics` was 0 as well. An evaluator issued seven queries including the gate's
own filename and verbatim prose from its section, and never once saw it --- **the string a
refused developer actually has in hand is the one that found nothing.**
**The string a developer actually has in hand --- the bare script name --- is the one
that finds nothing.**

**The fix was to drop the directory prefix from the headings**, so the token becomes
**So write each script's heading without the directory prefix**, so the token is
`check_page_baseline.mjs` and the trailing wildcard reaches it. Nothing is lost from the
page: each entry's anchor is pinned with `{: #... }` so no URL moved, and the synopsis
page: each entry's anchor is pinned with `{: #... }` so no URL moves, and the synopsis
block on the next line still shows the full `node scripts/<name>.mjs`. Every script name
returns hits now, and the index grew by nothing.
returns hits this way, and the index does not grow.

**Two other fixes were measured and rejected, and both are worth not re-proposing.**
Raising `search.heading_level` to 3 --- so each `###` becomes its own entry, which is what
would give a script section its own title boost and its own anchor in the results ---
**Two other fixes were measured and rejected; do not re-propose them.**
Raising `search.heading_level` to 3 --- so each `###` becomes its own entry, which would
give a script section its own title boost and its own anchor in the results ---
**doubles the index, 3,742 entries to 7,524, and does not fix it**: the titles still carry
the `scripts/` prefix, so the bare query still misses. That is a 3.4 MB payload every page
already downloads, doubled, for nothing. Widening the tokeniser's separator to include
the `scripts/` prefix, so the bare query still misses. That doubles a 3.4 MB payload every
page already downloads, for nothing. Widening the tokeniser's separator to include
`/`, `_` and `.` is the other obvious proposal; the `check-page-baseline` row above is
what it would do to *every* path token on a site whose subject matter is `Debug.Print`
and `_App`.
Loading
Loading