This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
npm start— dev server at http://localhost:4200 (ng serve).npm run build— prod build intodist/risk/browser(+ SSRdist/risk/server).npm run watch— dev build, watch mode.npm test— Vitest unit tests viang test. Single spec:npx vitest run src/daga/utils/<file>.spec.ts.npm run lint— angular-eslint + typescript-eslint + prettier rules.npm run format/format:check— Prettier write/check.npm run cy:open/cy:run— Cypress (project roote2e/, baseUrlhttp://localhost:4200). Dev server must be running.npm run serve:ssr:risk— run SSR server bundle fromdist/.- Deploy:
scripts/publish-pre.sh(pre-risk.metadev.pro) andscripts/publish-pro.sh(risk.metadev.pro). Bothnpm run buildthen sync to S3 (region eu-south-2) viadeploy-to-s3.sh+ apply CORS JSON. Require AWS CLI creds.
Angular 21 standalone-component SPA (SSR-enabled) wrapping the @metadev/daga / @metadev/daga-angular diagram engine to model probability graphs. Two diagram modes share one canvas abstraction.
src/main.tsbootstrapsSimpleComponent(src/daga/component/prob.component.ts) withsimpleAppConfig(prob.app.config.ts, onlyprovideBrowserGlobalErrorListeners).SimpleComponentis shell: sidebar +selectedModel: 'binomial' | 'bayes'switches between two feature components. TemplatedagaIndex.html.- SSR entrypoints:
main.server.ts,server.ts(Express).
src/daga/component/dagaBase.component.ts is shared engine logic for both modes. Key contract:
- Inputs:
autoNormalizeAdjacent,showTheoreticalProbabilities,branchValueKey(default'probability', switched to weight key in binomial),bayesMode,bayesGraph. - Subscribes to
canvas.diagramChange$and dispatches onUpdateValuesAction/AddConnectionAction/RemoveAction. - Probability key + max stored as
PROBABILITY_KEY/MAX_PROBABILITY(0–100 scale, see commit4021dd7). All edits flow throughnormalizeProbabilityinutils/probability.utils.ts. - Sibling-rebalance logic lives in
utils/connectionCalculate.utils.ts(handleConnectionStructuralChange,handleConnectionUpdateValues,AUTO_NORMALIZE_ADJACENT_KEY). Re-entry guarded byisApplyingConnectionRebalance. - Decorators: SVG/foreignObject overlays drawn via
canvas.model.decorators.new(...). Three suffixes:-probability-decorator,-theoretical-probability-decorator,-bayes-decorator. Always remove-then-redraw on every diagram change (refreshProbabilityDecorators). - Bayes mode uses DOM
dblclicklistener ondaga-diagramelement +data-node-idwalk-up to emitnodeDoubleClicked;handleUpdateValuesActionis no-op whenbayesMode=true. - Validator
DagaBaseDiagramValidatorerrors when model has zero nodes.
Node id normalization (utils/generalCalculationNodes.utils.ts → normalizeNodeId) is required because @metadev/daga may suffix ids; always normalize before keying maps/emitting.
Each has component + config + utils:
- Binomial —
binomial.component.ts, weight-based branching. Theoretical probabilities computed viabinomialWeight.utils.ts::calculateTheoreticalNodeProbabilities. Per-connection nodes inbinomialCalculationNodes.utils.ts.branchValueKeyswitches off'probability'so connection labels show raw weights. - Bayes —
bayes.component.ts, configbayes.config.ts. Inference engine inutils/bayes/bayesInference.utils.ts; supporting modules:causalLayout.ts,csv.utils.ts,em.utils.ts,mle.utils.ts,montecarlo.utils.ts,structureLearning.utils.ts,syntheticData.utils.ts. Bayes graph passed toDagaBaseComponentvia[bayesGraph]Input; node marginals (si/no) +evidencerendered as inline foreignObject bars.
generic.component.ts is the abstract pattern host for the two feature components — they extend it and pass mode-specific config to the daga canvas.
- Keep probability scale 0–100 everywhere; convert at I/O boundary only. Never re-introduce 0–1 scale without updating
MAX_PROBABILITY. - Always go through
normalizeProbability/normalizeWeightValuebefore writing to avalueSet. - After any structural change to connections, refresh decorators AND
connectionSourceByConnectionIdmap (used to recover source nodes forRemoveAction). - Cypress specs use
data-cytest IDs (see commit6023960). New interactive UI must expose stabledata-cy. - Prettier + eslint-config-prettier active — run
npm run formatbefore commits.
utils/importExport.utils.ts::RiskFile is the canonical serialization format. Shape:
- Bayesian CPTs and evidence live in
RiskFile.bayes— not insidedaga.nodes[].valueSet. Runtime keeps the authoritative state inBayesComponent.bayesGraph;buildBayesGraphonly builds topology + default uniform CPTs. readRiskFilerunsmigrateLegacyValueKeysto rewrite legacy aliases: connectionschance/probability→weight; nodeschance→probability. Canonical keys per entity: connections useweight, nodes useprobability.
CSV format consumed by the "Aprender desde CSV" flow:
- Optional comment lines starting with
#at the top of the file. Recognized directive:# edges: Padre->Hijo; Padre->Hijo; .... Used to auto-create connections when the CSV introduces nodes that don't yet exist in the diagram. - Header row: column names must match
bayes_node.name(case-insensitive) for learning to associate samples with nodes. - Data rows: cell values accepted by
normalizarValor:si/no,yes/no,1/0,true/false. Empty cells mark the variable as hidden in that row → EM is used instead of MLE.
Without the # edges: directive, importing a CSV that introduces new variables creates only the nodes, leaving the user to wire the DAG manually. UI banner warns when this happens (creationSummary.missingEdgesWarning).
- Exact inference (
recalcAllMarginals) is hard-capped atMAX_EXACT_INFERENCE_NODES = 20. Beyond that the function skips enumeration andBayesComponentalerts the user once. Use Monte Carlo (likelihood weighting inmontecarlo.utils.ts) for approximate inference on larger nets. - UI edits (
setEvidence,updateCPTCell) route throughBayesComponent.scheduleRecalcwhich debouncesrecalcAllMarginalsat 200 ms to collapse keystroke bursts.
{ "riskFileVersion": 1, "modelType": "binomial" | "bayes", "exportedAt": "<ISO date>", "daga": <DagaModel>, "bayes": { "nodes": { "<nodeId>": { "evidence": "si"|"no"|null, "cpt": <BayesCPT> } } } // bayes mode only }