Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changelog/bundled-consumer-skill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: added
type: minor
---

Bundle the fast-forward-framework consumer skill with executable examples, optional installation guidance and Composer discovery metadata.
6 changes: 6 additions & 0 deletions .changelog/dependency-freshness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: changed
type: patch
---

Raise compatible Fast Forward dependency minimums to current stable releases, use stable DevTools and check Composer and Actions updates daily through Dependabot.
22 changes: 19 additions & 3 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,20 @@ updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
interval: "daily"
time: "09:00"
timezone: "America/Sao_Paulo"
open-pull-requests-limit: 20
versioning-strategy: increase
allow:
- dependency-type: "all"
groups:
fast-forward-compatible:
patterns:
- "fast-forward/*"
update-types:
- "minor"
- "patch"
commit-message:
prefix: "Composer"
include: "scope"
Expand All @@ -14,10 +27,13 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
interval: "daily"
time: "09:00"
timezone: "America/Sao_Paulo"
open-pull-requests-limit: 20
commit-message:
prefix: "GitHub Actions"
include: "scope"
labels:
- "github-actions"
- "continuous-integration"
- "continuous-integration"
8 changes: 8 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,11 @@ Fast Forward components through a single provider entry point.
- When making user-visible changes, add a unique `.changelog/*.md` fragment using the installed Changelog skill and [contribution guide](CONTRIBUTING.md).
- Preserve published `CHANGELOG.md` history. The reviewed version PR consolidates pending fragments; do not add an `Unreleased` heading.
- Prefer concise entry wording and include the current PR reference when known.

## Bundled consumer skill

Read [the consumer skill](resources/skills/fast-forward-framework/SKILL.md) when changing application integration
examples, consumer guides or the skill. Keep its version contract, references
and executable examples aligned with the supported public API. The canonical
distributable source is `resources/skills`; it needs no installed copy or host
alias. Repository maintenance continues to follow this AGENTS.md.
37 changes: 37 additions & 0 deletions DEPENDENCIES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Dependency freshness

The framework requires the latest reviewed stable Fast Forward baselines with
caret constraints. A fresh Composer resolution chooses the newest compatible
versions allowed by the entire application graph and its PHP/extensions.

This library intentionally commits no composer.lock. Applications should commit
their lockfile: composer install reproduces that application lock, while composer
update deliberately resolves new compatible versions. Installing/updating this
library does not rewrite an application's lockfile in the background.

Dependabot monitors Composer and GitHub Actions daily at 09:00 America/Sao_Paulo
(on Dependabot's weekday daily schedule). Composer uses versioning-strategy:
increase so a new release can propose an increased manifest minimum even when
it was already compatible. All dependency types are eligible; compatible
fast-forward/* minor/patch updates are grouped and major proposals stay separate.
No ignored package/version or cooldown suppresses new Fast Forward releases.
Twenty concurrent version-update PRs are permitted. These settings take effect
when the configuration is merged into the default branch. They prepare reviewable
PRs; checks and maintainer merge decisions still apply.

HTTP Client, HTTP Factory and HTTP Message are already installed transitively
through fast-forward/http. Requiring them again at framework level is unnecessary
for the framework's own provider. Clock, Config, Container, Defer, Enum, Event
Dispatcher, Fork, HTTP and Iterators form the intended runtime aggregate.
Changelog, DevTools, Composer Installers and the phpDocumentor template are
development/distribution tools rather than extra application runtime services.
Empty/prototype repositories do not establish a supported runtime library.

For a consumer that needs every newly published compatible release, schedule
reviewed dependency updates in that consumer too. Another dependency or the
consumer's PHP version can constrain resolution; this framework cannot guarantee
that the globally newest release is compatible. Review major releases and
runtime requirement changes explicitly before widening constraints.

References: [Composer constraints](https://getcomposer.org/doc/articles/versions.md)
and [Dependabot options](https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference).
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,15 @@ Fast Forward Framework is licensed under the [MIT license](LICENSE).

Developed by **Felipe Sayão Lobato Abreu**
- 📧 [github@mentordosnerds.com](mailto:github@mentordosnerds.com)

## Consumer agent skill

The package includes [fast-forward-framework](resources/skills/fast-forward-framework/SKILL.md) for application integration.
It supports `fast-forward/framework:^1.5`; inspect the installed version.
See [skill installation and lifecycle](resources/skills/fast-forward-framework/references/installation.md) for
optional project synchronization with `llm/skills ^1.15`, guarded manual
project/global copies and a pinned Skills CLI alternative. Shipping files does
not install tooling or activate the skill in an agent session.

See [dependency freshness](DEPENDENCIES.md) for compatible version ranges,
application lockfiles and the daily Dependabot update policy.
24 changes: 15 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,21 @@
],
"require": {
"php": "^8.3",
"fast-forward/clock": "^1.0",
"fast-forward/config": "^1.4",
"fast-forward/container": "^1.5",
"fast-forward/defer": "^1.0",
"fast-forward/enum": "^0.1",
"fast-forward/clock": "^1.1",
"fast-forward/config": "^1.7.3",
"fast-forward/container": "^1.10.1",
"fast-forward/defer": "^1.0.1",
"fast-forward/enum": "^0.1.1",
"fast-forward/event-dispatcher": "^1.0",
"fast-forward/fork": "^1.0",
"fast-forward/http": "^1.0",
"fast-forward/iterators": "^1.0"
"fast-forward/fork": "^1.0.1",
"fast-forward/http": "^1.1",
"fast-forward/iterators": "^1.2"
},
"require-dev": {
"fast-forward/dev-tools": "dev-main"
"fast-forward/dev-tools": "^1.26"
},
"suggest": {
"llm/skills": "Optionally synchronize the bundled consumer skill in your project."
},
"minimum-stability": "stable",
"autoload": {
Expand Down Expand Up @@ -71,6 +74,9 @@
},
"grumphp": {
"config-default-path": "vendor/fast-forward/dev-tools/grumphp.yml"
},
"skills": {
"source": "resources/skills"
}
},
"scripts": {
Expand Down
21 changes: 21 additions & 0 deletions resources/skills/fast-forward-framework/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Felipe Sayão Lobato Abreu <github@mentordosnerds.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
88 changes: 88 additions & 0 deletions resources/skills/fast-forward-framework/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
name: fast-forward-framework
description: Compose a Fast Forward application container, resolve HTTP, event and clock services, and diagnose missing or conflicting configuration.
license: MIT; see LICENSE
compatibility: Supports fast-forward/framework ^1.5 and PHP ^8.3. Requires Composer and declared extensions; inspect the installed version. Earlier releases are outside this contract.
metadata:
author: Fast Forward
api-baseline: fast-forward/framework ^1.5
---

# Bootstrap the Fast Forward framework

Use this skill for an application consuming `fast-forward/framework:^1.5`.
Read its instructions, manifest/lockfile and installed source before editing.
Run `composer show fast-forward/framework`. For versions outside this contract,
inspect matching documentation; do not silently upgrade the application.

## First working integration

Requires PHP ^8.3, Composer's application autoloader and this package's runtime
dependencies.
With authority to install the dependency:

```sh
composer require 'fast-forward/framework:^1.5'
```

Create `app.php` in the application root alongside composer.json/vendor:

```php
<?php

declare(strict_types=1);

require __DIR__ . '/vendor/autoload.php';

use FastForward\Config\ArrayConfig;
use FastForward\Container\ContainerInterface;
use FastForward\Framework\ServiceProvider\FrameworkServiceProvider;
use Psr\Clock\ClockInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use function FastForward\Container\container;

$config = new ArrayConfig([ContainerInterface::class => [FrameworkServiceProvider::class]]);
$container = container($config);
$response = $container->get(ResponseFactoryInterface::class)->createResponse(201);
if ($response->getStatusCode() !== 201
|| !$container->get(ClockInterface::class)->now() instanceof DateTimeImmutable
|| !$container->get(EventDispatcherInterface::class) instanceof EventDispatcherInterface) {
throw new RuntimeException('Framework services were not composed.');
}

echo "integration ready\n";
```

Run `php app.php`. It throws on a wrong result; success prints
`integration ready`. It uses no production data and starts no server.

## Wiring and failure boundaries

The raw provider list is keyed by `FastForward\Container\ContainerInterface::class` in the ArrayConfig passed to `container($config)`. It is exposed as `config.FastForward\Container\ContainerInterface`; the PSR-11 interface is a different key. Do not pass an array to the variadic container helper. The provider composes HTTP, Event Dispatcher and Clock; it does not install an HTTP server, router, cache, logger or middleware pipeline.

For a provider-only bootstrap, call `container(FrameworkServiceProvider::class)`. Use ArrayConfig when the event integration needs listener configuration. Inject the resulting PSR-11 container into the application's own runtime; obtaining a response does not emit it. HTTP Message, HTTP Factory and HTTP Client arrive transitively through HTTP.

For application overrides put an explicit ArrayServiceProvider first in the helper's arguments, ahead of the configured/default providers. Aggregate source lookup uses the first successfully resolving source; it does not recursively merge factories across separate sources. Services created by ServiceProviderContainer are cached. A missing id raises a PSR-11 not-found exception; an existing factory can still fail at get(), so has() is not a construction guarantee.

The helper tries aggregate sources in registration order. A PSR container or
not-found exception from one source permits fallback to another source; other
throwables propagate. Source priority is therefore the first successful resolution,
not a guarantee that an earlier broken factory terminates lookup. Nested provider
list errors during helper composition are caught; if services are absent, inspect
the raw configuration and resolve the provider directly to diagnose the failure.

## Verify integration

Run the [complete example](examples/integration.php) against the application's
autoloader in a disposable process. It checks success and negative cases:

```sh
php /path/to/fast-forward-framework/examples/integration.php ./vendor/autoload.php
```

Expected final marker: `fast-forward-framework: ok`. Keep application-specific regression
tests in its existing PHPUnit suite, with each fixture class in its same-named
file. File copying, host discovery and completed agent tasks are different checks.
For optional copying/synchronization load
[installation and lifecycle](references/installation.md).
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

require $argv[1] ?? dirname(__DIR__, 4) . '/vendor/autoload.php';

use FastForward\Config\ArrayConfig;
use FastForward\Container\ContainerInterface;
use FastForward\Framework\ServiceProvider\FrameworkServiceProvider;
use Psr\Clock\ClockInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use function FastForward\Container\container;

$config = new ArrayConfig([ContainerInterface::class => [FrameworkServiceProvider::class]]);
$container = container($config);
$response = $container->get(ResponseFactoryInterface::class)->createResponse(201);
if ($response->getStatusCode() !== 201
|| !$container->get(ClockInterface::class)->now() instanceof DateTimeImmutable
|| !$container->get(EventDispatcherInterface::class) instanceof EventDispatcherInterface) {
throw new RuntimeException('Framework services were not composed.');
}
try {
$container->get('application.missing');
throw new RuntimeException('Missing service unexpectedly resolved.');
} catch (\Psr\Container\NotFoundExceptionInterface) {
}

echo "fast-forward-framework: ok\n";
Loading
Loading