Skip to main content

Module projects

Module projects 

Source
Expand description

The single owner of project behaviour (mission first-class-projects-01M3BYBW, WP02).

Everything about a project lives here: identity and resolution, the registry lifecycle (create / edit / delete / list), derived membership and the index that makes a project filter a bucket lookup, the association mutations, and missing-reference diagnosis. Surfaces call this rather than re-deriving, because a second identity resolver or a stored membership index is exactly the divergence the mission’s charter escalates (C-006, NFR-001).

§What this module deliberately does not do

  • It touches no files. It takes an in-memory Config and an in-memory issue set, and returns values. Storage owns the write; this module owns the rule. The whole surface is therefore testable with no Store and no tempfile (T010 step 4).
  • It does not know about the issue model. ProjectNode is the minimum an issue must expose — its number, title, status, and its projects id list — and WP03 implements it for crate::model::Issue in src/model.rs (this mission’s WP03 owns that file), exactly as the hierarchy service’s HierarchyNode is implemented there. WP02 is forbidden from touching src/model.rs, so the service is defined against the shape WP03 provides.
  • It never mutates or returns a whole Issue. associate and dissociate return a ProjectChange: the resulting association list plus the History event to append. Storage applies it. That is the boundary that keeps this module model-free.
  • It stores no membership. A project’s members are derived by inverting the issues’ association lists, never persisted (data-model §4, C-003).
  • It does not compute progress or health. ProjectProgress and ProjectHealth are WP04’s, added to this module additively; the single health operation the contract names lands there (contract §2).

§The index is built once per read

ProjectIndex is the derived view over one snapshot. It is built once (ProjectIndex::build) and every read — ProjectIndex::membership, ProjectIndex::resolve, ProjectIndex::missing — reads that one value rather than rebuilding. The contract’s free operations each build exactly one index per call, so a filter is a bucket lookup rather than a scan (NFR-001).

§Ordering is deterministic

Members are ordered by issue number, projects by declaration order, and missing references by (issue number, project id), so repeated reads of the same snapshot are identical (contract §6).

Structs§

BulkProjectOutcome
The per-issue outcome of a bulk association (contract §1).
IssueKey
A project issue number, as the derived structures key it.
MemberRef
One member of a project, with its derived display label.
MissingProjectReference
A stored association whose project is not in the registry (data-model §3).
NewProject
The spec for a new project.
Project
The service-side view of a project (data-model §2).
ProjectChange
The outcome of an association mutation: the resulting list plus the event.
ProjectDeletion
The impact report of a project deletion (contract §1).
ProjectEdit
The fields of a project edit.
ProjectEvent
One association mutation, ready for storage to append to ## History.
ProjectHealth
A project’s health counters (data-model §5, FR-003).
ProjectHealthReport
The typed value the health operation returns (contract §1).
ProjectIndex
The derived project view over one snapshot of issues and the registry.
ProjectMembership
The derived members of a project (data-model §4).
ProjectProgress
A project’s completion progress (data-model §5, FR-003).

Enums§

Patch
One field edit: leave it, clear it, or set it.
ProjectDiagnosticKind
The diagnostic kinds contracts/project-service.md §1 names, spelled exactly.
ProjectError
Why a project operation was refused.
ProjectEventKind
The two association mutations, as the ## History section records them.

Constants§

MISSING_REFERENCE_KIND
The lint diagnostic kind for an association that no longer resolves.
MULTIPLE_PROJECTS_BUCKET
The single bucket for an issue in several projects.
NO_PROJECT_BUCKET
The clearly labelled bucket for an issue in no project.
PROJECTS_KEY
The frontmatter key carrying an issue’s project associations.

Traits§

HealthNode
The one per-issue fact project health reads beyond ProjectNode.
ProjectNode
The minimum an issue must expose for project derivation.

Functions§

assigned_keys
The members of a snapshot that carry an assignee.
associate
Associate an issue with a project, producing the change and its History event.
association_detail
The single wording for an association change’s ## History detail line.
bulk_associate
Associate each selector independently, reporting every outcome.
create_project
Create a project, allocating a fresh stable id (FR-001).
delete_project
Remove a project from the registry, reporting the issues that reference it.
dissociate
Remove an issue’s association with a project.
duplicate_name_reason
The single wording for a project name refusal.
edit_project
Edit a project’s fields by reference.
health
Progress and health for a project, in one index build (contract §1).
invalid_dates_reason
The single wording for a project date refusal.
list_projects
The projects in declaration order, with derived member counts.
membership
The ordered membership of a project, by id or name.
membership_index
Build the reverse index once for one read (HashMap<ProjectId, Vec<IssueKey>>).
missing_reference_reason
The single wording for an association that no longer resolves.
project_bucket_label
The group-section label for one issue’s resolved project memberships.
project_display
The shared display form for a project: Platform hardening (p-3f9a2c).
resolve
Resolve a project by id (first) or by name.
resolve_project_id
Resolve a project id from a reference: id first, then a name convenience.
unknown_issue_reason
The single wording for an issue selector that names no issue.
unknown_project_reason
The single wording for an unresolvable project reference.
validate_references
Every association in the snapshot whose project is not in the registry.