droost / engine
Framework-free engine behind Droost: QA verify loop, AI-harness installers, guidelines/skills corpus services, scaffold blueprints, OKF wiki core, and code search/graph core for Drupal projects.
Requires
- php: ^8.3
- nikic/php-parser: ^5.0
- psr/log: ^2.0 || ^3.0
- symfony/process: ^6.4 || ^7.0
- symfony/yaml: ^6.4 || ^7.0 || ^8.0
Requires (Dev)
- dealerdirect/phpcodesniffer-composer-installer: ^1.0
- drupal/coder: ^8.3
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^10.5 || ^11.5
Suggests
- ext-pdo_sqlite: SQLite-backed code-graph/vector storage for repo-only (no-site) usage
README
The framework-free engine behind Droost.
Droost is a developer-acceleration toolkit for AI coding agents working on Drupal. Most of what it does is not actually Drupal-specific: running a QA verify loop, writing AI-harness config files, reading a guidelines corpus, generating scaffolds, composing wiki pages, indexing code. This package is that half — plain PHP with no Drupal dependency — so the same logic can serve the Drupal module, a standalone CLI, and repo-only tooling that has no installed site to boot.
Areas (each depends only on Support and Site, never on a sibling):
| Area | What it holds | Landed |
|---|---|---|
Support |
Shared primitives: project-root discovery, path guards, secret redaction, git HEAD, clock, state store | partly |
Site |
What the engine may know about the site it runs against: the extension-locator port and the no-site implementation | yes |
Verify |
The QA verify loop (lint, static analysis, tests) and its leg results | yes |
Guidelines / Skills |
Guidelines corpus reader and skill emitters | yes |
Harness |
Installers that write AI-harness files (AGENTS.md, SKILL.md, and friends) | yes |
Scaffold |
Blueprint registry and the framework-free code blueprints | partly — see below |
Wiki |
OKF wiki core: frontmatter, provenance, page composition, bundle reading | yes |
Search |
Code search and graph core: chunkers, extractors, index diffing | partly — stores and indexer still to come |
Why Scaffold is a partial lift
The scaffold area splits along a line that is not negotiable. Droost composes
Drush's ~70 code generators rather than reinventing them, and that runner needs
the Drush runtime container — Drush::hasContainer(), and Drush's own
ApplicationFactory. Seven blueprints (service, content-entity, config-entity,
event-subscriber, block, form, plugin) are built on it, and an eighth reflects
over DrushCommands to compute its reserved method list. None of those can
live in a package that does not depend on Drush, so they stay in the module.
What lives here is the spine — BlueprintInterface, AbstractBlueprint,
BlueprintRegistry, ScaffoldContext, ScaffoldResult — plus the eight
blueprints that emit from templates rather than delegating: access-handler,
config-schema, hook, kernel-test, mcp-tool, route-subscriber, sdc,
views-handler. The registry accepts both halves, so a consumer sees one set.
That the two halves are wired together at the container rather than merged is the point: the contract is framework-free even where an implementation is not.
The Site port, and why it is three-valued
Site\ExtensionLocatorInterface is how everything else asks what the project
has. Its isInstalled() returns true, false, or null — because the
engine runs both inside a booted site, where absence is a fact, and against a
bare checkout, where it is not knowable.
That distinction is load-bearing rather than fussy. "Not installed" prunes: it
drops a topic from the guidelines catalog, so it never becomes a skill, so it
never reaches the agent. Letting null collapse into false would make a
plain checkout silently report half a corpus, and guidance that is missing
looks exactly like guidance that was never written. Site\UnknownSite answers
null to everything, and callers are contracted to read that as "show it".
Status
0.x — extraction in progress. Code is being lifted out of the droost module
area by area (phases B1 through B5 of the extraction plan); each tranche lands
behind a tagged release before the module switches over to it. Treat the API as
unstable until 1.0: breaking changes bump the minor, and consumers should pin
per minor (~0.1.0).
0.1.1 landed the pilot tranche — Support\ProjectRoot, Support\PathGuard,
Support\SecretRedactor, Support\GitHead, Verify\VerifyRunner,
Verify\LegResult — chosen because it has zero coupling to Drupal and
therefore proved the packaging pipeline on the smallest possible surface.
0.2.0 adds the guidance tranche (B2): Site\ExtensionLocatorInterface and
Site\UnknownSite, Guidelines\GuidelineProvider, Skills\Skill,
Skills\SkillProvider, Skills\SkillMdWriter, and the whole Harness area —
fifteen classes that write AGENTS.md, SKILL.md, and the per-harness config
files for Claude, Codex, Gemini, opencode and Qwen. The minor bumps because
consumers pinned to ~0.1.0 must opt in; nothing in 0.1.1 changed.
0.3.0 adds the scaffold spine and the eight template-only blueprints (B3),
for the reasons in "Why Scaffold is a partial lift" above.
0.4.0 adds the OKF wiki core (B4) — frontmatter parsing, provenance,
page composition, bundle reading — plus Support\Yaml, which reproduces
Drupal's YAML settings exactly (Dumper(2), inline level PHP_INT_MAX, the
same flag pairs) so a regenerated page is byte-identical to the last one. That
was verified against core's own serializer on a booted site, not assumed;
Wiki\BundleLocatorInterface is the one port it needs, and the module's
existing WikiSettings already satisfies it unchanged.
0.5.0 adds the pure search core (B5a): the chunkers, Graph\GraphVisitor
and Graph\YamlGraphExtractor, index diffing, and the embedding and
vector-store interfaces. The storage layer stays in the module for now — four
classes built on Drupal's database API, which need a port of their own before
they can move (B5b).
The rest of Support (clock, state store) arrives with the areas that need it.
Install
composer require droost/engine
Requires PHP 8.3 or newer. ext-pdo_sqlite is suggested — it backs the
SQLite code-graph and vector stores used for repo-only (no site) operation.
Development
composer install
vendor/bin/phpcs
vendor/bin/phpstan analyse
vendor/bin/phpunit
Coding standards are Drupal + DrupalPractice (phpcs.xml.dist), matching the
module so lifted files diff to near-zero. PHPStan runs at level max with an
empty baseline. CI runs all four on PHP 8.3 and 8.4.
License
GPL-2.0-or-later. See LICENSE.