User Stories — Full Detail
Click-through target for the US IDs in the Product Requirements & Roadmap milestone tables. The single source of truth for story text is docs/portfolio/product/user-stories/*.qmd; this page only re-arranges it for reading in one place, with a stable anchor per story for the milestone tables to link to. Edit the .qmd, then regenerate: python docs/portfolio/_build/generate_user_stories_page.py.
M0 — Platform Foundation · Jul 2025
Evidence Intake
US-M0-01 — Ingest a campaign’s imagery with its provenance intact
FR-EVI-01 (Delivered)
As a Data Explorer, I want to load a campaign’s RGB inspection imagery into one dataset with each image’s capture time and GPS position preserved, so that everything downstream — the scene, the gallery, an engineer’s finding — can say where and when a picture was taken.
- Given a set of drone images with EXIF headers, when I ingest them into a dataset, then each image record carries its capture timestamp and GPS position from the header, and the dataset reports how many images it holds.
- Given an image with no GPS in its header, when it is ingested, then it is kept in the dataset and marked as unpositioned — never dropped silently, never given a fabricated position.
- Given two datasets in one organisation, when I browse either, then I see only that dataset’s images; an image belongs to exactly one dataset.
Application Surface
US-M0-02 — See the campaign in space
FR-APP-07 (Delivered)
As an Integrity Engineer, I want a browser-based 3D geospatial scene of the site with the campaign’s imagery placed where it was captured, so that I can orient a picture to the plant without leaving the application.
- Given a dataset with positioned images, when I open its 3D view, then the scene renders in the browser with each positioned image marked at its GPS location.
- Given a marked image in the scene, when I select it, then I see the image and its metadata in place, and can continue to the gallery or the viewer from there.
- Given a dataset whose images carry no position, when I open the 3D view, then the scene loads with a clear statement that nothing could be placed, rather than an empty globe with no explanation.
US-M0-03 — Know where every campaign stands
FR-APP-08 (Delivered)
As a Data Explorer, I want one dashboard listing my organisations, their campaigns and the anomalies found so far, so that I can see at a glance which campaign needs attention without opening each one.
- Given membership of one or more organisations, when I open the dashboard, then I see every campaign I can access with its image count and anomaly count, and nothing from organisations I am not a member of.
- Given a campaign on the dashboard, when I select it, then I land in that campaign’s workspace with the same counts.
- Given an organisation with no campaigns yet, when I open the dashboard, then it is listed as empty rather than omitted.
US-M0-04 — Review what the analysis found, picture by picture
FR-APP-09 (Delivered)
As an On-call Integrity Engineer, I want a gallery of a campaign’s images with the detected anomalies drawn as bounding boxes and their annotations alongside, so that I can review findings against the evidence rather than against a list.
- Given a campaign with analysed images, when I open its gallery, then each image shows its anomaly bounding boxes with the annotation’s category and confidence.
- Given the gallery, when I filter by anomaly category, then only images carrying that category remain and the count updates to match.
- Given an image with no detections, when I open it, then it is shown clean with an explicit “no anomalies detected” state — an empty overlay is not an error.
Security & Compliance
US-M0-05 — Sign in once; see only my organisations
FR-SEC-04 (Delivered)
As an Operations Supervisor, I want every user to sign in to one account whose organisation memberships and roles decide what they can see and change, so that a contractor on one site cannot reach another site’s data by accident or by crafting a request.
- Given a signed-in user, when any page or API route loads campaign data, then only rows from organisations that user belongs to are returned — enforced in the database by row-level security, not only in the interface.
- Given a user with a viewer role in an organisation, when they attempt a write (an annotation, a finding, an export), then it is refused with a permission error and nothing changes.
- Given an expired or tampered session token, when a request is made, then it is rejected and the user is sent to sign in again — never served another user’s data.
M1 — AI Foundation · Dec 2025
Evidence Intake
US-M1-01 — Bring thermal, OGI and gas evidence into the same campaign
FR-EVI-02 (Delivered — as a prototype; calibrated thermal and field-survey readings are M4 requirements of their own)
As a Data Explorer, I want thermal images, OGI clips and gas readings ingested into the same campaign as the RGB imagery, each carrying its modality, so that an engineer can see a location’s evidence across sensors instead of across folders.
- Given thermal images alongside RGB in a campaign, when they are ingested, then each carries its modality and — where the capture pairs them — a link to its RGB counterpart, so the pair can be viewed together.
- Given gas readings for a campaign, when they are ingested, then each reading keeps its concentration, unit, timestamp and position, and can be listed for the campaign.
- Given a modality the pipeline does not recognise, when ingestion runs, then the files are reported as unhandled with their names — not ingested as RGB, not lost.
Application Surface
US-M1-02 — Ask the data a question in plain language
FR-AI-05 (Delivered — an early prototype; the reliable single-turn query is M3’s contextual-chat requirement)
As an Integrity Engineer, I want to ask a question about my inspection data in plain language and get an answer drawn from it, so that finding “how many anomalies in this campaign” does not require knowing where that number lives.
- Given a question about a campaign’s images or anomalies, when I ask it, then the assistant answers from that campaign’s data and shows what it looked at.
- Given a question the assistant cannot ground in data, when it answers, then it says so rather than producing a number with nothing behind it.
- Given the prototype’s known limits, when an answer is wrong, then I can see the query it ran — the criterion this prototype met was inspectable, not reliable; reliability is the bar of M3’s single-turn query and its evaluation gate.
US-M1-03 — Let the assistant plan the work, not just answer
FR-APP-10 (Delivered)
As an Integrity Engineer, I want a question that needs several steps — find the dataset, pull its images, run an analysis, write it up — carried out by the assistant as a sequence, so that I ask once and get a result rather than driving each tool by hand.
- Given a request that needs more than one tool, when the assistant handles it, then a planner chooses the steps and an executor runs them in order, and the answer reflects every step’s output.
- Given a step that fails, when the sequence runs, then the assistant reports which step failed and what it had so far, rather than presenting a partial result as complete.
- Given a request outside the tools’ reach, when the planner considers it, then it says what it cannot do instead of routing to the nearest tool anyway.
US-M1-04 — See gas readings on the scene
FR-APP-12 (Delivered)
As an On-call Integrity Engineer, I want a campaign’s gas readings drawn on the 3D scene as a colour-mapped heatmap, so that a high reading is a place on the plant, not a row in a table.
- Given a campaign with positioned gas readings, when I enable the gas overlay, then a heatmap renders on the scene with concentration mapped to colour and a legend stating the scale and unit.
- Given the overlay, when I select a hot spot, then I see the readings behind it with their values, units and times.
- Given a campaign with no gas readings, when I enable the overlay, then the scene says there is nothing to draw rather than rendering an empty layer.
M2 — App MVP · Mar 2026
Application Surface
US-M2-01 — Ask for datasets and get a list, whichever engine answers
FR-AI-06 (Delivered; certified on every registered engine — TEST-CERT-01 dataset-discovery)
As a Data Explorer, I want an answer about which datasets exist to arrive as dataset cards I can open, so that the assistant’s first answer is a starting point and not a paragraph to read names out of.
- Given a question that asks for a collection of datasets, when any certified engine answers, then the stream carries exactly one structured dataset list on a clean run — started, the list, finished — and the interface renders it as cards.
- Given a dataset card, when I select it, then I land in that dataset’s workspace.
- Given an engine that answers such a question in prose only, when it is certified, then it fails the row — the product commits to the surface, not to any one engine’s habit.
US-M2-02 — Ask for images and get a gallery I can click through
FR-AI-07 (Delivered; certified on every registered engine — TEST-CERT-01 image-browsing)
As an Integrity Engineer, I want an answer that shows images to arrive as a gallery whose every image opens in the viewer, so that “show me ten images from the unit audit” ends with me looking at the tenth image, not at a list of file names.
- Given an image-browsing question, when any certified engine answers, then the answer carries each image’s identity — id, dataset slug, filename, type — and the interface resolves thumbnails and opens the viewer from it.
- Given the identities in the answer, when the interface renders them, then every image has its dataset slug and no answer carries a signed storage URL — the presentation is the interface’s, the identity is the engine’s.
- Given an image the user’s organisation cannot see, when an answer would include it, then it is absent — the gallery is filtered by the same row-level security as every other read.
Operator Handoff
US-M2-03 — Hand the recommendations to the people who do the work
FR-OPS-01 (Alpha (prototype) — on the alpha lineage only; downgraded from Delivered by the 2026-09-01 audit)
As an Operations Supervisor, I want a campaign’s work orders and recommendations exported as a markdown packet and a CSV, so that the maintenance planner can take them into their own system without re-typing.
- Given a campaign with recommendations, when I export, then I receive a markdown packet listing each recommendation with its asset, priority and evidence reference, and a CSV with one row per recommendation and the same fields.
- Given the CSV, when it is opened in a spreadsheet, then every column is labelled and every row resolves to a recommendation in the platform by its id.
- Given a campaign with nothing to recommend, when I export, then I get an empty packet that says so — not an error, not a packet from another campaign.
M3 — AI Q2 Delivery · Jun 2026
Contextual data chat
US-M3-01 — Workspace-scoped natural-language query
FR-APP-02 (single-turn, Delivered), FR-APP-03 (multi-turn, Q3 Target)
As an Integrity Engineer, I want to ask natural-language questions scoped to my workspace and campaign so that I can find relevant findings without manual filtering.
- Given a selected workspace and campaign, when I ask a single-turn question, then the answer draws only on that workspace’s data. (Multi-turn context retention is FR-APP-03, targeted for M4 — accuracy at 2+ turns is currently below release bar.)
- Given a query that implies a high-consequence action, when the assistant proposes it, then it requires explicit human-in-the-loop confirmation before any action is taken.
- Given no grounded data supports an answer, when the assistant responds, then it states it cannot find supporting data rather than fabricating a result.
Agent reliability
US-M3-08 — Graceful degradation on backend faults
FR-APP-13 (failure recovery, Delivered)
As an Integrity Engineer, I want the chat assistant to fail safely when a backend dependency errors so that I get a clear message instead of a broken or hallucinated answer.
- Given a Supabase RLS denial or query timeout, when it occurs, then the assistant returns an empty/no-access result rather than crashing or leaking another workspace’s data.
- Given a Gemini rate-limit or timeout, when it occurs, then the request retries/backs off and the user sees a clear “try again” message rather than a stalled UI.
- Given an expired or tampered JWT, when a request is made, then it is rejected with a re-authentication prompt, not a silent failure.
US-M3-09 — Trustworthy chat backed by accuracy gates
FR-APP-14 (agent evaluation gate, Delivered)
As an Integrity Engineer, I want the chat assistant’s classification/query/report accuracy validated against a benchmark before each release so that I can trust its answers in day-to-day use.
- Given a new build of the classifier, executor, or reporter agent, when it is proposed for release, then it must pass the accuracy benchmark thresholds before shipping.
- Given a benchmark regression (e.g. below-target accuracy on a query category), when detected, then the release is blocked until resolved.
- Given multi-turn conversation accuracy remains below target, when a user starts a new conversation, then the assistant is scoped to single-turn queries only for M3 rather than silently degrading on follow-ups.
US-M3-10 — Persona-tailored workspace view
FR-APP-15 (persona-tailored workspace scoping, Alpha (prototype))
As a Data Explorer, I want the chat workspace tailored to my role so that I see the framing and results relevant to exploration rather than engineering sign-off tasks.
- Given a Data Explorer persona, when I open a workspace, then the chat surface presents exploration-oriented framing (discovery, browsing) distinct from the Integrity Engineer’s action-oriented framing.
- Given an Integrity Engineer persona, when the same underlying data is queried, then results are framed toward verification/action rather than raw exploration.
- Given multiple workspaces I have access to, when I switch between them, then the persona-tailored framing is preserved per workspace.
US-M3-11 — Query firewall against injection and malicious input
FR-APP-16 (SQL-injection & malicious-input defense, Delivered)
As an Integrity Engineer, I want the chat assistant’s generated SQL to be firewalled against injection and malicious input so that a crafted question can never modify data or escape my workspace’s scope.
- Given a generated query, when it contains DML/DDL (INSERT/UPDATE/DELETE/DROP/ALTER) or an injection pattern (e.g. SLEEP, CHR/ASCII obfuscation), then it is rejected before execution.
- Given a query attempting to reference another workspace’s data, when it is generated, then the workspace scope is enforced and the cross-workspace reference is blocked.
- Given a rejected query, when the assistant responds, then the user sees a safe refusal rather than a raw database error or partial result.
M4 — Persistent Sensing · Q3 2026
Evidence Intake
US-M4-11 — Multi-modal anomaly review
FR-SCN-01 / FR-SCN-02 / FR-SCN-03 (Q3 Target)
As an Integrity Engineer, I want OGI, calibrated thermal, and gas readings ingested and rendered natively so that I can review anomalies across modalities in one place.
- Given a campaign with OGI/thermal/gas data, when it is ingested, then each modality is parsed, associated to its asset, and viewable without external tools.
- Given a modality file is malformed or unsupported, when ingestion runs, then it is rejected with a clear reason and does not block the other modalities.
World Model
US-M4-03 — Geo-tagged assets & imagery in 3D
As a Data Explorer, I want geo-tagged assets and imagery registered in the 3D scene so that I can see findings in physical context.
- Given geo-tagged captures, when I open the unit, then assets and images register to the same coordinate frame.
- Given a large scene, when I navigate, then the viewer streams tiles and stays interactive (no full-model load stall).
CAD & P&ID open standards
US-M4-08 — Click-through from 3D element to engineering identity
FR-CAD-01 (IFC4, In Progress Q2), FR-CAD-07 (dual-tagging, In Progress Q2)
As an Integrity Engineer, I want to select a 3D element and see its standard engineering identity so that I can move from a visual anomaly to its asset record without manual cross-referencing.
- Given an IFC4 model for the unit, when I select an equipment item, then its IFC class, tag, material/lining, and source are shown.
- Given a legacy CAD tag and an operator/DEXPI tag for the same asset, when I open either, then both resolve to the same asset record via the dual-tagging cross-reference.
- Given a tag the dual-tagging rules cannot resolve, when resolution fails, then the item is flagged for manual mapping rather than silently mismatched.
US-M4-09 — P&ID structure from a clicked asset
FR-CAD-06 (DEXPI ingestion, In Progress Q2)
As an Integrity Engineer, I want logical P&ID structure ingested via DEXPI so that a clicked asset shows its nozzles, connected lines, and connections.
- Given a DEXPI P&ID for the unit, when I view an equipment item, then its nozzles (with service), connected pipe runs, and source-to-target connections are listed.
- Given a non-compliant CAD export, when the DEXPI file is ingested, then it is sanitized and parsed rather than failing outright.
Application Surface
US-M4-13 — Focus the chat on an asset
FR-APP-17 (Q3 Target; builds on FR-CAD-07 dual-tagging and FR-VIS-02 geo-tagged assets)
As an Integrity Engineer, I want to set an asset — by its engineering tag, e.g. AB-106 — as my chat focus so that follow-up questions resolve against that asset without restating context each time.
- Given a tag in either its legacy CAD or operator/DEXPI form, when I set it as focus, then the scope shows the one resolved asset record (tag, class, material) via the dual-tagging cross-reference.
- Given a tag that does not resolve, when I set focus, then I get an explicit “unknown asset” response with nearest candidate tags — never a silent empty scope.
- Given an active asset focus, when I ask a question that names no asset, then the answer is scoped to the focused asset and states that scope.
US-M4-14 — Anomalies on an asset and its vicinity
FR-APP-17 (Q3 Target)
As an Integrity Engineer, I want to ask for all anomalies detected on the focused asset or within a stated distance around it so that I can review everything found at that location across modalities in one answer.
- Given a focused asset with associated findings, when I ask “what anomalies were detected on this asset”, then annotations linked to it (by tag or spatial association) are returned with evidence references.
- Given a stated radius (e.g. “within 5 m”), when I ask about the area around the asset, then findings within that distance of the asset’s coordinates are included, each labeled with its distance.
- Given no findings exist for the asset or radius, when I ask, then the answer states that none were detected rather than fabricating results.
Operator Handoff
US-M4-12 — One-click finding export
FR-APP-06 (Alpha (prototype))
As an Integrity Engineer, I want to export the active workspace selection and defect findings to PDF/Word so that I can share a defensible record without re-keying.
- Given a set of selected findings, when I export, then the document includes asset IDs, evidence references, severity, and recommended actions.
- Given an export is generated, when I open it, then content matches what is shown on screen (no missing or placeholder fields).
US-M4-05 — IDMS bidirectional integration
As an Integrity Engineer, I want a defined bidirectional IDMS integration so that an approved finding becomes planned work without re-keying — under human sign-off.
- Given an engineer-approved finding, when I hand it off, then a work item is created in the target IDMS with asset, evidence, and recommended action.
- Given Kav AI’s corrosion rate disagrees with the IDMS record, when synced, then both values are surfaced for the engineer — the existing record is not silently overwritten.
- Given a Critical finding or a Remaining-Life change, when handed off, then it requires engineer sign-off (canonical HITL rule).
US-M4-06 — Partner-integrated delivery
As an Operations Supervisor, I want a single procurement vehicle covering platform plus partner integrity-engineering services so that I can buy the closed loop without stitching two contracts — while keeping the option to contract separately.
- Given a partner-integrated engagement, when scoped, then the partner provides the HITL Integrity Engineer seat and the proposal is a single vehicle.
- Given a customer that prefers separate contracts, when requested, then the platform subscription and partner services can still be split.
Integrity Analytical Chain
US-M4-15 — Raise a finding as a claim about an asset
FR-DMR-01 (Alpha (prototype))
As an Integrity Engineer, I want a finding to be a claim that a named asset exhibits a condition, grounded in one condition class or one API 571 mechanism and citing the images that show it, so that what I decide on is an engineering statement and not a tagged photo.
- Given an asset and a set of images that depict it, when I raise a finding, then it records exactly one grounding (condition class or mechanism), the cited images, and starts as “possible”.
- Given a finding with no grounding or two groundings, when it is written, then the platform rejects it rather than storing an ambiguous claim.
US-M4-16 — Screen an asset for credible mechanisms
FR-DMR-02 (Alpha (prototype))
As an Integrity Engineer, I want the platform to propose the API 571 mechanisms credible for an asset’s material, service and unit so that my review starts from the catalogue rather than from memory.
- Given an asset profile, when screening runs, then each credible mechanism is proposed as a Tier-2 “possible” finding with its screening rationale.
- Given a screening proposal, when I read it, then it is labelled as screening, never as evidence, and asks me to confirm or dismiss.
US-M4-17 — Correct a finding and curate its evidence
FR-DMR-03 (Alpha (prototype))
As an Integrity Engineer, I want to re-ground a finding, replace its notes and add or remove the images it cites, so that a finding improves as evidence improves without losing its history.
- Given an existing finding, when I change its grounding, notes or cited images, then the current row reflects the change and an edit-log row records what changed, by whom, and when.
- Given an edited finding, when I open its history, then every edit is listed in order and none has been overwritten.
Operator Handoff
US-M4-18 — Decide a finding, with reasoning, in an append-only log
FR-OPS-02 (Alpha (prototype))
As an Integrity Engineer, I want to confirm, dismiss or reinstate a finding with my reasoning recorded verbatim against my name, so that a decision is an auditable judgement and a dismissal can be reversed without erasing it.
- Given a “possible” finding, when I confirm or dismiss it with reasoning, then a decision row is appended naming me, the verdict, the reasoning and the time, and the finding’s credibility reflects the latest decision.
- Given a dismissed finding, when I reinstate it, then the dismissal is superseded (both rows remain) and the finding returns to “possible”, not to confirmed.
US-M4-19 — Work one campaign queue
FR-OPS-03 (Alpha (prototype))
As an Integrity Engineer, I want one worklist per campaign over its findings and notes, ordered by what changed most recently, so that I can answer “what have I not looked at” without leaving the queue.
- Given a campaign with findings and notes, when I open its worklist, then both appear in one feed ordered by last change, each showing its kind from the organisation’s note vocabulary.
- Given a note that describes a condition on an asset, when I promote it, then a finding is created from it and the note records the promotion; the reverse is not offered.
US-M4-20 — Record an action that names its finding
FR-OPS-04 (Alpha (prototype))
As an Integrity Engineer, I want a work order or observation to carry the finding it follows from, so that the reason for the work travels with it into the export and the hand-off.
- Given a decided finding, when I record an action from it, then the action stores the finding reference, a status of open, and my summary.
- Given an open action, when work is scheduled or completed, then its status moves open → scheduled → complete and the change is attributed.
US-M4-21 — Hand a campaign over, or send it back
FR-OPS-05 (Alpha (prototype))
As a Data Explorer, I want to send a campaign for review when the evidence is ready, and as an Integrity Engineer I want to return it with a reason when it is not, so that the relay between the two workspaces is a state we can both see.
- Given a campaign in indexing, when the Data Explorer sends it for review, then its lifecycle becomes ready for review and it appears under “awaiting an engineer” in the Integrity workspace.
- Given a campaign awaiting review, when the Integrity Engineer returns it, then a reason is required, the lifecycle returns to indexing, and the campaign history shows who moved it, when, and why.
World Model
US-M4-22 — Attribute an image to an asset by the tag it depicts
FR-CAD-09 (Alpha (prototype))
As a Data Explorer, I want an image attributed to an asset only when the equipment tag in the frame has been read and I have confirmed it, so that a photo of a cable beside a vessel never becomes evidence about the vessel.
- Given an image whose OCR pass read an equipment tag, when I open the asset, then the image is offered as a suggested attribution that I confirm or reject, and my decision propagates to its RGB/thermal pair.
- Given images near an asset that carry no tag, when I open the asset, then they are listed as nearby (or framed, where camera pose is known) context and are never cited as evidence unless an engineer curates them onto a finding.
Application Surface
US-M4-23 — Drive the loop through an AI agent, as myself
FR-APP-22 (Alpha (prototype))
As an Integrity Engineer, I want an AI agent connected through the MCP surface to raise, correct, decide and curate findings and record actions as me — under my permissions and with my name on every write — so that the assistant can do the legwork while the judgement stays mine.
- Given an agent acting under my session, when it reads or writes, then row-level security applies as it would in the app, and every write is attributed to me.
- Given an agent asked to decide a finding, when I have not stated my conclusion, then it reports what it sees and asks, rather than deciding on my behalf; a decision write requires explicit confirmation.
US-M4-24 — Carry on a conversation, and keep conversations apart
FR-APP-03 (Q3 Target; the multi-turn half of US-M3-01, whose single-turn half is delivered)
As an Integrity Engineer, I want the assistant to remember what we were just talking about — and to offer me prompts about what I am looking at — so that a follow-up question is a short sentence, not a restatement of the whole context, and so that two conversations I have open never bleed into each other.
- Given I asked about a campaign’s images, when I follow up with “only the thermal ones”, then the answer narrows the previous one — the images returned are a subset of the first answer, from the same campaign, without my naming it again.
- Given two conversations open on different threads, when I continue one of them, then nothing from the other appears in the answer, and every event in the stream carries the thread I asked on — an engine never answers on a thread of its own choosing, and a blank thread id never lands me in someone else’s session.
- Given a selected campaign, module, candidate or asset, when I open the assistant, then the prompts it offers are about that selection — the campaign by name, the asset by tag — and change when the selection does.
- Given a conversation several turns long, when I ask “which dataset did I start with”, then the answer names the first dataset I asked about, not the most recent.
M5 — Engineering Context & Enterprise · Q4 2026
Evidence Intake
US-M5-01 — SCADA / IOW signals (read-only)
As an Integrity Engineer, I want read-only SCADA / OPC UA signals aligned to assets so that IOW exceedances can be reasoned about alongside physical evidence — without Kav AI ever writing to the control system.
- Given an OPC UA endpoint and a tag map, when the connector runs, then it reads values read-only and associates each to its asset in the world model.
- Given an IOW threshold is exceeded, when the value is ingested, then it is surfaced as a time-series signal on the asset, not as an autonomous action.
- Given the connector loses the endpoint, when a read fails, then it degrades to last-known with a staleness flag rather than blocking other evidence.
World Model
US-M5-02 — 3D CAD model overlay
As a Data Explorer, I want the engineering CAD model overlaid on the photorealistic scene so that I can read findings against as-designed geometry.
- Given an IFC4 model and the captured scene, when I open the unit, then the CAD overlay registers to the same coordinate frame as the assets and imagery.
- Given the overlay is on, when I inspect an asset, then its design geometry and field evidence are visible together.
US-M5-03 — CAD lifecycle: diff, as-built, change
FR-CAD-02, FR-CAD-03, FR-CAD-04, FR-CAD-08
As a Design Engineer, I want CAD versions tracked and compared to as-built so that engineering changes and field deviations are visible, across more than one CAD format.
- Given two CAD versions, when I diff them, then added/removed/changed elements are listed and highlighted in 3D.
- Given an as-built capture vs the as-designed model, when compared, then deviations beyond tolerance are flagged on the affected assets.
- Given an engineering change, when a new revision lands, then affected assets are notified for re-review.
- Given an RVT or DGN source, when ingested, then it resolves to the same asset schema as the IFC4 path (no format-specific dead end).
US-M5-04 — P&ID database (SQL) connector
As an Integrity Engineer, I want a direct read from the operator’s P&ID SQL database so that logical process structure is available even where a DEXPI export is not.
- Given P&ID database credentials, when the connector reads, then equipment, lines, and connectivity resolve to the same world-model assets as the DEXPI path.
- Given a tag present in SQL but not in CAD, when reconciled, then it is surfaced for dual-tagging rather than dropped.
Application Surface
US-M5-14 — Chat grounded on the 3D map
FR-APP-04, FR-APP-05 (Q3 Target)
As a Data Explorer, I want chat answers to highlight the relevant assets and overlays in the 3D model so that I can see where a finding is, not just read about it. (Pushed from M4: viewport grounding builds on the M4 asset-focus work and the CAD/P&ID-anchored world model.)
- Given an answer that references specific assets, when it is returned, then those assets are selectable/highlighted in the 3D view.
- Given an interactive overlay (thermal, gas, OGI) is available for the asset, when I open the result, then the relevant overlay can be toggled on in context.
US-M5-15 — Analyze an image on demand
FR-AI-10 (Q4 Target)
As an Integrity Engineer, I want to ask for an image to be analyzed from the viewer so that I get findings when I want them, without composing a chat message and hoping the assistant chooses the right tool.
- Given an image I am permitted to see, when I request analysis, then the findings returned correspond to that image and no other, and each is labelled with a location on the image.
- Given an image the analysis cannot read, when the attempt completes, then I am told it failed and why, rather than shown an empty result that looks like a clean surface.
- Given I lack permission for an image, when I request analysis, then the request is refused, and refusal is indistinguishable from the image not existing.
US-M5-16 — Review what the model proposed
FR-AI-11 (Q4 Target)
As an Integrity Engineer, I want proposed annotations shown as suggestions I can accept, reject, or recategorize so that model output never enters the record as though a person had drawn it.
- Given an analyzed image, when I open it, then suggestions are visually distinct from stored annotations and are not counted as annotations anywhere in the product.
- Given a suggestion I agree with, when I accept it, then it becomes an annotation attributed to me as the accepting reviewer, and the suggestion records that it was accepted.
- Given a suggestion with the wrong label, when I change its category and accept it, then the stored annotation carries my category and the record keeps what the model originally proposed.
- Given I accept an annotation, when the integrity workflow is consulted, then nothing has been confirmed as an operational finding — accepting an annotation is quality assurance, not integrity confirmation.
US-M5-17 — Analyze a collection without waiting on the page
FR-AI-12 (Q4 Target)
As an Integrity Engineer, I want to analyze a set of images as one run I can leave and come back to so that a large campaign is a background job rather than an afternoon spent holding a browser tab open.
- Given a selection of images, when I ask to analyze them, then I am shown how many are eligible, how many are already analyzed and will be skipped, and how many previously failed and will be retried — before anything runs or is billed.
- Given a run in progress, when I reload the page or open it elsewhere, then progress is accurate, because it is read from the run rather than from my connection.
- Given a run in progress, when I cancel it, then queued work stops and I am told what had already completed.
- Given a run where some images could not be read, when it finishes, then it reports how many succeeded and how many failed with reasons, and is not presented as a plain success.
- Given images already analyzed by the same skill version, when I start a run over them, then they are skipped by default and re-analyzed only if I explicitly ask for it.
US-M5-18 — Know what produced a finding, and who decided about it
FR-AI-13 (Q4 Target)
As an Integrity Engineer, I want every finding to carry what produced it and every decision to be kept so that a result can be reproduced, questioned, and audited a year later.
- Given any finding, when I inspect it, then I can see which backend, model version, and skill version produced it, and when.
- Given a reviewer who rejects a suggestion and later accepts it, when the history is read, then both decisions are present with their actors and times — the later one does not overwrite the earlier.
- Given two backends configured for the same skill, when their findings are compared, then each is attributable to the backend that produced it rather than to the skill alone.
Evidence Confidence
US-M5-05 — Multi-source confirmed reporting
As an On-call Integrity Engineer, I want the cross-source correlation engine to report multi-source confirmed performance so that the closed loop has a measured accuracy bar.
- Given the multi-source confirmed set, when measured, then TPR / FPR are reported against the calibration curve (target TPR > 98% / FPR < 2%).
- Given a correlated finding, when surfaced, then the contributing sources and match basis are shown so the confirmation is auditable.
US-M5-06 — Physical-AI reasoning to remediation
FR-ANO-02 — research-gated
As an Integrity Engineer, I want a finding reasoned from anomaly → damage mechanism → remediation so that I get a defensible recommendation, with a safe fallback if the capability is not yet validated.
- Given a confirmed finding, when reasoning runs, then the suggested mechanism and remediation cite API 571/581/584 grounding.
- Given the research bar (> 90% agreement with the IE panel) is not met, when the feature ships, then it falls back to descriptive reporting only — no remediation advice.
- Given any suggestion, when surfaced, then it passes the Filter Skill and confidence gate first (priority order preserved).
US-M5-07 — Synthetic data for rare defects
FR-MDA-02 — research-gated
As a Data Explorer, I want synthetic data generation for rare defect classes so that detection models improve where real examples are scarce.
- Given a rare defect class, when synthetic examples are generated, then they are labelled synthetic and never mixed untracked into evaluation sets.
- Given the spike does not meet its go criterion, when assessed, then the fallback (no synthetic augmentation) is recorded and detection proceeds on real data only.
US-M5-10 — Calibrated, gated AI outputs
As an On-call Integrity Engineer, I want confidence calibration, a chain-level consistency gate, and an out-of-distribution (OOD) detector so that I can trust what reaches my dashboard.
- Given a stated confidence, when compared to empirical accuracy per bucket, then calibration error is within target and reported per campaign.
- Given a chain of inferences, when Stage 3.5 runs, then internally inconsistent conclusions are withheld.
- Given an out-of-distribution input, when detected, then the output is marked “UNCERTAIN — REVIEW REQUIRED” and the OOD detector’s update cadence is honoured.
US-M5-19 — A new detector must earn its place
FR-AI-14 (Q4 Target)
As an Integrity Engineer, I want a new model or skill revision measured before it becomes the default so that “newer” is never mistaken for “better” in a product whose output is inspection evidence.
- Given a candidate backend or skill revision, when adoption is proposed, then it has been measured on a frozen, independently annotated evaluation set using the agreed protocol, and the numbers are recorded against that revision.
- Given a candidate that is worse than the incumbent on the agreed metric, when adoption is proposed, then it does not become the production default regardless of cost or speed advantages.
- Given review history from accepted and rejected suggestions, when quality is assessed, then that history is used as training evidence and not as the evaluation set — it only observes what the current model proposed, so it cannot show what the model missed.
US-M5-11 — Cross-source correlation primitive
FR-XSC-01, FR-ANO-01 — FR-ANO-01 research-gated
As an On-call Integrity Engineer, I want findings correlated across modalities (tag / match / score / surface) so that multi-source agreement raises confidence and contradictions are flagged rather than averaged away.
- Given anomalies from ≥ 2 sources on one asset, when correlated, then they are merged into a single finding with a calibrated confidence.
- Given sources that disagree, when correlated, then the contradiction is surfaced for review, not silently averaged.
- Given the cross-modal anomaly spike does not meet its bar, when it ships, then it falls back to manual triage rather than autonomous flagging.
US-M5-12 — Grounded damage-mechanism suggestions
FR-AI-01 (Filter Skill calibration & FNR, Q4 Target)
As an On-call Integrity Engineer, I want AI-suggested damage mechanisms checked against a deterministic susceptibility filter so that implausible suggestions never reach my action dashboard.
- Given a suggested mechanism inconsistent with the asset’s material/process, when it is generated, then the Filter Skill rejects it before surfacing.
- Given an output below the confidence threshold, when it is produced, then it is marked “UNCERTAIN — REVIEW REQUIRED” and withheld from the Critical Action dashboard.
- Given cross-source corroboration exists, when it is applied, then it can raise priority but cannot override a Filter Skill rejection (priority order: Filter Skill > consistency gate > cross-source uplift).
Integrity Analytical Chain
US-M5-13 — RBI inspection intervals and scope
FR-RBI-01, FR-RBI-02, FR-MDA-01
As an Integrity Engineer, I want API 581 risk and inspection-interval calculation within a clear automation boundary, benchmarked against industry RAM data, so that recommended intervals are defensible.
- Given asset, damage-mechanism, and consequence inputs, when computed, then the inspection interval follows API 581 with the inputs shown.
- Given an equipment class outside the automation boundary, when requested, then it is clearly marked out-of-scope rather than silently computed.
- Given Solomon (or sector-equivalent) RAM data, when benchmarked, then results are expressed relative to the peer profile.
Operator Handoff
US-M5-08 — SAP PM certified connector
As an Integrity Engineer, I want a certified SAP PM connector so that approved findings become planned maintenance in the system of record without re-keying.
- Given an engineer-approved finding, when I hand it off, then an SAP PM work order is created with asset, evidence, and recommended action.
- Given the connector is certified, when it writes, then it conforms to the operator’s SAP PM integration requirements and the canonical HITL sign-off rule.
Security & Compliance · Deployment
US-M5-20 — My imagery stays mine
FR-SEC-05 (Q4 Target)
As an Operations Supervisor, I want analysis output and anything derived from our imagery to stay inside my tenant so that using the product does not quietly contribute our site’s data to someone else’s model.
- Given suggestions and review decisions generated from our images, when any tenant boundary is applied, then they are scoped to our tenant like the images themselves.
- Given a pilot that ends without continuation, when deletion is requested, then suggestions, decisions, and derived datasets or exports are covered by the same deletion workflow as the imagery.
- Given a proposal to train a shared model, when our data would be included, then it is excluded unless we have authorized it in writing, and any derived artefact remains traceable to its source tenant so the obligation can be assessed.
US-M5-09 — Certification, compliance, and deployment profiles
FR-SEC-01, FR-SEC-03, FR-SEC-02, FR-NUC-01 (H1 2027)
As an Operations Supervisor, I want SOC 2 Type II, compliance management, and a customer cloud-tenant / air-gapped deployment option so that the platform clears procurement and OT security review.
- Given a procurement review, when SOC 2 Type II evidence is requested, then the report and compliance package are available.
- Given a high-security site, when deployed, then a customer-tenant or air-gapped profile runs the same capabilities within the operator’s perimeter.
- Given a high-hazard site, when the dose-aware workflow is scoped (H1 2027), then it is labelled roadmap, not a v1 commitment.
H1 2027 — Roadmap horizon
Evidence Intake
US-H1-01 — Autonomous robot coverage
FR-ROB-01, FR-ROB-04, FR-ROB-05
As an Operations Supervisor, I want robot/KRSI captures ingested and orchestrated for coverage so that the facility is inspected on a schedule without manual flight planning.
- Given a KRSI capture set, when it is ingested, then each frame is normalized, provenance-tagged (carrier + modality), and spatially anchored.
- Given a coverage plan, when patrols run, then covered vs missed assets are reported so gaps are visible.
- Given repeated patrols, when fleet analytics run, then coverage and capture quality trends are available per unit.
US-H1-02 — Fixed capture infrastructure
As an Operations Supervisor, I want fixed navigation beacons and a communication backbone so that autonomous capture is reliable where onboard SLAM alone is not.
- Given installed beacons, when a robot navigates, then localization meets the registration-accuracy target for as-built comparison.
- Given a backbone outage, when connectivity drops, then captures buffer locally and sync on reconnect rather than being lost.
Application Surface
US-H1-03 — Full spatial navigation
As a Data Explorer, I want full spatial navigation through the unit so that I can move through confined and hard-to-reach space and follow a repeatable robot path.
- Given the anchored 3D scene, when I navigate, then confined-space fly-through and spatial asset search resolve to the same assets as the 2D and map views.
- Given a robot patrol path, when replayed, then the navigation follows the beacon-anchored route for repeatable coverage.
Generated by docs/portfolio/_build/generate_user_stories_page.py from docs/portfolio/product/user-stories/*.qmd. Regenerate after editing a story.