Fixed
-
Tracking no longer breaks prompt rendering. Tracking defaulted to on whenever
APP_DEBUGwas false, but its tables are published in a separate opt-in step — so the natural production install (composer require, publish config, deploy) threwno such table: prompt_versionson the very firstDeck::get(). Caching gave no protection, because the active version is resolved before the cache is consulted. Tracking now defaults to off, and every database interaction degrades tometadata.jsonwith a single logged warning instead of throwing.Deck::track()never throws under any circumstances: it runs after a completed, paid-for AI call, and no analytics failure is worth discarding that response. -
Deck::activate()now records the version it activated. It only ever issued anUPDATE, which matched no rows because nothing ever inserted them — soprompt_versionsstayed empty and the lookup that read it could fail but never succeed. Activation is now an upsert, making runtime version switching work as documented. -
Prompt names are validated. A name was interpolated straight into a filesystem path, so one containing
..or a directory separator could read files outside your prompts directory. Names now throwInvalidPromptNameExceptionunless they contain only letters, numbers, dots, dashes, and underscores. -
Version directories are matched precisely. The pattern was unanchored and applied to the full path, so
rev2,dev3, andarchive-v9registered as versions 2, 3, and 9 — advertised byprompt:list --all, then failing to load. -
make:promptcan no longer create a prompt that will not load. Kebab-casing passed path separators through, somake:prompt Support/Replyscaffolded a nestedsupport/replythat the manager refuses to resolve andprompt:listdisplays as a brokensupportentry. The generator and the loader now share one definition of a valid name, so they cannot drift apart. -
Deck::track()no longer throws on an invalid name, which contradicted its own documented promise. It builds no path — the name is only a column value — so the guard protected nothing. -
getActiveVersion()no longer picks arbitrarily between multiple active rows, and casts the version it reads. -
The name pattern no longer accepts a trailing newline, since
$matches before one.
prompt_versions.user_promptis nullable, so activation can be recorded without prompt content. Deck is file-based; content lives on disk.- Once a version has been activated with tracking enabled, the database takes precedence over
metadata.json. Editingactive_versionin the file and deploying no longer changes what is served — activation is environment state, the file is the bootstrap default. See Tracking — Activation precedence.
Added
- A
qualityCI workflow now checks formatting with Pint on every push and pull request, and asserts that every release in the repositoryCHANGELOG.mdhas a matching entry on this page. Formatting was never checked in CI before, and the two changelogs could drift apart unnoticed. - The test workflow now runs
composer testrather than calling Pest directly, so CI and the documented contributor command cannot diverge.
-
Deck::activate()now accepts string versions.'v2','2', and2are all valid, matching whatDeck::get()has accepted sincev0.4.2. Onlyget()was widened at the time, soDeck::activate('order-summary', 'v2')raised aTypeErrordespite the release notes describing both. Passing an integer continues to work unchanged.
- Unparseable versions now name the offending value. Both
Deck::get()andDeck::activate()threw a message with the version missing entirely —Version for prompt [order-summary] does not exist.They now throwInvalidVersionExceptionreadingInvalid version [banana] for prompt [order-summary]. Use a positive number like [1] or [v1]. - Corrected the prompt structure diagrams throughout the documentation and README. They omitted the version-level
metadata.jsonintroduced inv0.4.4, and the README showed auser.mdthatmake:promptdoes not create without--useralongside a second version that a single run does not create. - Corrected the README describing new versions as becoming active automatically. Creating a version has not changed the active version since
v0.4.4. - Corrected the documented
Deck::get()signature, which read?intrather thanstring|int|null.
Fixed
- Migrations now publish on case-sensitive filesystems.
vendor:publish --tag=deck-migrationsreported success without copying anything on Linux and case-sensitive macOS volumes. If yourdatabase/migrationsdirectory came up empty after installing Deck, publish again after upgrading. - Creating a version no longer changes which version is live.
make:promptrewrote the prompt’s rootmetadata.jsonfrom scratch, discarding theactive_versionkey, so scaffolding a draft silently promoted it to active. The file is now merged:active_version, your description, the originalcreated_at, a populatedvariableslist, and any keys you added by hand all survive. - Prompt metadata is now readable.
make:promptrecorded the name, description, and roles in the prompt’s rootmetadata.json, but Deck only ever read the version-levelv{n}/metadata.json.PromptTemplate::metadata()was always empty and theprompt:listdescription column was always blank.make:promptnow writes version-level metadata too, and reads merge the two files with version keys winning. See Metadata. prompt:test --ver=v2renders the version you asked for. Thevprefix was discarded during parsing, so the command quietly rendered the active version while reporting the wrong number in its header. Both2andv2now work, and an unparseable value fails with a clear message.- Corrected the
PromptPHP\Deck\Database\Factories\PSR-4 mapping, which pointed at a directory that does not exist. - Corrected the README downloads badge, which reported the deprecated
veeqtoh/prompt-deckpackage, and the stale repository and licence links.
-
make:promptnow tells you how to promote a new version when a different one is active:
- Removed the
PromptPHP\Deck\Database\Seeders\autoload mapping, which pointed at a directory that does not exist.
Fixed
- Widened the
sebastian/diffconstraint to allowv8andv9, so Deck can be installed alongside Pest 5. #12
Fixed
Deck::get()andDeck::activate()now accept mixed version types, resolving versions through the sharedResolvesVersiontrait.
Fixed
prompt:activatenow accepts both1andv1version formats.
Changed
- Renamed the package from
veeqtoh/prompt-decktopromptphp/deck. - Renamed the PHP namespace from
Veeqtoh\PromptDecktoPromptPHP\Deck. - Renamed the public package identity from Prompt Deck to Deck by PromptPHP.
- Updated installation, usage, README, badges, documentation links, and package metadata for the new PromptPHP organisation. #7
- Removed the old
Veeqtoh\PromptDeckpublic namespace. - Removed old Prompt Deck naming from the main public API.
Added
- Published this documentation site, built on Mintlify. #5
- Added dedicated pages for installation, configuration, commands, prompt management, Laravel AI SDK integration, tracking, testing, and the API reference.
- Reworked the documentation from flat markdown files into organised MDX pages. #6
- Fixed stale documentation links and navigation paths.
Added
- Added a
CHANGELOGto the repository. - Added a GitHub Actions workflow for automated testing.
- Added a
.gitattributesfile to manage text handling and export-ignore rules.
- Refined the Composer package keywords for discoverability.
Added
- Added support for Laravel 13. #3
- Added the
scaffold_on_make_agentoption to toggle auto-scaffolding of prompts when you runmake:agent. See Configuration.
The first release. #1Added
- Versioned prompt management with file-based storage in structured prompt directories.
- Variable interpolation for prompt templates.
- Artisan commands for creating, listing, testing, diffing, and activating prompts. See Commands.
- Prompt execution tracking. See Tracking.
- A/B testing through versioned prompt activation and tracking.
- Optional Laravel AI SDK integration. See Laravel AI SDK.