Skip to content

build(deps): bump actions/upload-artifact from 4 to 7 - #5

Merged
mlcyclops merged 1 commit into
masterfrom
dependabot/github_actions/actions/upload-artifact-7
Jun 20, 2026
Merged

mlcyclops merged 1 commit into
masterfrom
dependabot/github_actions/actions/upload-artifact-7

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jun 20, 2026

Copy link
Copy Markdown
Contributor

Bumps actions/upload-artifact from 4 to 7.

Release notes

Sourced from actions/upload-artifact's releases.

v7.0.0

v7 What's new

Direct Uploads

Adds support for uploading single files directly (unzipped). Callers can set the new archive parameter to false to skip zipping the file during upload. Right now, we only support single files. The action will fail if the glob passed resolves to multiple files. The name parameter is also ignored with this setting. Instead, the name of the artifact will be the name of the uploaded file.

ESM

To support new versions of the @actions/* packages, we've upgraded the package to ESM.

What's Changed

New Contributors

Full Changelog: actions/upload-artifact@v6...v7.0.0

v6.0.0

v6 - What's new

[!IMPORTANT] actions/upload-artifact@v6 now runs on Node.js 24 (runs.using: node24) and requires a minimum Actions Runner version of 2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.

Node.js 24

This release updates the runtime to Node.js 24. v5 had preliminary support for Node.js 24, however this action was by default still running on Node.js 20. Now this action by default will run on Node.js 24.

What's Changed

Full Changelog: actions/upload-artifact@v5.0.0...v6.0.0

v5.0.0

What's Changed

BREAKING CHANGE: this update supports Node v24.x. This is not a breaking change per-se but we're treating it as such.

... (truncated)

Commits
  • 043fb46 Merge pull request #797 from actions/yacaovsnc/update-dependency
  • 634250c Include changes in typespec/ts-http-runtime 0.3.5
  • e454baa Readme: bump all the example versions to v7 (#796)
  • 74fad66 Update the readme with direct upload details (#795)
  • bbbca2d Support direct file uploads (#764)
  • 589182c Upgrade the module to ESM and bump dependencies (#762)
  • 47309c9 Merge pull request #754 from actions/Link-/add-proxy-integration-tests
  • 02a8460 Add proxy integration test
  • b7c566a Merge pull request #745 from actions/upload-artifact-v6-release
  • e516bc8 docs: correct description of Node.js 24 support in README
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v4...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot @github

dependabot Bot commented on behalf of github Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

Labels

The following labels could not be found: ci, dependencies. Please create them before Dependabot can add them to a pull request.

Please fix the above issues or remove invalid values from dependabot.yml.

@mlcyclops
mlcyclops merged commit 9fca383 into master Jun 20, 2026
5 checks passed
@dependabot
dependabot Bot deleted the dependabot/github_actions/actions/upload-artifact-7 branch June 20, 2026 03:35
mlcyclops added a commit that referenced this pull request Jun 20, 2026
…+ add AGENTS.md (#31)

Review addendum to the user-authored ADR-0020. The auth engineering (PKCE/RFC 8252,
GCP WIF via Entra OIDC + STS, safeStorage) is sound; this adds the integration
discipline it was missing so it builds as an EXTENSION of omp, not greenfield:

- Decision 6 (load-bearing): extend omp, don't fork — omp already accepts mcpServers[]
  in session/new (acp_backend.ts), so the hub does auth + config assembly only and
  feeds authenticated server entries to omp; it does not re-implement an MCP client.
- safeStorage is Electron-main-only → token seal/unseal routes through main.ts+preload
  (the ADR-0010 seam), passphrase fallback in dev.
- Untrusted MCP output must pass the fail-closed gate + be delimited (invariant #5).
- Localhost PKCE catcher: distinct ephemeral port + drain/close (the OAuth bug class).
- terraform/mcp_auth scoped as IaC/docs only — doesn't widen the TS+Python boundary.
- Added phases P-MCP.1–4 (one increment each), recommended first build, and the
  frozen-contract impacts (new EventNames, no migration, registry stays git-ignored).
- Minor: PQC cross-refs ADR-0015 (ML-KEM already FIPS-203); Entra/Okta are the IdPs,
  Yubikey/PIV the factors.

Also adds AGENTS.md — a mirror of CLAUDE.md (the cross-tool agent-instructions filename).

Docs only; no code changed.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
mlcyclops pushed a commit that referenced this pull request Jun 21, 2026
…s, dashboard escaping (ADR-0026)

Five real fixes from the open CodeQL alerts on master:

- #3/#4 js/stack-trace-exposure (desktop/dev.ts, tools/web/server.ts): the catch
  handlers returned String(err) to the client. Now they log the detail
  server-side and return a generic {ok:false,error:"internal error"}.
- #5 js/file-system-race (harness/memory/state.ts): existsSync-then-writeFileSync
  was a TOCTOU. Now a single writeFileSync(..., {flag:"wx"}) (create-or-fail,
  EEXIST-safe); existing files preserved. existsSync dropped from imports.
- #6 js/insecure-temporary-file (harness/personal/store.ts): the encrypted store
  was written then chmod'd, leaving a 0644 window. Now created owner-only via
  {mode:0o600}; chmod kept for the overwrite-existing case.
- #1 js/incomplete-html-attribute-sanitization (tools/web/index.html): the
  dashboard esc() escaped only &<> but its output lands in double-quoted
  attributes — a " could break out (attribute XSS). It now escapes " and ' too,
  matching the desktop renderer's esc.

The eight "File data in outbound network request" alerts (asksage, ratelimit_
probe) are intended API-key transmission to configured provider endpoints and
are dispositioned dismiss-as-by-design. #14/#15 were fixed by #41 (auto-close).

Tests: store-perms assertion (0600); state reopen/no-clobber already covered.
Verified live: a forced handler error returns the generic body with the real
SyntaxError only in the server log. harness 195 pass (+1), desktop 33, root +
desktop tsc clean. ADR-0026 + PROGRESS recorded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FrTqRvkZBtq3NdEExxyCLG
mlcyclops added a commit that referenced this pull request Jun 24, 2026
…every turn) (#54) (#62)

Persona (ADR-0007), bundled skill (ADR-0029), and the <user-profile> personalization
recall (P9.2) were delivered only on the FIRST user turn of a session, then never
re-sent — so in a multi-turn chat the standing guidance faded and the model 'forgot'
the active skill/persona and the learned profile (the custard/knowledge-graph case).

Re-deliver them on EVERY turn. They live AFTER the cache breakpoint (invariant #5/#6),
so re-sending does not bust the frozen-prefix KV cache; the only cost is a few input
tokens per turn — the tradeoff that makes the guidance actually stick. The profile is
re-read each turn (recallPreamble()), so facts learned mid-session show up next turn.
The cross-session <recalled-memory> block stays ONCE per session (a session-start
recall of prior-session facts, not standing guidance). Supersedes the 'delivered once
per session' delivery noted in ADR-0007/0029 for standing guidance.

Extracted the assembly into a pure buildUserTurnPreamble() (desktop/preamble.ts) and
removed the now-unused personaDelivered/skillDelivered/recallDelivered flags. 5 new
unit tests prove persona/skill/profile persist across turns while memory-recall is
once; full desktop suite (277) green; tsc clean.

Co-authored-by: mlcyclops <mlcyclops@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
mlcyclops added a commit that referenced this pull request Jul 5, 2026
…oser/UX fixes (ADR-0162) (#222)

* feat(report): P-REPORT.9 — multi-repo remote fetch + PR aggregation for the Engineering Report (ADR-0160)

The Engineering Report was blind to anything not already on one repo's local
default branch. This adds a repo picker (workspace ∪ recents ∪ tracked repos,
plus add-by-path/clone-URL), a read-only `git fetch` per selected repo (never a
pull — no working-tree mutation), recent-commit aggregation across branches, and
opt-in GitHub PR listing via `gh` — folded into a new "Cross-repo activity" annex.

- harness/brief/repo_activity.ts (+test): PURE parser/renderer; untrusted commit/
  PR text escaped + fence-stripped + capped before the markdown (invariant #5).
- desktop/repo_collect.ts: first-party fetch/branch/log/gh collector (fail-soft,
  timeouts), like cloneRepo — not the agent gate.
- /api/brief POST + /api/report/repos(/add); settings reportRepos; bridge methods.
- Reports panel: checkable repo picker with remote-URL verify surface + per-repo PR
  toggle (GitHub + gh-auth gated), and a hero Generate button with the rail-pill
  chasing-light border. Rail fly-outs now toggle closed on a second click.

Verified: 25 unit tests + demo-P-REPORT.9 green; renderer suite 134 pass; live
across public (mlcyclops/lucidagentide) + private (TechLead187/lucidagentIDEaddon)
repos — commits across 8 branches each + PRs, working trees untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ui): pin composer on short windows + report repo sort (Recent/Name)

Composer clipping: the .body grid's implicit row was content-sized (`auto`), so a
tall column (chat+composer, or a full rail) overflowed the viewport and clipped the
prompt bar / mic when the window was shrunk vertically. Pin the row with
`minmax(0,1fr)` so columns shrink below content — the composer stays at the bottom
and the thread just gets shorter (still scrollable). The nav rail + metrics rail now
scroll instead of clipping; a short-window media query trims the composer footprint
(hides the keyboard hint) so ~3 lines of thread stay visible. Verified 250–380px.

Report repo sort: a Recent/Name picker in the Repositories header (persisted to
localStorage). listReportRepos now returns each repo's last-commit epoch; "Recent"
orders by it (desc), "Name" alphabetically. Sort affects display only — the active
workspace pre-check still keys off the server order.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(report): entity-escape pipes in clean() — resolve CodeQL js/incomplete-sanitization

clean() escaped `|` as `\|` (backslash) without escaping backslashes — an incomplete
sanitization scheme (CodeQL js/incomplete-sanitization, high). Switch to the `&#124;`
HTML entity: table-safe (the markdown parser sees the entity, not a `|`), renders as
`|`, runs after the &-escape so the entity's & stays literal, and introduces no
backslash escaping at all.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: mlcyclops <mlcyclops@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
mlcyclops added a commit that referenced this pull request Jul 6, 2026
…ILL.4/.5, P-SKILLREG.1/.2, P-KB.1/.2/.2b) (#242)

* Build the skills governance suite + the compiled knowledge base

Seven verified increments across two epics, each fail-closed + scan-gated.

Skills governance:
- P-SKILL.4 (ADR-0097): the Agent Skill directory + per-skill management
  (inspect / re-scan / remove), closed-set trust labels, enable/disable.
- P-SKILLREG.1 (ADR-0098): the enterprise registry READER seam
  (Ed25519 verify -> fail-closed scan-gate -> confined install).
- P-SKILL.5 (ADR-0101): Skill Studio (analyze recent work -> model-drafted
  candidates -> gated codify).
- P-SKILLREG.2 (ADR-0102): the publish seam (RegistryPublisher +
  LocalRegistryPublisher + fail-safe PublishDispatcher).

Compiled knowledge base:
- P-KB.1 (ADR-0099): the compiled-page store + gated compile pipeline
  (harness/kb, TS+DuckDB, frozen migration 0011).
- P-KB.2 (ADR-0100): the hybrid retrieval router (vector | compiled | both)
  + kept-in-sync + contradiction flag.
- P-KB.2b: the desktop surface (kbStore + /api/kb routes + a Compiled-KB
  graph view reusing mountGraph in the Knowledge panel).

Invariants held: fail-closed everywhere (dead scanner => quarantine),
keystone #2 (derived/registry content never auto-trusted), delimited
untrusted data (#5), closed trust set (#7), frozen DuckDB migration (#10),
no contracts.ts change (EventNames deferred, inv #8), no Python outside
scanner-sidecar (#2).

Verified: root tsc green; bun test desktop + harness green (modulo the
documented fs_browse / lucid_acp Windows path-sep fails); renderer bundles;
demo-P-SKILL.4/.5, demo-P-SKILLREG.1/.2, demo-P-KB.1/.2/.2b all pass;
BUSL-1.1 headers present.

* Potential fix for pull request finding 'CodeQL / Incomplete string escaping or encoding'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: mlcyclops <mlcyclops@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
mlcyclops added a commit that referenced this pull request Jul 10, 2026
…MARKET.1/.3) (#297)

* Build P-KGPACK.1 (ADR-0205): named, swappable KGs via file-per-KG + registry

The combined "Compiled KB" becomes a set of named KGs. Each KG is its own
kb_graph.duckdb (frozen 0011 reused verbatim - no schema change, invariant #10),
indexed by a new JSON registry that maps a stable Snowflake kg_id + a renamable
name to that file. A default "My Knowledge" KG auto-adopts the pre-existing
kb_graph.duckdb (zero data loss), so no-arg kbStore() stays backward-compatible.

- harness/kb/registry.ts: typed JSON registry (atomic write, corrupt=throw, missing=empty)
- desktop/kb_store.ts: kbStore(kgId?) per-KG resolver + list/active/create/rename/setActive
- 16 tests (registry 10 + resolver 6: adoption, isolation, active-switch) + demo-P-KGPACK.1

Foundation for the KG-pack SKU: .lkgpack authoring/import (P-KGPACK.4) and the
Marketplace "Role KG Packs" hint (P-KGPACK.5) build on this. UI/ingest are .2/.3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Build P-KGPACK.2 (ADR-0205): the named-KG picker (filter-as-you-type)

The combined "Compiled KB" views-menu row now opens a filter-as-you-type
dropdown of named KGs (same pattern as the plugin marketplace): one row per KG
with the active one checked, an origin badge + read-only lock, inline Rename
(shared promptText modal) and a New KG action. The views button reads the
active KG's name in kb mode. Picking a KG activates it server-side then draws
its page graph; re-picking the on-canvas KG returns to Personal (retires the
old single-graph toggleKbGraph).

- kg_header.ts: pure builders filterKgList + kgPickerHtml/kgPickerRowsHtml;
  kgViewLabel gains kbName. User KG names are esc'd (invariant #5).
- bridge.ts + dev.ts: kbList/kbCreate/kbRename/kbActivate over
  /api/kb/{list,create,rename,activate}; a validation error rides on `error`
  and never nulls the list.
- app.ts: openKgPicker popover + pickKg/renameKgFlow/newKgFlow wiring. .kgp-* CSS.
- 15 kg_header tests + demo-P-KGPACK.2 green; renderer+server tsc 0 errors;
  license clean; LIVE server smoke (token+origin gated) proves list/create/error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Build P-KGPACK.3 (ADR-0205): seed a named KG from a folder, gated

A KG is now seedable, not just selectable. A ChatGPT/Claude/Gemini export or an
Obsidian markdown vault becomes one document per conversation/note, batch-compiled
into a chosen or newly-named KG through the SAME fail-closed pipeline.

- harness/kb/batch_ingest.ts: ingestSourcesIntoKg, a thin loop over ingestDocument
  (all scan guarantees inherited) + batch concerns: cap/skipped, progress, cancel,
  and an honest `errored` count (a compile/backend throw is caught, not admitted,
  not a security quarantine) so one outage can't abort the run.
- desktop/kb_sources.ts: readKbSources normalises a folder to KbSourceDoc[] - a
  vendor export (reusing loadExportData + parseExport, both sides of each convo) or
  an Obsidian vault (bounded .md walk, hidden/system dirs skipped).
- dev.ts POST /api/kb/ingest-batch ({path, name?/kgId?}): `name` creates + names
  the KG at ingest (source_kind chat/obsidian); blocks audited; capped at 50 docs.
- bridge.kbIngestBatch + picker "Import files" action: folder -> name -> gated
  compile -> the seeded KG is activated + drawn, with a counts summary toast.
- 13 tests + demo-P-KGPACK.3 (real scanner: Trojan-Source note quarantined, KGs
  isolated) green; renderer+server+harness tsc clean; license clean; LIVE smoke:
  a vault -> new KG with 7 pages / 9 links compiled by the real model, garbage ->
  friendly error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Build P-KGPACK.4 (ADR-0205): the .lkgpack KG Pack — author + gated import

A KG becomes a portable, signable, sellable artifact: a <slug>.lkgpack directory
holding the KG's kb_graph.duckdb + a manifest.json.

- harness/kb/pack.ts (pure): manifest + canonicalManifestBytes (stable signed
  payload matching JSON.stringify's undefined handling) + verifyPackManifest.
  Trust model: integrity (db sha256 must match); signature = ORIGIN not SAFETY
  (present-but-invalid REFUSED, absent = unsigned/allowed since the scanner is
  the safety gate). Self-contained Ed25519 (harness must not import desktop).
- desktop/kb_pack.ts: exportKgPack (flush via closeKg, hash, sign-if-configured,
  write pack) + importKgPack (mirrors installRegistrySkill: integrity -> origin
  -> re-scan EVERY page fail-closed, any finding/dead-scanner blocks the whole
  import -> register a NEW read-only KG + copy the clean db; never auto-trusted).
  Keys/signer from env, fail-soft to unsigned: public verifies + builds unsigned
  packs, the real signing key is private-repo IP (public-seam split, P-SKILLREG.1).
- routes POST /api/kb/pack/{export,import}; bridge kbPackExport/kbPackImport;
  picker per-row export + Import pack footer action. createKg gained readOnly;
  kgEntry/closeKg added.
- 14 tests + demo-P-KGPACK.4 (real scanner + real Ed25519: signed round-trip
  read-only, tamper->integrity, Trojan-Source page->scan block, untrusted-key
  ->refused) green; renderer+server+harness tsc clean; license clean; LIVE smoke:
  seed a KG (5 pages, real model) -> export -> import -> a read-only pack KG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Build P-KGPACK.5 (ADR-0205): the Role KG Packs storefront (public SKU surface)

Closes the pack arc with the shopfront. A curated, filter-as-you-type catalog of
role/Position-Description KG Packs authored by TechLead 187 LLC; each row is a
hint that links to the product page (the files live in the private add-on repo,
same public-seam/private-IP split as P-SKILLREG.1). The modal's "Import a pack
you own" routes straight into the P-KGPACK.4 gated import (integrity + origin
verified, every page re-scanned fail-closed, installed read-only).

- desktop/renderer/kg_packs.ts (pure): KG_PACKS (5 role packs) + filterKgPacks +
  kgPackRowsHtml/kgPacksHtml, reusing the .mkt-* marketplace styles.
- app.ts openKgPacks() mirrors openMarketplace (scrim, live search, Get-pack ->
  window.open); reached from the KG picker footer ("KG Packs") + a command-palette
  entry. Import action reuses importPackFlow.
- 5 tests + demo-P-KGPACK.5 green; renderer+server tsc clean; license clean; full
  P-KGPACK arc regression 87 tests pass across 13 files.

P-KGPACK arc feature-complete: .1 registry -> .2 picker -> .3 seed-from-folder ->
.4 .lkgpack author+import -> .5 storefront.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Build P-KGPACK.6 (ADR-0205): background KG-seed job — lift the 50-doc cap

Authoring a real role pack means compiling hundreds of conversations (one model
call each); the old /api/kb/ingest-batch capped at 50 to avoid hanging the
request. Now the seed runs as a tracked background job with no cap.

- desktop/kb_ingest_job.ts (mirrors import_job.ts): single-active job, KB-shaped
  progress/result, start/status/cancel, fail-safe (cancel/fail keeps compiled pages).
- dev.ts: /api/kb/ingest-batch now STARTS a job (returns jobId, no cap) +
  /status + /cancel. KB_BATCH_CAP removed.
- bridge: kbIngestBatch returns a start; kbIngestStatus/kbIngestCancel added.
  importKgFlow reuses the shared import pill (progress + Cancel), polls to done.
- 4 job tests + demo-P-KGPACK.6 (120-doc seed, all compile, 0 skipped) green;
  renderer+server tsc clean; license clean; arc regression 91 tests / 14 files.
  LIVE on real data: 6-conversation slice of a 365-convo ChatGPT export -> 75
  pages compiled by the real model -> exported senior-proposal-manager.lkgpack.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* ADR-0206 (P-KGMARKET): commerce + entitlement gating for KG Packs (SCOPE/PLAN)

Design for monetizing the KG Pack SKU: Firebase Auth identity + Stripe payment +
a Firestore entitlement ledger fronting the pack pull. Three independent gates —
payment (access), signature (origin), scanner (safety); none substitutes for
another. Firebase Cloud Functions (private) hold the Stripe secret + issue
short-lived signed download URLs only on a verified entitlement (fail-closed).
Decisions baked in: BOTH one-time + subscription licensing; card/GPC self-serve
AND PO/invoice (net-30) for GovCon. Public repo ships only the client check +
the existing P-KGPACK.4 import; keys/functions/pack files are private add-on IP.
Sub-increments P-KGMARKET.1-.4. No build this commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Build P-KGMARKET.1 (ADR-0206): the fail-closed entitlement gate (public seam)

The client-side PAYMENT gate — one of three independent gates (payment=access,
signature=origin, scanner=safety); it never substitutes for the P-KGPACK.4
import gate that still verifies + re-scans a pulled pack.

- harness/market/entitlement.ts (pure): decidePackAction -> signin|checkout|pull
  + isEntitled. Fail-closed: not signed in -> signin; ONLY an active, unexpired
  entitlement -> pull; a lapsed subscription / stale-active / missing record ->
  checkout. Absence is never ownership.
- desktop/renderer/market_gate.ts (public seam): EntitlementProvider interface +
  a fail-closed nullProvider + registerMarketProvider/getMarketProvider (the
  private Firebase provider injects at boot, like the skills-publisher pattern).
- storefront wired: KgPack gains `licensing` (+ One-time/Subscription chip);
  "Get pack" routes through getPackFlow — unconfigured build opens the product
  page (no regression), configured build enforces signin/checkout/pull.
- 16 tests + demo-P-KGMARKET.1 green; renderer+server+harness tsc clean; license
  clean. Real signed-download + install is P-KGMARKET.2 (private).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* kg_packs: Cleared Software Engineer -> subscription (match Stripe)

Reconcile the in-app catalog with the finalized Stripe products (Cleared is a
subscription; GovCon one-time). kg_packs tests green.

* Build P-KGMARKET.3 (ADR-0206): the Firebase client provider

The EntitlementProvider (P-KGMARKET.1 seam) as a thin, SDK-free fetch client over
the private Firebase callables (createCheckout / getEntitlement / getPackDownload).

- desktop/renderer/firebase_market_provider.ts: calls the callables via the
  documented protocol (POST {data} + Bearer <idToken>); auth is INJECTED
  (getUser/getIdToken) so sign-in is a swappable concern. registerFirebase-
  MarketProvider registers into market_gate only when configured; unconfigured
  stays on the fail-closed nullProvider (no regression). Missing token ->
  null with no network call; callable error -> null (decision core re-checks).
- 6 provider tests (mocked fetch + auth); 22 market tests total; renderer tsc 0;
  license clean. getPackFlow already routes through the seam, so it activates
  the moment the provider is registered.

Sign-in flow + the download->unzip->gated-import bridge are P-KGMARKET.4.

---------

Co-authored-by: mlcyclops <mlcyclops@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
mlcyclops added a commit that referenced this pull request Jul 14, 2026
…307)

* Add headless KG-pack builder tools/build_kg_pack.ts (ADR-0207)

Runs the exact in-app pack-authoring pipeline from the CLI so the role-pack
product line builds repeatably (`make kg-pack ROLE=bd`, or --all), composing
already-shipped pieces with zero new trust path:

  readKbSources -> createKg -> ingestSourcesIntoKg (fail-closed scan + compile,
  model injected as backend.complete = the same backend the LUCID session uses,
  resolved to the app's most-used model like /api/kb/ingest-batch) ->
  exportKgPack (Ed25519-sign when LUCID_KG_PACK_SIGNING_KEY is set) ->
  importKgPack (verify + re-scan round-trip, proving the pack installs).

Builds into an isolated temp KB workspace (never the user's ~/.omp graphs) and
writes <slug>.lkgpack(.zip) next to its source dataset. A build catalog maps
each role folder under LucidAgentDesigns/KG Packs/ to name/role/desc/licensing +
a stable product id (the five existing storefront ids match). Cost controls:
--limit N, --dry-run (no model calls), --all.

Verified: 10 pure-helper unit tests; --dry-run loads 365 BD conversations; a
live --limit 2 smoke compiled 2 -> 28 pages (0 quarantined/errored) with
claude-fable-5, exported, and verify-import round-tripped OK. Root tsc + license
clean. No signing key committed (smoke pack was unsigned).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Settings clone reaches parity with agent clone; add AskSage GPT-5.6 (ADR-0208/0209)

Settings "Clone a git repo" now clones private repos headlessly like the
agent does. cloneRepo injects a host token (GITHUB_TOKEN/GH_TOKEN/GITLAB_TOKEN,
https only) via a per-command http.extraHeader (never persisted to .git/config,
redacted from errors), sets GIT_TERMINAL_PROMPT=0, trims the trailing-dot repo
name (the Windows folder-desync behind l.e.a.p.s.), clears leftover partial
clones, and surfaces an actionable auth hint instead of a generic toast. Pure
helpers exported + unit-tested (desktop/workspace.test.ts).

AskSage CIV GPT-5.6 added to OPENAI_MODELS + MODEL_CTX so the newly-added gov
model populates the picker; ADR-0209 scopes a live /get-models fetch so future
models appear without a code change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Vault-backed git PAT for private-repo clones (ADR-0210)

The ADR-0208 follow-up: enter a git token once instead of exporting an env var.
Settings -> Workspace stores a PAT in the OS-encrypted vault (ref git_pat, via
credStore) with a saved indicator + Remove. main.ts prepareGitToken injects it
as LUCID_GIT_PAT into the dev child at spawn (the Figma/Local-Providers vault->env
pattern); hostTokenForUrl uses it as the host-agnostic fallback after a workflow's
own GITHUB_TOKEN. A token saved this session works immediately with no relaunch:
the clone request carries an optional inline pat (sessionGitPat) and
resolveCloneToken prefers it over env. Stays leak-safe (http.extraHeader, redacted,
never sent to the agent).

resolveCloneToken + the LUCID_GIT_PAT fallback are unit-tested (17 workspace tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Enforce AskSage lockdown server-side, fail-closed (ADR-0211)

AskSage-only "lockdown" was enforced only in the renderer (one-shot model switch
on the toggle click + picker hiding), so it silently failed on a fresh launch with
lockdown persisted ON and after every omp respawn (workspace change, clone, Refresh
models, provider-key change): the maker turn used omp's default direct model.

Add enforceAsksageLock() in acp_backend.ts - a fail-closed clamp in prompt() that
forces the active model to an asksage-routed one before every send and REFUSES the
turn ([blocked: ...]) when lockdown is on but no gov model exists (never routes
direct), plus a best-effort clamp on fresh session init so the picker/status show
gov immediately. Fix the checker's broken /gov/i predicate (real ids like
asksage-openai/gpt-5.6 have no "gov" substring, so it matched nothing and fell
through to all models) -> shared isAsksageRouted = /asksage/i. Renderer guard:
lockdown can't be enabled without a configured AskSage key.

resolveLockdownModel + isAsksageRouted are pure + unit-tested, including the
fail-closed "no gov model -> block" case (15 checker_model tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Lockdown covers egress + agent runs; RAG on GPT-5.6 Luna; real 5.6 ids (ADR-0212)

Completes the ADR-0211 lockdown work and extends the sovereignty boundary:

- Egress under lockdown is now fail-closed: the in-process gate blocks ALL public
  egress (web_search / browser / web / fetch / navigate / external http(s)) with an
  audited high-severity event, so CUI can't backflow to a public service. Local
  file:// previews stay allowed. omp owns web_search and takes no endpoint, so the
  control is deny, with the AskSage RAG /query model as the sanctioned alternative.
- Built-agent runs honor lockdown via a shared Backend.resolveAgentRunModel() -
  clamps to a gov model or REFUSES (never the default direct "haiku"), wired into
  both the scheduled-automation path and the Builder "Run" route.
- Corrected the GPT-5.6 ids against the LIVE gateway: family is gpt-5.6-luna(mid)/
  -sol/-terra; the earlier bare gpt-5.6 was invalid and is removed. RAG /query
  default moved gpt-5.2 -> gpt-5.6-luna (validated live). Marked recheck-each-release.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Per-session CUI/Search mode, violet CUI banner, DoD consent, titlebar Datasets picker (ADR-0213)

Refines ADR-0212's global lockdown egress block into a per-session control and
adds the gov compliance UI:

- Per-session CUI vs Search mode: new sessionModes store (settings_store, fail-
  closed default "cui", bounded) + /api/session-mode route (defaults to the active
  omp session) + bridge. The egress gate now blocks only when
  asksageLocked() && sessionMode(active)==="cui" — a CUI session blocks all public
  egress; a Search session (no CUI datasets) may search while still gov-routed.
- Titlebar CUI/Search toggle + violet CUI banner (lockdown-only, per current
  session, reloaded on session switch; new sessions default CUI). Switching to
  Search routes through a spillage warning that steers CUI work to a separate
  Search session.
- DoD/STIG Notice & Consent banner (standard USG/DoD text in one editable
  constant), once per launch when the gov gateway is configured.
- Restored the AskSage Datasets picker to the titlebar next to Skills: short name
  shown, full name on premium hover, multi-select, count on the chip.

5 new session_mode tests incl. the fail-closed default; tsc + license clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* knowledge_search: RAG grounding for non-AskSage users (ADR-0214, increment 1)

Lets ANY model (Claude/GPT/local) ground on the user's own knowledge, not just
AskSage users. The whole local KB stack (Obsidian/folder/chat ingest, compile,
lexical+graph retrieval, KG registry) already existed and was desktop-wired - it
was just never exposed to the agent. This adds the missing wire:

- harness/omp/knowledge_extension.ts: a read-only knowledge_search tool (mirrors
  codegraph_extension) that POSTs the query to the EXISTING /api/kb/retrieve via a
  token'd LUCID_KB_RETRIEVE_URL (preview-tool env-URL pattern) and returns the
  delimited, cited UNTRUSTED hits; empty -> "add an Obsidian vault/folder" guidance.
- dev.ts sets the URL + adds /api/kb/retrieve to the ?t= token allowlist (additive;
  renderer header call unchanged); acp_backend registers the -e extension in ompArgv
  (always-on, not gated behind AskSage).
- Titlebar Datasets chip dual-purposed: non-AskSage -> "Knowledge" menu (add vault/
  folder via the existing importKgFlow + open the Knowledge panel).

Retrieved text stays delimited/late/untrusted (#5/#6); tool mints no trust (PURE
READ, keystone #2); approval "read" keeps it out of the exec gate. 9 unit tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Bring-your-own-embeddings ApiEmbedder (ADR-0215, increment 2 part 1)

The "bring your own embeddings" primitive behind the existing Embedder seam:
POSTs {model, input} to an OpenAI-compatible /embeddings endpoint (the user's
OpenAI/Azure key, or a local Ollama/vLLM via Local Providers), so semantic RAG
needs no bundled WASM weights. Pure (fetchImpl-injected), holds no secret at rest,
fail-loud on any non-2xx / count / dim / non-finite so a broken endpoint can't
poison cosine retrieval. Dormant until wired (ingest->embed, retrieve->hybrid,
Settings card) - pending a config decision + an embeddings-capable endpoint to
verify against.

9 unit tests; tsc + license clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Semantic RAG wired: bring-your-own-embeddings end-to-end (ADR-0215 part 2)

Completes non-AskSage semantic search on top of ADR-0214's lexical knowledge_search:

- embed_config.ts: resolves the stored config + vault secret -> an ApiEmbedder
  (fail-safe null keeps retrieval lexical).
- settings_store `embeddings` config + a dedicated "Semantic search" Settings card
  (local Ollama for air-gap, or OpenAI/Azure). Key vaulted (credStore) and injected
  as LUCID_EMBEDDINGS_KEY by main (the Figma/git-PAT vault->env pattern).
- kb_store: per-KG vector store (sibling _vec.duckdb) + vectorDatasetFor (model+dim
  scoped so vector spaces never mix).
- /api/kb/ingest-batch also embeds each source into the KG's vector store (scan-gated
  ingestText, best-effort, never fails the compile job); /api/kb/retrieve auto-upgrades
  to hybrid when an embedder + embedded chunks exist -> knowledge_search transparently
  gains semantic recall, else stays lexical. No WASM bundling.

15 tests (ApiEmbedder w/ injected fetch, config resolver, and the vector-store glue
against real DuckDB incl. a store->retrieve round-trip). Live path needs a real
/embeddings endpoint configured (this profile has none). tsc + license clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Semantic search: Test-endpoint + Re-index actions (ADR-0215 finishers)

- Test endpoint: probeEmbeddings + /api/embeddings/test do a one-vector probe
  against the ENTERED values (incl. an inline key, so it works before save/relaunch)
  and DISCOVER the model's dimension; the card button auto-fills Dim so a mismatch
  can't silently break retrieval.
- Re-index: /api/embeddings/reindex rebuilds every KG's semantic index from its
  compiled PAGES via a shared, idempotent syncVectorIndex (clear-then-embed), so a
  KG compiled before semantic search was enabled can be indexed without re-ingesting.
  Ingest now uses the SAME routine (embeds compiled pages), keeping the two consistent;
  added KnowledgeStore.clearChunks for idempotency.

+2 probe tests (14 green across api_embedder + the DuckDB vector-store glue); tsc +
license clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Shared-session viewer: show thinking + tools, use the whole window (ADR-0216)

Two fixes to the P-COLLAB guest "Watching" panel:

- The viewer now sees the host's THINKING (collapsible block) + TOOL calls
  (name + path chips) + subagent delegations + blocks, not just the final answer.
  The guest handler used to drop those; the frame protocol already relays the full
  ChatEvent stream, so this is a pure render change (no protocol bump).
- When watching, the modal fills the window (calc(100vw/vh - 56px), ~28px border),
  drops the 520px cap, hides the redundant icon/title/desc (the join-head labels
  the session), and cuts padding (22px -> ~12px, transcript 340px -> flex:1) to
  maximize real estate. The connect step stays the small centered modal; X / Leave
  / Escape still close.

tsc clean; renderer-only, additive.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Renumber this arc's ADRs 0208-0216 -> 0214-0222 (master assigned 0208-0213 to other decisions)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: mlcyclops <mlcyclops@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant