@halfway-lab/question-expansion
v0.1.9
Published
Normalize, validate, and audit compatible raw exploration payloads into stable Question Expander path data.
Maintainers
Readme
@halfway-lab/question-expansion
Normalize raw exploration output into stable path data.
Validate, normalize, and audit compatible raw exploration payloads, including HWP-style payloads, before they hit your UI, storage, or product logic.
- Normalize unstable provider output into one stable contract
- Surface unknown fields as findings instead of silently missing them
- Build product-ready overviews and path artifacts on top of normalized data
npm install @halfway-lab/question-expansionimport { validateRawExpansion } from '@halfway-lab/question-expansion'
const result = validateRawExpansion({
question: 'Should we expand internationally this year?',
paths: [
{
path_id: 'path-1',
title: 'Reframe the market-entry assumption',
follow_up_question: 'Which constraint matters more than market size?'
}
]
})
if (result.valid) {
console.log(result.normalized.expansionPaths)
}Why use it:
- Stable output contract for Question Expander-style path exploration
- Tolerant validation with schema-aware fallback and unknown-field findings
- Built-in helpers for overviews, session artifacts, view models, and payload audits
Next Step
import { buildStructuredOverview } from '@halfway-lab/question-expansion'
const normalized = result.normalized
const overview = buildStructuredOverview(normalized.question, normalized.expansionPaths)
console.log(normalized.expansionPaths[0].path_title)
console.log(overview.nextQuestions)Best For
- apps that render exploration trees, branches, or follow-up question paths
- adapters that need to normalize unstable provider output before it reaches product logic
- audit workflows that compare live protocol output against a stable app contract
- teams evolving a reasoning or question-expansion protocol while keeping downstream UI stable
Input To Output
Raw input:
{
"question": "Should we expand internationally this year?",
"paths": [
{
"path_id": "path-1",
"title": "Reframe the market-entry assumption",
"follow_up_question": "Which constraint matters more than market size?",
"path_type": "premise_shift"
}
]
}Normalized output:
{
"question": "Should we expand internationally this year?",
"expansionPaths": [
{
"id": "path-1",
"path_title": "Reframe the market-entry assumption",
"next_question": "Which constraint matters more than market size?",
"branch_type": "premise_shift"
}
]
}That means upstream payloads can evolve, while your UI and product logic keep depending on one stable shape.
Version
Current local package version: 0.1.9
License
MIT
Verification
- package self-test:
npm test - raw payload audit:
npm run audit:raw-expansion -- ./path/to/payload.json - live chain-log audit:
npm run audit:raw-expansion -- /path/to/chain_*.jsonl - raw payload audit as markdown:
npm run audit:raw-expansion -- ./path/to/payload.json --format markdown - legacy CLI alias still supported:
npm run audit:raw-hwp -- ... - downstream integration check: run the Question Expander app tests from
apps/question-expander - heuristic rule notes:
docs/HEURISTICS.md - release readiness notes:
docs/RELEASE_READINESS.md
Core Capabilities
- Raw expansion request shaping with
buildRawHwpExpandRequest(...) - Raw exploration payload normalization for object or top-level array payloads
- Schema-aware validation with protocol-version fallback
- Unknown-field auditing at both top-level and path-level
- Overview and session artifact generation for Question Expander-style UX
Owns
- Question Expander path contract normalization
- branch-type labels and product-facing path semantics
- structured overview generation
- view-model assembly for focused branch exploration
- session artifacts such as pause summaries, markdown export content, and session summaries
- session record and history-card view model shaping
- pure runtime helpers for tree-state maps, session ids, and status copy
Does Not Own
- app UI and interaction rendering
- browser-local persistence implementation
- protocol/HWP execution authority
- adapter transport details
- app state management
Package Surface
import {
buildRawExpansionAuditReport,
normalizeRawExpansion,
summarizeRawExpansionValidation,
validateRawExpansion,
buildRawHwpExpandRequest,
buildRawHwpAuditReport,
buildChildParentMap,
buildExpansionViewModel,
buildHistoryCardViewModel,
buildPathMarkdown,
buildPauseSummary,
buildRootParentMap,
buildSessionRecord,
buildSessionSummary,
buildStatusMessage,
buildStructuredOverview,
createSessionId,
extractRawHwpAuditPayload,
formatSessionTimestamp,
getBranchTypeLabel,
inferLiveBranchType,
LIVE_BRANCH_TYPE_RULES,
matchLiveBranchTypeRule,
normalizeExpansionPath,
normalizeExpansionResponse,
normalizeRawHwpExpansion,
normalizeRawHwpPath,
summarizeRawHwpValidation,
validateRawHwpExpansion
} from '@halfway-lab/question-expansion'Common Workflows
Validate and normalize a provider payload:
import { validateRawExpansion } from '@halfway-lab/question-expansion'
const result = validateRawExpansion(payload)
if (result.valid) {
console.log(result.normalized.expansionPaths)
} else {
console.log(result.findings)
}Audit a real payload from the CLI:
npm run audit:raw-expansion -- ./payload.json
npm run audit:raw-expansion -- ./payload.json --format markdown
npm run audit:raw-expansion -- ./chain_2026-03-31.jsonlBuild a product-facing expansion view model:
import {
normalizeRawExpansion,
buildExpansionViewModel
} from '@halfway-lab/question-expansion'
const normalized = normalizeRawExpansion(payload)
const viewModel = buildExpansionViewModel({
question: normalized.question,
rootPaths: normalized.expansionPaths,
focusedPathId: normalized.expansionPaths[0]?.id
})
console.log(viewModel.structuredOverview)What Makes It Different
- It is tolerant by default: unknown fields become findings instead of hard failures.
- It is product-oriented: outputs are shaped for apps, not raw protocol internals.
- It is practical for real migrations: you can audit live chain logs before you trust a new upstream contract.
Current Structure
src/
branchTypes.js
contracts/
liveBranchTypeHeuristics.js
paths.js
rawHwp.js
overview/
structuredOverview.js
runtime/
status.js
treeState.js
session/
historyViewModel.js
sessionArtifacts.js
sessionRecord.js
viewModel/
buildExpansionViewModel.js
index.jsBoundary
The intended long-term flow is:
- an upstream adapter or runtime provides a compatible raw exploration contract
packages/question-expansionvalidates and interprets that raw payload into stable Question Expander structuresapps/question-expanderowns input, rendering, interaction, revisit flows, and mobile UX
This package is a standalone product-domain package. It should not be described as an interpretation layer for any other package.
Upstream
halfway-lab/HWP is one supported upstream contract family, and an important reference implementation for this package.
This package should depend only on a compatible raw exploration contract. It should not depend on upstream repository-internal file layout, scripts, or module structure.
For audit and alignment only, the CLI can also read a real HWP chain_*.jsonl log entry and extract a contract-shaped payload before validation. That extraction path is intentionally audit-only, reports which fields were derived or inferred, and does not change the runtime product contract.
