This documentation is also published as Markdown for efficient machine reading: the whole site is indexed at /llms.txt, and every page has a clean Markdown copy under /_llms/. These are generated from the same source and cost far fewer tokens to read than this rendered HTML.

Skip to main content Skip to navigation

ISiteProjection Pennington.Pipeline

Single shared corpus projection: walks every indexable route once, captures its post-pipeline HTML once, parses the DOM once, and yields a stream of RenderedPage records. Every site-wide aggregator (search index, llms.txt, build-time link audit) folds over this stream instead of independently fanning out across the corpus.

this projection is for build-time and artifact-service consumers only. Materialization triggers parallel HTTP self-fetches that re-enter the request pipeline, so no component that runs during a content page's render or response processing may await it — that is the task-cycle deadlock from commit b719d73. The implementation fails fast instead of hanging: every projection-issued fetch is stamped via Infrastructure.CorpusFetchScope, and consuming the projection from such a request (or from inside its own materialization) throws a descriptive InvalidOperationException. Artifact services may consume it freely — their claimed URLs are disjoint from the page corpus the projection fetches. Request-path link verification stays on Infrastructure.PageLinkVerifier, which consults IContentService.DiscoverAllAsync and artifact claims only.

Methods

GetPageAsync

#
public Task<RenderedPage> GetPageAsync(UrlPath canonicalPath, CancellationToken cancellationToken = default)

Returns the projected page at canonicalPath, or null when no page matches. Triggers full materialization on first call; cheap on subsequent calls.

Parameters

canonicalPath UrlPath
cancellationToken CancellationToken

Returns

Task<RenderedPage>

GetPagesAsync

#
public IAsyncEnumerable<RenderedPage> GetPagesAsync(CancellationToken cancellationToken = default)

Yields every renderable page in deterministic discovery order. Materializes lazily on first enumeration; subsequent calls replay the cached array until the instance is dropped by file-watch invalidation.

Parameters

cancellationToken CancellationToken

Returns

IAsyncEnumerable<RenderedPage>

Pennington.Pipeline.ISiteProjection

namespace Pennington.Pipeline;

/// Single shared corpus projection: walks every indexable route once, captures its post-pipeline HTML once, parses the DOM once, and yields a stream of RenderedPage records. Every site-wide aggregator (search index, llms.txt, build-time link audit) folds over this stream instead of independently fanning out across the corpus.  this projection is for build-time and artifact-service consumers only. Materialization triggers parallel HTTP self-fetches that re-enter the request pipeline, so no component that runs during a content page's render or response processing may await it — that is the task-cycle deadlock from commit b719d73. The implementation fails fast instead of hanging: every projection-issued fetch is stamped via Infrastructure.CorpusFetchScope, and consuming the projection from such a request (or from inside its own materialization) throws a descriptive InvalidOperationException. Artifact services may consume it freely — their claimed URLs are disjoint from the page corpus the projection fetches. Request-path link verification stays on Infrastructure.PageLinkVerifier, which consults IContentService.DiscoverAllAsync and artifact claims only.
public interface ISiteProjection
{
    /// Returns the projected page at canonicalPath, or null when no page matches. Triggers full materialization on first call; cheap on subsequent calls.
    
public Task<RenderedPage> GetPageAsync(UrlPath canonicalPath, CancellationToken cancellationToken = default)
; /// Yields every renderable page in deterministic discovery order. Materializes lazily on first enumeration; subsequent calls replay the cached array until the instance is dropped by file-watch invalidation.
public IAsyncEnumerable<RenderedPage> GetPagesAsync(CancellationToken cancellationToken = default)
; }