scripts/enterprise-server.sh builds and runs qqq-all's enterprise profile
(branch feat/enterprise-terminal-test in .worktrees/qqq-all-enterprise)
on port 8078 against the UI API 1.9.0 fix-branch build: MOCK auth, every
locally runnable qbit, the qqq sample app, Redis and OpenSearch in Docker
for redis and quick search. --status and --stop only touch the pid it
started and the two containers it names; it never touches the 8077 sample
server.
scripts/enterprise-smoke.sh runs the CLI through each qbit surface (ESB,
alerts, assistant, collaboration, data analysis, DB performance, QA
capture, quick search, release notes, secured data, SQL workbench, jobs,
audits, saved views and reports, exports, webhooks, processes) and records
exit codes, so client and server gaps show as non-zero lines.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
scripts/print-agent.sh runs qqq-print-agent's virtual file printer against
a local server with the printing qbit (the enterprise server on 8078 by
default): it enrolls and approves itself the first time and writes each
job to a directory. README and CHANGELOG (1.0.0, Added) describe qqq print,
qqq printer and the TUI's Print action.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CHANGELOG 1.0.0 gains the -o/--order convention with its migration note
and the extension table output under "Changed since 1.0.0-rc.1", and the
ESB trigger, login profile, health fallback and conformance fixes under a
new "Fixed since 1.0.0-rc.1". README, the cli and conformance package
READMEs, TRY-IT, the 1.0.0 release notes and the parity matrix (and its
generator) use --order for the sort and -o/--out for files.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The cli-windows-x64 lane failed in every package with "Could not find
...\dist\test\*.test.js": npm runs scripts with cmd.exe there, which
does not expand globs, and Node 20 does not glob its own arguments.
Plain "node --test" is no fix on Node 20 either, because its default
patterns run every file under a test directory, helpers such as
harness.js and stub.js included.
scripts/run-tests.mjs lists the *.test.js files directly in dist/test and
spawns node --test with them, so all four packages run the same files on
every platform. Counts on macOS are unchanged: 18, 167, 3 and 100.
Two cheap Windows fixes in the CLI test harness: the sandbox sets
USERPROFILE as well as HOME (os.homedir() reads USERPROFILE on Windows,
so defaults would have escaped into the real profile) and QQQ_STATE_DIR,
and the golden-file normaliser turns backslashes in sandbox paths into /
so export-download-dir.txt matches there too.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The installer took the newest cli-v* release including prereleases, so
after 1.0.0 the next release candidate would have reached curl users
while Homebrew and Scoop stayed on the stable channel. It now picks the
newest release whose "prerelease" is false; --pre (or QQQ_PRE=1) opts
into prereleases and --version still pins one.
--help printed nothing under curl | sh because it read the script back
with sed from "$0"; the help is now a heredoc. The Windows hint says to
add the QRun-IO scoop bucket before scoop install qqq. A --dry-run option
prints the resolved version and URLs, which made the change testable:
sh -n and shellcheck are clean, and dry and real runs against compact
and pretty-printed release lists and a file:// mirror pick 1.0.0 over a
newer rc, the rc with --pre, and ignore tag_name/prerelease text inside
release notes. The README install section documents the stable default.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Found on the fix-branch sample (8bf6a5a66, private server on 8091): grid
cells showed REVEAL secrets and raw RENDER_HTML; they are now drawn like the
record view (masked, text, CHIP brackets). A WIDGET-adorned field with a
plain value shows the value. Create forms ask for a text primary key (the
archive table's file name) and leave out generated numeric keys. Parity
notes record what was verified live there: weekday criteria (QRY-085
pass), case-insensitive matching, AdornmentLab adornments, the composite
association, the locker refusal, uploads and downloads, sharing, saved
report setup, help. NAV-030 and PRC-020 stay blocked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/release-notes/1.0.0-rc.1.md is the user-facing release body (install
table, the Gatekeeper and SmartScreen notes, getting started, what is in
it, known limitations), with the exact rc.1 command sequence for James
in an HTML comment that GitHub does not render. release.mjs prints
--notes-file with that file when one exists for the version, else the
CHANGELOG section.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
scripts/soak.sh drives the real TUI in tmux with random keys from the keymap
(F-keys, arrows, paging, Tab, Esc, Enter, single keys, : commands) and fails
on an exit or an error boundary, keeping the last 20 frames; nothing that
quits, saves, confirms a delete or exports is sent (QQQ_UI_NO_QUIT=1 ignores
a Quit chosen from a menu). The theme picker keeps a theme for every profile
or this one. README and TRY-IT: options, environment, per-screen keys, the
settings file, themes. SEC-030 is blocked on qqq-cli#10 and qqq#1359.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The navigation, widget and report rows were the last open CLI rows. The kernel render model now
follows the web's widget contracts (multiStatistics values, location, usaMap, generic, cronUI,
dynamicForm, pivot and filter setups, rowBuilder, every composite block, table extras, chrome,
empty states, the dropdown message), and a loader fetches widgets as ConnectedWidget does:
metadata first (unknown or denied widgets cost no request), parent widgets load their children,
data bag and script viewers read their records, dashboards load every widget once at once.
On top: qqq home, qqq find, apps show --widgets, widget get --record/--run; report run through
the report's process (input fields, GET /download) or the report route; qqq saved-report
(show, preview incl. through an application API, run, set filter/sort/columns, pivot, schedule)
and qqq share for any shareable record. A WIDGET-adorned filter field in a process takes the
filter grammar. Printed filters no longer mark case-sensitive matches (the TUI builds criteria
without options, and its footers must not change).
The sample has no reports, saved reports or editor widgets; stub-server CLI tests cover them.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
AUTH_0 signs in in the browser (authorization code + PKCE with the API
audience, code exchanged at the tenant, the token handed to manageSession)
and can end the Auth0 session on sign-out. F1 uses the kernel's help
entries (app, widget, instance, table, process, step) with readable places;
:helpkeys shows every help slot key. The grid footer shows the column's
help. scripts/perf-large-table.sh times a 10,000 x 40 table on the fake
large-instance server: first page ~100 ms, record 10,000 ~40 ms, column 40
~350 ms. Parity: TUI 330 pass, 67 n/a, 3 blocked, 1 todo (SEC-030: needs a
real Auth0 tenant).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TABLE_BASED servers could not be signed in to at all. The server's TableBasedAuthenticationModule
accepts HTTP Basic credentials on any route, inserts a session and answers with a sessionId
cookie; qqq login --username now does that once (password asked, or QQQ_PASSWORD), keeps only
the session and sends it as the sessionId cookie, which the typed client could not do, so the
CLI wraps its fetch. A refused password stores nothing; logout ends the session.
AUTH_0 servers were refused by the native sign-in discovery. The client now builds the sign-in
from the tenant, the native (or SPA) client id and the audience, which Auth0 needs to issue a JWT
the server can verify. No AUTH_0 server exists to run it against (finding 28).
DISABLED tables and processes come in the metadata with their permissions false; the CLI lists
them with the reason and refuses query, writes, copy (insert needed), bulk commands and process
run before any request, as the web explains the denial.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
qqq ruled that CONTAINS, STARTS_WITH and ENDS_WITH are case-sensitive by design (finding 11,
qqq#1344) and that clients opt in per criterion with CriteriaOption.CASE_INSENSITIVE. The
grammar and quick search now add the option to every text match; ~= , OPERATOR:CS and
--case-sensitive ask for a case-sensitive match, and printed filters mark those with :CS.
The option does not reach the backend over v1 yet: QFilterCriteriaDeserializer ignores
options and the spec does not declare them (finding 27), so matching stays case-sensitive
until the server reads it. Finding 26 records the bulk mapping suggester problem the kernel
works around (it was cited as finding 11 by mistake).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The CLI column moves to 232 pass, 2 blocked (finding 19 for variant writes, finding 24 for
weekday criteria on H2) and 1 partial (NAV-028, navigation group next). Rows the sample cannot
exercise say unit-tested or stub-server tested in their note.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Bulk insert and bulk edit with a file (file navigator upload, column mapping
grid with typed defaults and field help, value mapping with the picker,
review with optional validation, result), bulk edit (switched-on fields) and
bulk delete; saved bulk load profiles (yours and shared, owner-only update
after a confirm listing the changes, delete); the upload template; table
actions list the bulk actions with their CLI commands. Verified live on the
sample: 2 person rows loaded from CSV, bulk edited, bulk deleted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bulk rows (PRC-016, 029-034, 046, 058-061, QRY-031/032/034) are verified live against the
sample, except saved profiles, which the sample does not offer: those are covered by a stub-server
CLI test. The matrix script gains a blocked status (a note must cite a server finding) so the
release gate can tell a server limitation from unfinished work.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Record view value columns start from the field set (DATE_TIME 30, dates,
numbers, text length) as well as the first record, so an empty first
record no longer cuts later values; still fixed while stepping.
Parity TUI column: the partials resolved: passes (live or unit-tested, said
in each note), browser-only n/a with the reason (icon fonts, logos, URL
state, rich-text and code editors), and blocked on server findings 13
(cancel keeps the run) and 21 (no search provider). Remaining partial: report
runs, the 10,000 x 40 budget, ad hoc widget buttons, bulk load (parked),
OAuth authorization code + PKCE.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The orb (PR #165) publishes all four packages as rc when any of them is
a prerelease and as latest only when all are final. The readiness gate
gains a package-versions line that refuses a final CLI version while
client, core or conformance is still a prerelease; release.mjs derives
the dist-tag from all four. The runbook's version table, the rc-to-final
step and the publish step follow the rule, and its signing step now
uses sign-macos.sh and sign-windows.sh.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
sign-macos.sh signs the darwin binaries with a Developer ID under the
hardened runtime with Bun's documented entitlements, notarizes them
(keychain profile or App Store Connect key) and recomputes SHA256SUMS;
sign-windows.sh Authenticode-signs the .exe with osslsigncode. Both read
everything from environment variables, exit 0 with what is missing when
it is not set, and have --dry-run. Checked here: both no-op messages and
dry runs; an ad-hoc hardened-runtime signature with the entitlements,
after which verify-binary.sh against the sample server and the qqq ui
tmux smoke still pass; and a real osslsigncode signature with a
throwaway self-signed certificate in Docker, which verifies against
that certificate and changes the recorded checksum. Notarization and a
real Developer ID or Authenticode certificate were not available.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
scripts/readiness.mjs reports what a final release still lacks: parity
rows that are partial or todo in the CLI or TUI column (a blocked row
must cite a finding or issue), server findings without an issue link, a
missing CHANGELOG entry for the version, and qqq commands quoted in
README.md and TRY-IT.md that the program (createProgram from the built
CLI) does not have. release.mjs refuses a non-prerelease version until
the report is clean, prints it as information for a prerelease, and
--check prints only the report. Today: 122 CLI and 152 TUI rows open,
everything else clean.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A prerelease keeps rc and --prerelease; 1.0.0 prints --tag latest,
--latest, and the dist-tag commands that move latest while the orb
still publishes everything as rc. The printed packaging step names the
tap's formula path and the signing step.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Version with "binary with ui", completion for four shells, qqq ui
--check naming the build, and with a server: login, doctor, whoami, a
query and a process run, in a temporary profile (file keyring, or the OS
keyring removed again). Run here on darwin-arm64 (both keyrings), in
Debian amd64, and the .ps1 under PowerShell 7 in a Linux container, all
against the sample server; never on Windows. The proposed lane YAML now
calls them and still validates; ci-lanes.md says Windows x64 and macOS
x64 stay unverified until the lanes run.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
docs/packaging/homebrew-tap/ is the whole tap repository (formula,
README, LICENSE, qqq-orb homebrew-tap profile); the formula moves there
as the single source, installs only bin/qqq with completions, says qqq ui
is bundled, and its test fails on a binary without the UI. The binary is
chmod 0755 before install: Homebrew downloads arrive without the
execute bit and the completion step runs the binary (found by installing
the formula in the homebrew/brew container, where it then installed,
passed brew test and wrote the three completion files). The Scoop
manifest describes the with-UI binary and notes the ConPTY requirement.
The packaging README covers Gatekeeper without notarization and the
xattr workaround, SmartScreen, and what is still unverified.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The TUI batch (fixed-height rows, uploads and downloads, sort, process
screens, saved views, variants), so the with-UI binary carries it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
James's decision: one qqq binary per platform with the UI is the release
artifact. npm run binaries and release.mjs bundle the TUI unless
--cli-only. Both entries now start the built CLI (packages/cli/dist),
the module the TUI imports as @qrun-io/qqq-cli/program, so the CLI
program is in the bundle once (darwin-arm64: 100.8 -> 100.5 MB; the rest
of the 16 MB over the CLI-only build is React, OpenTUI and its native
library).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Process step forms show DATE_TIME inputs in the local zone and send UTC
instants (kernel datetime); processes launched from a variant grid carry
tableVariant through the runner.
scripts/parity-matrix.py: the TUI column re-scored against what is built
now. Priority families (NAV, PRF, PRC, QRY, REC, REL): 150 pass, 44
partial with a reason, 13 named todo, 42 n/a. All rows: 180 pass, 49
partial, 103 todo, 69 n/a.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
release.mjs passes --with-tui to the binary build. docs/packaging
records the three ways tried to ship qqq ui (one binary with the UI, a
second qqq-ui binary, npm with Bun), the sizes, what was smoke-tested
and what was not, and recommends one qqq binary with the UI bundled.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
scripts/binary-with-tui.ts is a Bun-only entry that registers the
bundled TUI and starts the CLI, so the Node build is untouched. The
build installs OpenTUI's native package for every target (bun install
--os='*' --cpu='*' in packages/tui), pins OPENTUI_LIBC per Linux libc
and defines QQQ_BUILD_UI, which qqq --version prints as "with ui".
Source maps that bun writes beside each binary now go to
dist/sourcemaps/, so the release glob dist/qqq-* no longer uploads them.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Developer mode and the TUI batch (Home screen, search-first F9, the
metadata index, audits, tags and developer screens).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
scripts/install.sh picks qqq-linux-<arch>-musl on Alpine, so a release
without them would leave those hosts with a 404.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The TUI is neither published nor bundled into the qqq binaries yet, but
it builds on the same kernel, so a release that breaks it should stop.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Brings in the TUI package and the hardening review (createProgram in
program.ts, qqq doctor, the golden-output suite). Resolutions: main.ts
from the base; program.ts prints versionText(), whose second line now
starts with "UI API client <version>" as the golden test expects and
adds the supported server range; the CLI package keeps the release
metadata with the base's exports and its new conformance dependency,
and conformance goes to 1.6.0-rc.2 because the CLI now ships against it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Brings in the TUI stream (program.ts with createProgram and runCli, the io
object, qqq ui, session/login, local-state, filter completion, the result
cursor, the file navigator and env/doctor). Resolutions:
- main.ts is the base's thin entry; it still awaits the 0.1 credentials import.
- program.ts carries the option fixes (--version only, --server without -s)
and registers qqq doctor.
- One set of ui helpers: the TUI's. readUiSettings/writeUiSettings are gone;
qqq config set|get download-dir, upload-dir and download-mode use
readFilePreferences/writeFilePreferences (ui.files), and the new
qqq config set|get theme uses readTheme/writeTheme. readConfig keeps the
corrupt-file refusal and unknown sections; the profiles test covers files,
theme and an unknown section together.
- qqq doctor's terminal rows come from checkEnvironment, with formatReport
under the table; --fix asks before each applyLiveFix and calls
appendTmuxConf only after a y typed at a terminal.
- runCli and the prompts coexist (stdin is not a terminal in runCli, so
prompts refuse; direct stdout writes are captured), tested in a child process.
- @qrun-io/qqq-ui-api-conformance is a dependency of the CLI package.
- The parity matrix is regenerated; docs/review-2026-10-31.md records each
merge decision.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/review-2026-10-31.md lists each finding of the fresh-eyes review, its
severity and the fix (or why it was left). TRY-IT.md was run block by block
against the sample server and corrected: placeholders written as commands,
missing upload files, record ids the shared data no longer matches; it now
documents the option names shared by every noun, the footer, the exit codes
for a no, Ctrl-C and gateways, the download directory and qqq doctor. The
parity matrix notes REC-022 (BLOB upload and download) as verified and the
REVEAL masking in lists.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/install.sh picks the binary for the machine (musl on Alpine,
native arm64 under Rosetta), verifies it against the release's
SHA256SUMS and installs to ~/.local/bin. qqq.rb and qqq.json follow the
qctl tap and bucket shapes; scripts/update-packaging.mjs fills their
version and checksums from the uploaded release so nobody pastes sums
by hand. The formula writes its own #compdef zsh file because the
output of qqq completion zsh is an eval script, not an fpath file.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
packages/tui/README.md: running it, keys, screens, the : commands, the local
settings, the keys terminals and tmux may take (with the alternate_on
rebinding), tests and the code layout. TRY-IT.md replaces the spike section
with the qqq ui section. scripts/parity-matrix.py gets a TUI status table
and a TUI summary; feature-matrix.md regenerated (TUI: 118 pass, 25
partial). Server findings: recordSearch advertised with no provider, and
the untyped multiStatistics group (statisticList).
Also: -o -field in : commands and qqq ui routes, ASCII title separators,
short F-key labels at 80 columns.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Clean tree, free tags, npm ci, the orb's generate-drift, build and test
steps, lint, npm pack dry runs and the binaries; then it prints the
signed tag, npm publish and gh release commands. It never tags,
pushes or publishes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>