Spaces:
Running
Running
Commit History
20 days ago
-
fix(pipeline): read pytest's quiet summary; a token without Checks reads as no checksβ
Both seen on the first deploy through the pipeline (2026-10-22, test-mcp = 3108c38): - `pytest -q` ends with a bare "3 failed, 2049 passed in 40s" line; the run recorded "pytest exit 1" because the parser wanted the ===== border. - The sync's first pass answered 403 on the pull request list (the token was created without the Pull requests permission: boone's to fix). A token with Pull requests but not Checks would still have failed the whole sync on the check-runs call; that now reads as "none" for that PR. Docs: the exact token permissions in docs/development_process.md; the sprint doc records the first deploy and what is left. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>4637f97 -
fix(pipeline): the lock file lives beside the worktree, not inside itβ
git refuses to create a worktree in a directory that already holds anything, and the first real run had created the directory for its own lock file. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>f1d74d1 -
fix(pipeline): fold in commits pushed straight to the Space; a token without repos never stops the serverβ
Two things the first real pickup run met on 2026-10-22: - The test Space was ahead of develop by two commits another session had pushed to it directly (settings document, Data Adjuster LLM fix). The push would have been refused as a non-fast-forward. The run now merges the Space's own commits into the integration branch first (--no-ff, a conflict is reported, not forced), so nothing on the Space is lost and the push is a fast-forward. Recorded on the deployment note. - GITHUB_TOKEN landed on prod too, with no TRACKER_REPOS. The server used to raise at startup on that half config, which would have taken prod down at the next promotion. The poller is now skipped with a loud log line; the sync runs only on the Space that has TRACKER_REPOS (test). Also: the job and the CLI load the nearest .env when run from a worktree; the launchd job runs the pipeline worktree's own copy of the script, so it always runs the integration branch whatever boone's checkout is on; the third pβ¦02321f4 -
chore(pipeline): the pickup run, worker and tracker CLI are executableβ
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>81be5c5 -
feat(pipeline): the pickup run, the agent worker, and the process they implementβ
Every change on a branch off develop, a PR in, approved on arrival for Mike and Jack and by one of them for everyone else, picked up four times a day and pushed to the test Space. Everything that writes to GitHub or Hugging Face runs on boone's Mac under his own credentials; the server only reads. - scripts/pipeline_run.py: queue -> merges in its own pipeline/ worktree (detached, --no-ff, a conflict skips with a note) -> unit suite with the known-failures allowlist -> push origin -> three-minute idle gate on the Space -> push hf-mcp-test -> ping confirms the sha -> deployments row and "on test-mcp" notes. Never prod, never a red suite, never a non-fast- forward. --dry-run reports against the real tracker. - scripts/launchd/com.demoprep.pipeline.plist: 7:30 / 11:30 / 15:30 / 19:30 local time. scripts/pipeline_known_failures.txt: the pre-existing failures. - scripts/agent_worker.sh + agent_worker_prompt.md + tracker_cli.py: the agent's turn β top task, agent/t<id>-<slug> oβ¦62f3e9a
23 days ago
-
feat(portal): login-clone pipeline β branded TSE login pages (prototype)β
Automates the hand-built branded login page (Firework/Snowrise/Travel Oregon) so a headless DemoPrep build can produce it. Prototype: capture, generate-verify- repair, the shared kit, real imagery and exact styles are built and tested end to end. The integration into builder.py / mcp_server.py is documented but NOT wired up yet, so nothing here runs until that step β merging is inert. Key design (do not undo): the model builds a MARKETING page only and never writes a login form β a fixed SignInDialog owns all credentials. This clears the Anthropic "cyber" refusal that reproducing a login page from a screenshot triggers, and keeps the SE password in one reviewed file that posts only to ThoughtSpot. Full rationale + the remaining integration steps are in demoprep_app/portal/login_clone/HANDOFF.md. - login_clone/: capture.py, generate.py, contract.py, __init__ (clone_login), LOGIN_CONTRACT.md, HANDOFF.md, three worked few-shot examples - template-tse kit: SignInDialog (fixed credentiaβ¦aa1927e
-
Merge origin/drop-cors-block into integrate/test-2026-09-28
cbde6ef
-
Drop cors_setup_required from the build resultβ
Every successful build returned a block telling the caller to add the portal's host to the cluster's CORS whitelist. The block itself says why that is the wrong place for it: `one_time: true`, because every portal is now served from one shared host and told apart by path, so once the entry exists no future build needs another. So it was correct exactly once per cluster and noise on every build after - and a block that is safe to skip nine times out of ten teaches the reader to skip it the tenth. The requirement has not gone away. It is one-time cluster setup, alongside the TS_ENV table and the trusted-auth key, and nothing a build can act on: the credential a build holds is trusted auth acting AS the SE, while a CORS entry needs cluster admin on Security Settings. The docstring now says where it belongs, and config_check already exists to answer "what does this cluster need". scripts/build_portal.py was the only reader - it printed the block - and now prints the download link insteaβ¦24359dc -
Merge branch 'prod/mcp' into integrate/test-2026-09-22
0ff105b -
docs(deploy): prod/mcp is the MCP production line; deploy/mcp is test-onlyβ
deploy/mcp now carries unreleased work (~70 commits on 2026-09-22), so the old documented step 'git push hf-mcp deploy/mcp:main' would ship all of it to prod. prod/mcp (created at ed4c240, what prod runs) is the only branch that deploys to hf-mcp. CLAUDE.md gains the three flows: normal work to test, full release, and hotfix/selective release off prod/mcp that leaves the test Space alone. whats_deployed.py compares prod against prod/mcp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>7bd6b89 -
docs(muze): MUZE_ENGINE_MAIN_TABS defaults ON since 56a7b8e β the variable is now the emergency offβ
The flag-docs branch (0c60520, written 09-21) still described unset = off. Code (golden_layout.muze_main_tabs_enabled) has read unset as ON since 2026-09-22, and prod runs that default since the d11d3d5 push at 16:48 EDT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>4162a45
-
docs(muze): per-Space variable rules + Space-variable helper scriptβ
MUZE_ENGINE_MAIN_TABS shipped to test-mcp in d04a84e with the variable set. This adds what an operator needs around it: the README "Per-Space variables" table, the CLAUDE.md deploy rule (set the variable BEFORE pushing, verify with config_check, never a code flag again), scripts/set_space_variable.py (show/set/delete with --dry-run and the restart warning) and the loop-harness docstring (export MUZE_ENGINE_MAIN_TABS=true to exercise the engine locally). A parallel implementation of the same switch (DEMOPREP_MUZE_MAIN_TABS, read at import, exposed via ping and the startup line) was superseded by d04a84e and dropped; it is kept as backup/muze-space-flag-dup only for that exposure idea. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>0c60520
-
deploy: golden-demo-v3 merged into the MCP line (squashed for HF)β
Squash of merge/golden-into-mcp (8b7aa14 + 0cd2d8a). Full history is on GitHub at merge/golden-into-mcp; this is squashed because HF Spaces' pre-receive hook rejects binaries anywhere in the pushed history, and the other branch's portal vendoring carried a 707KB figma-reference.png. Deleting it at the tip was not enough β the blob was still in the pushed commits. It was dead weight anyway: apply-spec.mjs:356 already lists it under 'remove stale template assets'. Brings the third page and the Muze viz styling onto the line the Space runs β SEs demoed today and asked where the third page was, and the answer was that it had been built on a branch that was never merged. Contents: SHOWCASE_TAB (third page) + muze_templates.py; Demo Guide tile moved to the Showcase tab (boone's ISS-5 ruling: move, not remove); MANAGER_MIN_TILES 1 -> 3 with the strongest remaining chart protected from promotion, retuned once against three tabs; three duplicate fixes collapsed to one each (the secondary-axisβ¦635b8b1
-
fix(portal): the default brand collided with the template's own constantsβ
Live evidence β runs efbfe328b1ca (Nuvocargo) and 8208c1c14de8, both: portal build failed (PortalBuildError): derived light token --sl-evergreen='#12283f' collides with cssSwaps key '#12283f' cssSwaps LEFT-hand keys are the template's hardcoded constants, and the default primary was #12283f β one of those very constants, picked from the template's own palette when the builder was written. Deriving a token equal to a swap key means the codemod rewrites the token after generating it, which _check_swaps correctly refuses. So EVERY portal that passed no colours failed β which is every portal chained off build_demo_from_brief. That is why the runs produced no TSE site. The guard was right; the default was wrong. Default primary is now #123a5c, verified collision-free, and the CLI default matches so both paths agree. Tests pin the invariant: the default brand must survive its own guard, the default must not be a cssSwaps key, and #12283f must STILL fail β so nobody "fixes" a future cβ¦4545fe1 -
fix(portal): the extracted brand can now actually reach the builderβ
f2a1292 widened theme()/swaps() to take all 8 extracted values, but no caller passed them β mcp_server.build_portal and scripts/build_portal.py still sent only primary/accent. So every real build got surface=#ffffff, Inter, and template radii, and the feature existed only inside its own unit tests. Worse, demoprep_app/portal/intake.py:44 already tells the interviewing agent that font.family fills font_family β an SE was being asked for a value that was then silently dropped. That is exactly the "no silent fallbacks" rule. Adds surface_color, font_family, button_radius, tile_radius, base_font_size, heading_scale and estimated to the MCP tool and as flags on the CLI, threaded to the builder. Empty means "not extracted" and only that one value falls back, so a partial extraction still improves on the default. `estimated` is comma-separated names of whichever values came from a screenshot rather than the prospect's CSS; it lands in spec.brandProvenance so a reviewer can tell read-from-rβ¦61a5937 -
feat(portal): one Space, many portals β one CORS entry per cluster foreverβ
A Space per portal meant a cluster allowlist entry per portal, because HF subdomain wildcards are rejected by ThoughtSpot's validation. That does not scale: every new demo needed a manual security-settings edit before its filters would load. Now every portal is served from ONE shared Space and told apart by path: https://<owner>-portals.static.hf.space/<slug>/index.html so a single allowlist entry covers every portal, present and future. The result payload says so explicitly (cors_setup_required.one_time). How it works: - Portals build with `vite --base=/<slug>/` so absolute asset paths resolve under the subpath. Verified: /advancedmd/assets/*.js and *.css both 200. - The template has no path-based routing (tabs are useState + sessionStorage), so nothing cares where it is mounted β no SPA fallback needed. - upload_folder(path_in_repo=<slug>) puts each build in its own subtree. - A generated root index lists every portal on the Space, so trimming the path off a URL no longβ¦e068980
-
fix(portal): act-as user, and a real error when a model is unreadableβ
Building a portal over another SE's liveboard failed with a raw KeyError: 'edoc'. TML export is permission-scoped β a model owned by another user comes back FORBIDDEN with an `info.status.error_message` and no `edoc` at all, and the code assumed every returned entry carried TML. - model_columns() now detects entries without `edoc`, surfaces the cluster's own error message, and on FORBIDDEN says what to do about it (build as the owner, or have them share). No traceback. - build_portal(as_user=...) / --as-user selects the ThoughtSpot identity via trusted auth, so a portal can be built over a liveboard whose model belongs to the SE who ran the demo. Found building AdvancedMD (mani.uppala's 2026-08-31 run, liveboard d8e70d02): unreadable as boone, 9/9 TML entries as mani. (cherry picked from commit 119111ef28c743f310c50ef48f3f112b207cabce)6e10d0d -
docs: single state-of-play snapshot + HF_TOKEN in the test-secrets scriptβ
The state had drifted across five branches, four Spaces and several sessions, and reconstructing it repeatedly cost more than the work. docs/STATE_OF_PLAY_2026_09_01.md records what is deployed where, which token lives where (and which one can never be read back), what exists only on this disk, the gotchas already encoded in code, and the open defects β all verified by inspection rather than memory. Also adds HF_TOKEN to setup_test_mcp_secrets.py's REQUIRED list. It was absent, so the test MCP Space had no HF_TOKEN and build_portal would have built a portal successfully and then failed on publish β a failure the health endpoint cannot distinguish from a healthy Space. (cherry picked from commit 591b95d4b10fc98488a001879f27770f557d3cf3)5caaf60 -
feat(mcp): build_portal tool β portals inside the automated pipelineβ
A CLI a human runs is not usable by the automated flow, so the portal build is now an MCP tool. Three parts: demoprep_app/portal/builder.py β the logic as an importable function. build_portal(...) -> dict, raising PortalBuildError with a specific message instead of exiting. Extracted from the CLI so the MCP tool and the CLI share one verified implementation. mcp_server.py β @mcp.tool() build_portal(...). Identifies the liveboard EITHER by run_id (GUIDs and company recovered from _recent_builds, so an agent can chain straight off build_demo_from_brief) OR by liveboard_guid directly. Synchronous: the build is ~1 min, well inside the tool timeout, so there is nothing to poll β unlike build_demo_from_brief. Bounded by its own 2-slot semaphore rather than competing for build slots. Returns the URL plus a cors_setup_required block naming the exact hostname the cluster needs; wildcards are rejected, so that step cannot be automated and must be reported instead. Dockerβ¦d301844
-
feat(portal): one-command portal build from a deployed liveboardβ
scripts/build_portal.py replaces the manual spec-by-hand / codemod / npm / huggingface_hub sequence with a single command: python scripts/build_portal.py --liveboard <GUID> --company "Acme" \ --space acme-portal It authenticates to the cluster, derives the model GUID from the liveboard, reads the model's columns, authors spec.json, runs the codemod, applies the known post-codemod patches, builds, and (with --space) creates/updates a static HF Space and prints the URL plus the exact CORS entry required. Encodes the lessons from the 08/25-26 debugging rather than repeating them: - Date column is chosen from the SAME fact table as the chosen metrics. The first draft of this script picked `Relationship Month` (CARRIER_RELATIONSHIP) for metrics on LOAD_TRANSACTIONS β exactly the cross-fact chasm of ISS-2, where the filter looks fine but slices a table the measures don't live on. pick_date() now fails loudly, naming the facts, rather than falling back to any date. -β¦0c17e43
-
feat(portal): bring portal builder into the codebaseβ
The portal work existed only in scratch/ (gitignored), so two live portals had no versioned source. Promotes the verified pieces into the repo. demoprep_app/portal/ - template-tse/ + scripts/apply-spec.mjs + references/, vendored from thoughtspot/tse_demos at pinned commit 0c68520f (node_modules and dist excluded; the codemod installs deps itself) - specs/{triumph,vantage}.json β real worked examples with live sebe GUIDs - assets/ β placeholder logos those specs reference - README.md β provenance, usage, and the four gotchas found while verifying (single-token `client`, dangling imports after tab pruning, unconditional spec fields, exact-host CORS requirement) scripts/data_repair/ β the three zero-measure/TML repair scripts, reusable patterns for the next run that hits the generator defect docs/portal_template_spike.md β spike findings (dev_notes/ is entirely gitignored, so tracked docs go in docs/) .gitignore β negations so the broad *.json and lib/ rulβ¦4549294