waterplane 0.1.24 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/SECURITY.md +25 -5
- package/node_modules/@waterplane/shared/dist/agentseries/compare.d.ts +8 -0
- package/node_modules/@waterplane/shared/dist/agentseries/compare.js +103 -0
- package/node_modules/@waterplane/shared/dist/agentseries/compare.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/agentseries/markers.d.ts +17 -0
- package/node_modules/@waterplane/shared/dist/agentseries/markers.js +125 -0
- package/node_modules/@waterplane/shared/dist/agentseries/markers.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/agentseries/series.d.ts +16 -0
- package/node_modules/@waterplane/shared/dist/agentseries/series.js +93 -0
- package/node_modules/@waterplane/shared/dist/agentseries/series.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/agentseries/stats.d.ts +8 -0
- package/node_modules/@waterplane/shared/dist/agentseries/stats.js +33 -0
- package/node_modules/@waterplane/shared/dist/agentseries/stats.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/agentseries/types.d.ts +103 -0
- package/node_modules/@waterplane/shared/dist/agentseries/types.js +11 -0
- package/node_modules/@waterplane/shared/dist/agentseries/types.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/agentseries.d.ts +10 -0
- package/node_modules/@waterplane/shared/dist/agentseries.js +11 -0
- package/node_modules/@waterplane/shared/dist/agentseries.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/calday.d.ts +5 -0
- package/node_modules/@waterplane/shared/dist/calday.js +10 -0
- package/node_modules/@waterplane/shared/dist/calday.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/clihealth/healthfixture.d.ts +13 -1
- package/node_modules/@waterplane/shared/dist/clihealth/healthfixture.js +22 -4
- package/node_modules/@waterplane/shared/dist/clihealth/healthfixture.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/clihealth.d.ts +1 -1
- package/node_modules/@waterplane/shared/dist/clihealth.js +1 -1
- package/node_modules/@waterplane/shared/dist/clihealth.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/dictate.d.ts +6 -0
- package/node_modules/@waterplane/shared/dist/dictate.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/dictatemodels.d.ts +23 -0
- package/node_modules/@waterplane/shared/dist/dictatemodels.js +31 -0
- package/node_modules/@waterplane/shared/dist/dictatemodels.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/commits.d.ts +1 -1
- package/node_modules/@waterplane/shared/dist/healthindex/commits.js +2 -2
- package/node_modules/@waterplane/shared/dist/healthindex/commits.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/healthindex/coverage.d.ts +128 -0
- package/node_modules/@waterplane/shared/dist/healthindex/coverage.js +343 -0
- package/node_modules/@waterplane/shared/dist/healthindex/coverage.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/healthindex/readings.d.ts +9 -1
- package/node_modules/@waterplane/shared/dist/healthindex/readings.js +122 -4
- package/node_modules/@waterplane/shared/dist/healthindex/readings.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/healthindex/repoindex.d.ts +5 -0
- package/node_modules/@waterplane/shared/dist/healthindex/repoindex.js +2 -0
- package/node_modules/@waterplane/shared/dist/healthindex/repoindex.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/healthindex/score.d.ts +3 -0
- package/node_modules/@waterplane/shared/dist/healthindex/score.js +52 -16
- package/node_modules/@waterplane/shared/dist/healthindex/score.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/healthindex/types.d.ts +82 -6
- package/node_modules/@waterplane/shared/dist/healthindex/types.js +35 -2
- package/node_modules/@waterplane/shared/dist/healthindex/types.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/healthindex/words.js +65 -6
- package/node_modules/@waterplane/shared/dist/healthindex/words.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/healthindex.d.ts +21 -7
- package/node_modules/@waterplane/shared/dist/healthindex.js +20 -7
- package/node_modules/@waterplane/shared/dist/healthindex.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/healthindexresponse.js +3 -2
- package/node_modules/@waterplane/shared/dist/healthindexresponse.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/healthspend.d.ts +23 -0
- package/node_modules/@waterplane/shared/dist/healthspend.js +32 -1
- package/node_modules/@waterplane/shared/dist/healthspend.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/hints.js +9 -0
- package/node_modules/@waterplane/shared/dist/hints.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/index.d.ts +9 -0
- package/node_modules/@waterplane/shared/dist/index.js +9 -0
- package/node_modules/@waterplane/shared/dist/index.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/installrow.js +10 -0
- package/node_modules/@waterplane/shared/dist/installrow.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/intent/kind.d.ts +45 -1
- package/node_modules/@waterplane/shared/dist/intent/kind.js +60 -2
- package/node_modules/@waterplane/shared/dist/intent/kind.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/intent.d.ts +1 -1
- package/node_modules/@waterplane/shared/dist/intent.js +1 -1
- package/node_modules/@waterplane/shared/dist/intent.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/itempaths.d.ts +23 -0
- package/node_modules/@waterplane/shared/dist/itempaths.js +38 -0
- package/node_modules/@waterplane/shared/dist/itempaths.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/pluginlaunch.d.ts +3 -2
- package/node_modules/@waterplane/shared/dist/pluginlaunch.js +1 -1
- package/node_modules/@waterplane/shared/dist/pluginlaunch.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/pricelist.d.ts +57 -0
- package/node_modules/@waterplane/shared/dist/pricelist.js +128 -0
- package/node_modules/@waterplane/shared/dist/pricelist.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/pricing.d.ts +86 -9
- package/node_modules/@waterplane/shared/dist/pricing.js +140 -20
- package/node_modules/@waterplane/shared/dist/pricing.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/queue/queuelanestate.d.ts +14 -0
- package/node_modules/@waterplane/shared/dist/queue/queuelanestate.js +25 -0
- package/node_modules/@waterplane/shared/dist/queue/queuelanestate.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/queue/queueplan.d.ts +4 -0
- package/node_modules/@waterplane/shared/dist/queue/queueplan.js +21 -0
- package/node_modules/@waterplane/shared/dist/queue/queueplan.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/queue/queuewords.js +2 -1
- package/node_modules/@waterplane/shared/dist/queue/queuewords.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/queue.d.ts +2 -0
- package/node_modules/@waterplane/shared/dist/queue.js +1 -0
- package/node_modules/@waterplane/shared/dist/queue.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/repohealth.d.ts +178 -0
- package/node_modules/@waterplane/shared/dist/repohealth.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/repohealthhabits.d.ts +15 -0
- package/node_modules/@waterplane/shared/dist/repohealthhabits.js +117 -0
- package/node_modules/@waterplane/shared/dist/repohealthhabits.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/repohealthnative.d.ts +10 -0
- package/node_modules/@waterplane/shared/dist/repohealthnative.js +94 -0
- package/node_modules/@waterplane/shared/dist/repohealthnative.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/repohealthread.js +23 -1
- package/node_modules/@waterplane/shared/dist/repohealthread.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/skillstate.d.ts +51 -0
- package/node_modules/@waterplane/shared/dist/skillstate.js +176 -0
- package/node_modules/@waterplane/shared/dist/skillstate.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/skillwords.d.ts +10 -0
- package/node_modules/@waterplane/shared/dist/skillwords.js +18 -0
- package/node_modules/@waterplane/shared/dist/skillwords.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/wire/agentreadings.d.ts +248 -0
- package/node_modules/@waterplane/shared/dist/wire/agentreadings.js +36 -0
- package/node_modules/@waterplane/shared/dist/wire/agentreadings.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/wire/backend.d.ts +2 -0
- package/node_modules/@waterplane/shared/dist/wire/costwindow.d.ts +4 -0
- package/node_modules/@waterplane/shared/dist/wire/dictatesetup.d.ts +42 -0
- package/node_modules/@waterplane/shared/dist/wire/dictatesetup.js +9 -0
- package/node_modules/@waterplane/shared/dist/wire/dictatesetup.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/wire/messages/hostcore.d.ts +22 -1
- package/node_modules/@waterplane/shared/dist/wire/notify.d.ts +6 -1
- package/node_modules/@waterplane/shared/dist/wire/notify.js +6 -1
- package/node_modules/@waterplane/shared/dist/wire/notify.js.map +1 -1
- package/node_modules/@waterplane/shared/dist/wire/repo.d.ts +1 -1
- package/node_modules/@waterplane/shared/dist/wire/skills.d.ts +142 -0
- package/node_modules/@waterplane/shared/dist/wire/skills.js +6 -0
- package/node_modules/@waterplane/shared/dist/wire/skills.js.map +1 -0
- package/node_modules/@waterplane/shared/dist/wire/sysstat.d.ts +17 -0
- package/node_modules/@waterplane/shared/dist/wire/telemetry.d.ts +4 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/packages/extensions/diskspace/waterplane-plugin.json +16 -0
- package/packages/extensions/links/waterplane-plugin.json +18 -0
- package/packages/host/dist/agentclass.d.ts +116 -0
- package/packages/host/dist/agentclass.js +339 -0
- package/packages/host/dist/agentclass.js.map +1 -0
- package/packages/host/dist/agentintents.d.ts +18 -0
- package/packages/host/dist/agentintents.js +40 -7
- package/packages/host/dist/agentintents.js.map +1 -1
- package/packages/host/dist/agentmarkers.d.ts +49 -0
- package/packages/host/dist/agentmarkers.js +255 -0
- package/packages/host/dist/agentmarkers.js.map +1 -0
- package/packages/host/dist/agentreadings.d.ts +68 -0
- package/packages/host/dist/agentreadings.js +336 -0
- package/packages/host/dist/agentreadings.js.map +1 -0
- package/packages/host/dist/agentscan.d.ts +8 -0
- package/packages/host/dist/agentscan.js +427 -0
- package/packages/host/dist/agentscan.js.map +1 -0
- package/packages/host/dist/archive.js +9 -3
- package/packages/host/dist/archive.js.map +1 -1
- package/packages/host/dist/artifacts.js +4 -7
- package/packages/host/dist/artifacts.js.map +1 -1
- package/packages/host/dist/askrules.js +12 -4
- package/packages/host/dist/askrules.js.map +1 -1
- package/packages/host/dist/auth.d.ts +1 -0
- package/packages/host/dist/auth.js +5 -3
- package/packages/host/dist/auth.js.map +1 -1
- package/packages/host/dist/autopull.js +4 -8
- package/packages/host/dist/autopull.js.map +1 -1
- package/packages/host/dist/backends/claude.js +1 -0
- package/packages/host/dist/backends/claude.js.map +1 -1
- package/packages/host/dist/backends/derive.js +3 -1
- package/packages/host/dist/backends/derive.js.map +1 -1
- package/packages/host/dist/binguard.js +19 -2
- package/packages/host/dist/binguard.js.map +1 -1
- package/packages/host/dist/capture.js +7 -10
- package/packages/host/dist/capture.js.map +1 -1
- package/packages/host/dist/clifixtures.d.ts +24 -4
- package/packages/host/dist/clifixtures.js +50 -10
- package/packages/host/dist/clifixtures.js.map +1 -1
- package/packages/host/dist/clihealth.d.ts +8 -2
- package/packages/host/dist/clihealth.js +11 -3
- package/packages/host/dist/clihealth.js.map +1 -1
- package/packages/host/dist/costwindow.js +4 -2
- package/packages/host/dist/costwindow.js.map +1 -1
- package/packages/host/dist/ctxlog/ctxagents.d.ts +2 -0
- package/packages/host/dist/ctxlog/ctxagents.js +5 -5
- package/packages/host/dist/ctxlog/ctxagents.js.map +1 -1
- package/packages/host/dist/ctxlog/ctxcursor.d.ts +2 -0
- package/packages/host/dist/ctxlog/ctxcursor.js +2 -2
- package/packages/host/dist/ctxlog/ctxcursor.js.map +1 -1
- package/packages/host/dist/ctxlog/ctxupdate.js +11 -6
- package/packages/host/dist/ctxlog/ctxupdate.js.map +1 -1
- package/packages/host/dist/deliver/deliverknobs.d.ts +0 -2
- package/packages/host/dist/deliver/deliverknobs.js +0 -2
- package/packages/host/dist/deliver/deliverknobs.js.map +1 -1
- package/packages/host/dist/deliver/deliverproof.d.ts +3 -2
- package/packages/host/dist/deliver/deliverproof.js +9 -8
- package/packages/host/dist/deliver/deliverproof.js.map +1 -1
- package/packages/host/dist/deliver/deliverreturn.d.ts +3 -2
- package/packages/host/dist/deliver/deliverreturn.js +13 -12
- package/packages/host/dist/deliver/deliverreturn.js.map +1 -1
- package/packages/host/dist/deliver/deliverrun.js +20 -18
- package/packages/host/dist/deliver/deliverrun.js.map +1 -1
- package/packages/host/dist/deliver/deliverscreen.d.ts +2 -1
- package/packages/host/dist/deliver/deliverscreen.js +9 -8
- package/packages/host/dist/deliver/deliverscreen.js.map +1 -1
- package/packages/host/dist/deliver/delivertypes.d.ts +4 -0
- package/packages/host/dist/deliver.js +2 -1
- package/packages/host/dist/deliver.js.map +1 -1
- package/packages/host/dist/dictate.d.ts +11 -0
- package/packages/host/dist/dictate.js +20 -10
- package/packages/host/dist/dictate.js.map +1 -1
- package/packages/host/dist/dictatesetup.d.ts +54 -0
- package/packages/host/dist/dictatesetup.js +261 -0
- package/packages/host/dist/dictatesetup.js.map +1 -0
- package/packages/host/dist/doctor.js +1 -1
- package/packages/host/dist/doctor.js.map +1 -1
- package/packages/host/dist/exposure.d.ts +10 -0
- package/packages/host/dist/exposure.js +25 -0
- package/packages/host/dist/exposure.js.map +1 -1
- package/packages/host/dist/exposurepush.js +2 -2
- package/packages/host/dist/exposurepush.js.map +1 -1
- package/packages/host/dist/extensions/diskspace/host/candidates.d.mts +180 -0
- package/packages/host/dist/extensions/diskspace/host/candidates.mjs +716 -0
- package/packages/host/dist/extensions/diskspace/host/candidates.mjs.map +1 -0
- package/packages/host/dist/extensions/diskspace/host/engine.d.mts +21 -0
- package/packages/host/dist/extensions/diskspace/host/engine.mjs +498 -0
- package/packages/host/dist/extensions/diskspace/host/engine.mjs.map +1 -0
- package/packages/host/dist/extensions/diskspace/host/index.d.mts +25 -0
- package/packages/host/dist/extensions/diskspace/host/index.mjs +135 -0
- package/packages/host/dist/extensions/diskspace/host/index.mjs.map +1 -0
- package/packages/host/dist/extensions/diskspace/host/large.d.mts +11 -0
- package/packages/host/dist/extensions/diskspace/host/large.mjs +56 -0
- package/packages/host/dist/extensions/diskspace/host/large.mjs.map +1 -0
- package/packages/host/dist/extensions/diskspace/host/run.d.mts +94 -0
- package/packages/host/dist/extensions/diskspace/host/run.mjs +200 -0
- package/packages/host/dist/extensions/diskspace/host/run.mjs.map +1 -0
- package/packages/host/dist/extensions/diskspace/shared/wire.d.mts +197 -0
- package/packages/host/dist/extensions/diskspace/shared/wire.mjs +23 -0
- package/packages/host/dist/extensions/diskspace/shared/wire.mjs.map +1 -0
- package/packages/host/dist/extensions/links/host/engine.d.mts +39 -0
- package/packages/host/dist/extensions/links/host/engine.mjs +285 -0
- package/packages/host/dist/extensions/links/host/engine.mjs.map +1 -0
- package/packages/host/dist/extensions/links/host/index.d.mts +10 -0
- package/packages/host/dist/extensions/links/host/index.mjs +72 -0
- package/packages/host/dist/extensions/links/host/index.mjs.map +1 -0
- package/packages/host/dist/extensions/links/host/parse.d.mts +61 -0
- package/packages/host/dist/extensions/links/host/parse.mjs +225 -0
- package/packages/host/dist/extensions/links/host/parse.mjs.map +1 -0
- package/packages/host/dist/extensions/links/host/run.d.mts +15 -0
- package/packages/host/dist/extensions/links/host/run.mjs +32 -0
- package/packages/host/dist/extensions/links/host/run.mjs.map +1 -0
- package/packages/host/dist/extensions/links/host/store.d.mts +11 -0
- package/packages/host/dist/extensions/links/host/store.mjs +76 -0
- package/packages/host/dist/extensions/links/host/store.mjs.map +1 -0
- package/packages/host/dist/extensions/links/shared/wire.d.mts +141 -0
- package/packages/host/dist/extensions/links/shared/wire.mjs +20 -0
- package/packages/host/dist/extensions/links/shared/wire.mjs.map +1 -0
- package/packages/host/dist/git.d.ts +5 -3
- package/packages/host/dist/git.js +16 -28
- package/packages/host/dist/git.js.map +1 -1
- package/packages/host/dist/halt.js +16 -3
- package/packages/host/dist/halt.js.map +1 -1
- package/packages/host/dist/jsonstore.d.ts +16 -4
- package/packages/host/dist/jsonstore.js +32 -8
- package/packages/host/dist/jsonstore.js.map +1 -1
- package/packages/host/dist/landedbase.d.ts +41 -0
- package/packages/host/dist/landedbase.js +59 -0
- package/packages/host/dist/landedbase.js.map +1 -0
- package/packages/host/dist/lantls.js +2 -2
- package/packages/host/dist/lantls.js.map +1 -1
- package/packages/host/dist/limitretry.js +2 -3
- package/packages/host/dist/limitretry.js.map +1 -1
- package/packages/host/dist/localledger.js +9 -12
- package/packages/host/dist/localledger.js.map +1 -1
- package/packages/host/dist/main.js +2 -0
- package/packages/host/dist/main.js.map +1 -1
- package/packages/host/dist/opendeliveries.d.ts +4 -0
- package/packages/host/dist/opendeliveries.js +27 -1
- package/packages/host/dist/opendeliveries.js.map +1 -1
- package/packages/host/dist/plugins/setupcontrib.js +3 -2
- package/packages/host/dist/plugins/setupcontrib.js.map +1 -1
- package/packages/host/dist/pricefetch.d.ts +80 -0
- package/packages/host/dist/pricefetch.js +289 -0
- package/packages/host/dist/pricefetch.js.map +1 -0
- package/packages/host/dist/pricegap.d.ts +11 -0
- package/packages/host/dist/pricegap.js +30 -0
- package/packages/host/dist/pricegap.js.map +1 -0
- package/packages/host/dist/repohealthscopes.js +16 -24
- package/packages/host/dist/repohealthscopes.js.map +1 -1
- package/packages/host/dist/repos.d.ts +4 -0
- package/packages/host/dist/repos.js +1 -1
- package/packages/host/dist/repos.js.map +1 -1
- package/packages/host/dist/reposkilltext.d.ts +2 -0
- package/packages/host/dist/reposkilltext.js +8 -2
- package/packages/host/dist/reposkilltext.js.map +1 -1
- package/packages/host/dist/routes/apiagentpoints.d.ts +5 -0
- package/packages/host/dist/routes/apiagentpoints.js +48 -0
- package/packages/host/dist/routes/apiagentpoints.js.map +1 -0
- package/packages/host/dist/routes/apidictate.d.ts +2 -0
- package/packages/host/dist/routes/apidictate.js +27 -0
- package/packages/host/dist/routes/apidictate.js.map +1 -0
- package/packages/host/dist/routes/apihost.js +3 -2
- package/packages/host/dist/routes/apihost.js.map +1 -1
- package/packages/host/dist/routes/apirepofiles.js +3 -1
- package/packages/host/dist/routes/apirepofiles.js.map +1 -1
- package/packages/host/dist/routes/apirepowork.js +14 -0
- package/packages/host/dist/routes/apirepowork.js.map +1 -1
- package/packages/host/dist/routes/apiroutes.js +4 -1
- package/packages/host/dist/routes/apiroutes.js.map +1 -1
- package/packages/host/dist/routes/apiskills.d.ts +3 -0
- package/packages/host/dist/routes/apiskills.js +81 -0
- package/packages/host/dist/routes/apiskills.js.map +1 -0
- package/packages/host/dist/routes/apistats.js +2 -2
- package/packages/host/dist/routes/apistats.js.map +1 -1
- package/packages/host/dist/routes/apisystem.js +3 -1
- package/packages/host/dist/routes/apisystem.js.map +1 -1
- package/packages/host/dist/routes/apitable.d.ts +2 -0
- package/packages/host/dist/routes/apitable.js.map +1 -1
- package/packages/host/dist/server/billingwire.js +5 -0
- package/packages/host/dist/server/billingwire.js.map +1 -1
- package/packages/host/dist/server/deliveries.d.ts +4 -1
- package/packages/host/dist/server/deliveries.js +38 -6
- package/packages/host/dist/server/deliveries.js.map +1 -1
- package/packages/host/dist/server/http.js +1 -1
- package/packages/host/dist/server/http.js.map +1 -1
- package/packages/host/dist/server/intentDeps.js +20 -6
- package/packages/host/dist/server/intentDeps.js.map +1 -1
- package/packages/host/dist/server/wsops.js +2 -1
- package/packages/host/dist/server/wsops.js.map +1 -1
- package/packages/host/dist/sessions/core.d.ts +1 -0
- package/packages/host/dist/sessions/ctxseries.js +7 -5
- package/packages/host/dist/sessions/ctxseries.js.map +1 -1
- package/packages/host/dist/sessions/drive.d.ts +6 -1
- package/packages/host/dist/sessions/drive.js +13 -10
- package/packages/host/dist/sessions/drive.js.map +1 -1
- package/packages/host/dist/sessions/record.js +16 -17
- package/packages/host/dist/sessions/record.js.map +1 -1
- package/packages/host/dist/sessions/sidechannel.js +1 -1
- package/packages/host/dist/sessions/sidechannel.js.map +1 -1
- package/packages/host/dist/sessions/tmux.js +6 -1
- package/packages/host/dist/sessions/tmux.js.map +1 -1
- package/packages/host/dist/sessions/turn.js +5 -0
- package/packages/host/dist/sessions/turn.js.map +1 -1
- package/packages/host/dist/sessions.d.ts +2 -1
- package/packages/host/dist/sessions.js +1 -1
- package/packages/host/dist/sessions.js.map +1 -1
- package/packages/host/dist/settle.d.ts +3 -2
- package/packages/host/dist/settle.js +13 -13
- package/packages/host/dist/settle.js.map +1 -1
- package/packages/host/dist/sidecar/sidecarname.d.ts +2 -0
- package/packages/host/dist/sidecar/sidecarname.js +5 -1
- package/packages/host/dist/sidecar/sidecarname.js.map +1 -1
- package/packages/host/dist/sidecar/sidecarroute.d.ts +1 -1
- package/packages/host/dist/sidecar/sidecarroute.js +5 -0
- package/packages/host/dist/sidecar/sidecarroute.js.map +1 -1
- package/packages/host/dist/sidecar.d.ts +1 -1
- package/packages/host/dist/sidecar.js +1 -1
- package/packages/host/dist/sidecar.js.map +1 -1
- package/packages/host/dist/skills/skillinventory.d.ts +23 -0
- package/packages/host/dist/skills/skillinventory.js +275 -0
- package/packages/host/dist/skills/skillinventory.js.map +1 -0
- package/packages/host/dist/skills/skilllayers.d.ts +28 -0
- package/packages/host/dist/skills/skilllayers.js +73 -0
- package/packages/host/dist/skills/skilllayers.js.map +1 -0
- package/packages/host/dist/skills/skillrecommend.d.ts +42 -0
- package/packages/host/dist/skills/skillrecommend.js +171 -0
- package/packages/host/dist/skills/skillrecommend.js.map +1 -0
- package/packages/host/dist/skills/skillrefs.d.ts +2 -0
- package/packages/host/dist/skills/skillrefs.js +50 -0
- package/packages/host/dist/skills/skillrefs.js.map +1 -0
- package/packages/host/dist/skills/skilluse.d.ts +57 -0
- package/packages/host/dist/skills/skilluse.js +242 -0
- package/packages/host/dist/skills/skilluse.js.map +1 -0
- package/packages/host/dist/skills/skillweight.d.ts +18 -0
- package/packages/host/dist/skills/skillweight.js +69 -0
- package/packages/host/dist/skills/skillweight.js.map +1 -0
- package/packages/host/dist/skills/skillwrite.d.ts +56 -0
- package/packages/host/dist/skills/skillwrite.js +183 -0
- package/packages/host/dist/skills/skillwrite.js.map +1 -0
- package/packages/host/dist/sysstat.d.ts +34 -1
- package/packages/host/dist/sysstat.js +82 -14
- package/packages/host/dist/sysstat.js.map +1 -1
- package/packages/host/dist/tokenscan.js +5 -2
- package/packages/host/dist/tokenscan.js.map +1 -1
- package/packages/host/dist/tokenstats.js +7 -4
- package/packages/host/dist/tokenstats.js.map +1 -1
- package/packages/host/dist/transcript/transcriptparse.js +2 -2
- package/packages/host/dist/transcript/transcriptparse.js.map +1 -1
- package/packages/host/dist/waitclock.d.ts +12 -0
- package/packages/host/dist/waitclock.js +23 -0
- package/packages/host/dist/waitclock.js.map +1 -0
- package/packages/host/dist/weekburn.js +7 -5
- package/packages/host/dist/weekburn.js.map +1 -1
- package/packages/host/dist/worktreeleftover.js +13 -15
- package/packages/host/dist/worktreeleftover.js.map +1 -1
- package/packages/web/dist/assets/demo-DHkwSmU5.js +26 -0
- package/packages/web/dist/assets/{icons-D8RlmSLR.js → icons-5lVTFNUU.js} +1 -1
- package/packages/web/dist/assets/index-Bh4cH6X8.js +170 -0
- package/packages/web/dist/assets/index-F7VHtsLI.css +1 -0
- package/packages/web/dist/assets/shared-BvQMg9ra.js +51 -0
- package/packages/web/dist/assets/sheets-Cwi72V02.js +257 -0
- package/packages/web/dist/assets/sheets-DjU2XiUd.css +1 -0
- package/packages/web/dist/build-id.txt +1 -1
- package/packages/web/dist/buildstamp.json +1 -1
- package/packages/web/dist/index.html +7 -7
- package/packages/web/dist/sw.js +2 -2
- package/release.json +11 -3
- package/tools/repohealth/constants.mjs +34 -1
- package/tools/repohealth/fixture.json +5374 -38
- package/tools/repohealth/git.mjs +77 -0
- package/tools/repohealth/lang/dart-analyze.mjs +181 -0
- package/tools/repohealth/lang/dart-lex.mjs +494 -0
- package/tools/repohealth/lang/dart-resolve.mjs +95 -0
- package/tools/repohealth/lang/python-ast.mjs +602 -0
- package/tools/repohealth/lang/python-resolve.mjs +228 -0
- package/tools/repohealth/metrics/habits.mjs +286 -0
- package/tools/repohealth/metrics/native.mjs +542 -0
- package/tools/repohealth/metrics/untested.mjs +20 -8
- package/tools/repohealth/metrics/workspace.mjs +256 -0
- package/tools/repohealth/own.mjs +67 -5
- package/tools/repohealth/packs/dart.mjs +153 -85
- package/tools/repohealth/packs/python.mjs +51 -14
- package/tools/repohealth/plot.mjs +143 -1
- package/tools/repohealth/reach.mjs +98 -0
- package/tools/repohealth/scope.mjs +14 -1
- package/tools/repohealth/series.mjs +5 -0
- package/tools/repohealth/types.mjs +4 -0
- package/tools/repohealth.mjs +39 -5
- package/packages/web/dist/assets/demo-ad3g3HDa.js +0 -26
- package/packages/web/dist/assets/index-Csb7jynu.js +0 -170
- package/packages/web/dist/assets/index-Cz9Haocy.css +0 -1
- package/packages/web/dist/assets/shared-DBaaGttP.js +0 -51
- package/packages/web/dist/assets/sheets-CqsP9w1V.js +0 -256
- package/packages/web/dist/assets/sheets-DoUhPGK0.css +0 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a Python import points inside the tree, resolved against the set of
|
|
3
|
+
* `.py` paths the tree holds. The Python half of `metrics/graph.mjs`'s
|
|
4
|
+
* contract, beside `typescript-resolve.mjs`.
|
|
5
|
+
*
|
|
6
|
+
* ── What counts as a module, and the key an edge carries ────────────────────
|
|
7
|
+
*
|
|
8
|
+
* `a/b.py` is module `a.b` and its graph key is `a/b`. `a/b/__init__.py` is
|
|
9
|
+
* package `a.b` and its key is `a/b/__init__`. (`graphKeysFor` in the pack
|
|
10
|
+
* offers exactly these two shapes, so a package and a module of one name never
|
|
11
|
+
* share a key.) A directory with `.py` files below it and no `__init__.py` is a
|
|
12
|
+
* namespace package: it exists, it has no file, it is no edge.
|
|
13
|
+
*
|
|
14
|
+
* ── Which directory an absolute import is read from ─────────────────────────
|
|
15
|
+
*
|
|
16
|
+
* Python reads `import a.b` against `sys.path`, and a repo does not say what
|
|
17
|
+
* its `sys.path` is. The roots tried, nearest first, are the directories above
|
|
18
|
+
* the importing file that are NOT themselves packages (a package directory is
|
|
19
|
+
* never a `sys.path` entry), and each one's `src/`. That finds the repo root,
|
|
20
|
+
* a `src` layout, and a script's own directory. Only when none of them holds
|
|
21
|
+
* the first segment is the name looked for tree-wide, and only if it lives in
|
|
22
|
+
* exactly ONE place and is not a standard-library name. Two places is an
|
|
23
|
+
* ambiguity reported as a MISS, never a pick — a guessed edge can invent a cycle.
|
|
24
|
+
*
|
|
25
|
+
* ── What is external ────────────────────────────────────────────────────────
|
|
26
|
+
*
|
|
27
|
+
* A first segment no root holds is a package from outside (`numpy`, `fastapi`,
|
|
28
|
+
* the standard library): no entry at all, no miss. A first segment that IS this
|
|
29
|
+
* tree's but whose rest is not (`import app.nothing`) is a miss. Every relative
|
|
30
|
+
* import is this tree's own, so one that finds nothing is a miss.
|
|
31
|
+
*
|
|
32
|
+
* ── Edges the graph does not draw ───────────────────────────────────────────
|
|
33
|
+
*
|
|
34
|
+
* - Imports under `if TYPE_CHECKING:` never run: no edge.
|
|
35
|
+
* - Imports inside a function body run when it is CALLED, not when the module
|
|
36
|
+
* loads. Python code puts them there on purpose to break a cycle (in
|
|
37
|
+
* `trading` they are the whole of a 16-module cycle: 1,438 edges and one
|
|
38
|
+
* cycle with them, 1,169 and none without). The graph is the load-time
|
|
39
|
+
* coupling, so they draw no edge and count as neither hit nor miss.
|
|
40
|
+
* - The parent packages `import a.b.c` also executes (`a/__init__`,
|
|
41
|
+
* `a/b/__init__`) are not edges: every package would then sit in a cycle
|
|
42
|
+
* with every module that imports a sibling. The target itself is the edge.
|
|
43
|
+
* - `from pkg import name` is an edge to `pkg/name.py` when that submodule
|
|
44
|
+
* exists and to `pkg` otherwise (`name` is then an attribute).
|
|
45
|
+
* - A target that is a test file is dropped: it is not a node of the graph.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
const STDLIB = new Set(
|
|
49
|
+
(
|
|
50
|
+
"abc argparse array ast asyncio atexit base64 bdb binascii bisect builtins bz2 cProfile calendar cmath cmd code codecs " +
|
|
51
|
+
"codeop collections colorsys compileall concurrent configparser contextlib contextvars copy copyreg csv ctypes curses " +
|
|
52
|
+
"dataclasses datetime dbm decimal difflib dis doctest email encodings ensurepip enum errno faulthandler fcntl filecmp " +
|
|
53
|
+
"fileinput fnmatch fractions ftplib functools gc genericpath getopt getpass gettext glob graphlib grp gzip hashlib " +
|
|
54
|
+
"heapq hmac html http imaplib importlib inspect io ipaddress itertools json keyword linecache locale logging lzma " +
|
|
55
|
+
"mailbox marshal math mimetypes mmap modulefinder msvcrt multiprocessing netrc nt ntpath numbers opcode operator " +
|
|
56
|
+
"optparse os pathlib pdb pickle pickletools pkgutil platform plistlib poplib posix posixpath pprint profile pstats pty " +
|
|
57
|
+
"pwd py_compile pyclbr pydoc pyexpat queue quopri random re readline reprlib resource rlcompleter runpy sched secrets " +
|
|
58
|
+
"select selectors shelve shlex shutil signal site smtplib socket socketserver sqlite3 sre_compile sre_constants " +
|
|
59
|
+
"sre_parse ssl stat statistics string stringprep struct subprocess symtable sys sysconfig syslog tabnanny tarfile " +
|
|
60
|
+
"tempfile termios textwrap this threading time timeit tkinter token tokenize tomllib trace traceback tracemalloc tty " +
|
|
61
|
+
"turtle types typing unicodedata unittest urllib uuid venv warnings wave weakref webbrowser winreg winsound wsgiref " +
|
|
62
|
+
"xml xmlrpc zipapp zipfile zipimport zlib zoneinfo"
|
|
63
|
+
).split(" "),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
/** Same three conventions as `packs/python.mjs` `testGlobs`, for one path. */
|
|
67
|
+
export function isPythonTest(path) {
|
|
68
|
+
const segs = path.split("/");
|
|
69
|
+
const file = segs[segs.length - 1];
|
|
70
|
+
return file.startsWith("test_") || file.endsWith("_test.py") || segs.slice(0, -1).includes("tests");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The resolver's data for one tree: every `.py` path (the entries are paths
|
|
75
|
+
* only; no text is read), the directories holding any, and the packages.
|
|
76
|
+
* @param {{path: string}[]} entries
|
|
77
|
+
*/
|
|
78
|
+
export function buildPythonContext(entries) {
|
|
79
|
+
const all = new Set();
|
|
80
|
+
const dirs = new Set([""]);
|
|
81
|
+
const inits = new Set();
|
|
82
|
+
/** first segment -> parents ("" for the root) holding a module or directory of that name */
|
|
83
|
+
const heads = new Map();
|
|
84
|
+
const top = [];
|
|
85
|
+
for (const e of entries) {
|
|
86
|
+
if (!e.path.endsWith(".py")) continue;
|
|
87
|
+
all.add(e.path);
|
|
88
|
+
const segs = e.path.split("/");
|
|
89
|
+
const file = segs.pop();
|
|
90
|
+
for (let i = 1; i <= segs.length; i++) dirs.add(segs.slice(0, i).join("/"));
|
|
91
|
+
if (file === "__init__.py") inits.add(segs.join("/"));
|
|
92
|
+
if (file !== "__init__.py") top.push([file.slice(0, -3), segs.join("/")]);
|
|
93
|
+
}
|
|
94
|
+
// A head is a module or package that sits in a directory which is not itself
|
|
95
|
+
// a package: the only places a `sys.path` entry can be.
|
|
96
|
+
const parentOf = (d) => d.slice(0, Math.max(0, d.lastIndexOf("/")));
|
|
97
|
+
for (const [name, dir] of top) if (!inits.has(dir) || dir === "") note(heads, name, dir);
|
|
98
|
+
for (const d of inits) {
|
|
99
|
+
if (!d) continue;
|
|
100
|
+
const parent = d.includes("/") ? parentOf(d) : "";
|
|
101
|
+
if (!inits.has(parent) || parent === "") note(heads, d.slice(d.lastIndexOf("/") + 1), parent);
|
|
102
|
+
}
|
|
103
|
+
return { all, dirs, inits, heads };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function note(map, head, parent) {
|
|
107
|
+
let s = map.get(head);
|
|
108
|
+
if (!s) map.set(head, (s = new Set()));
|
|
109
|
+
s.add(parent);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const join = (root, segs) => (root ? [root, ...segs] : segs).join("/");
|
|
113
|
+
|
|
114
|
+
/** What `root/segs` is: `{key}` for a module or package file, `{ns: true}` for a namespace directory, or null. */
|
|
115
|
+
function modAt(ctx, root, segs) {
|
|
116
|
+
if (!segs.length) return ctx.inits.has(root) ? { key: join(root, ["__init__"]) } : ctx.dirs.has(root) ? { ns: true } : null;
|
|
117
|
+
const p = join(root, segs);
|
|
118
|
+
if (ctx.all.has(p + ".py")) return { key: p };
|
|
119
|
+
if (ctx.all.has(p + "/__init__.py")) return { key: p + "/__init__" };
|
|
120
|
+
if (ctx.dirs.has(p)) return { ns: true };
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** The sys.path-like roots for a file in `dirSegs`, nearest first. */
|
|
125
|
+
function rootsFor(ctx, dirSegs) {
|
|
126
|
+
const roots = [];
|
|
127
|
+
for (let n = dirSegs.length; n >= 0; n--) {
|
|
128
|
+
const dir = dirSegs.slice(0, n).join("/");
|
|
129
|
+
if (ctx.inits.has(dir) && n > 0) continue;
|
|
130
|
+
roots.push(dir);
|
|
131
|
+
const src = join(dir, ["src"]);
|
|
132
|
+
if (ctx.dirs.has(src)) roots.push(src);
|
|
133
|
+
}
|
|
134
|
+
return roots;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Every module one file's import records load, as graph entries:
|
|
139
|
+
* `{spec, internal, candidates}`. Candidates are whole tree keys.
|
|
140
|
+
* @param {object[]} records `importsOf` output
|
|
141
|
+
* @param {string} fromPath
|
|
142
|
+
* @param {ReturnType<typeof buildPythonContext> | null} ctx
|
|
143
|
+
*/
|
|
144
|
+
export function resolvePythonImports(records, fromPath, ctx) {
|
|
145
|
+
if (!ctx) return [];
|
|
146
|
+
const out = [];
|
|
147
|
+
const seen = new Set();
|
|
148
|
+
const dirSegs = fromPath.split("/").slice(0, -1);
|
|
149
|
+
const emit = (spec, key) => {
|
|
150
|
+
// A test file is no node of the graph; neither hit nor miss.
|
|
151
|
+
if (key && isPythonTest(key.endsWith("/__init__") ? key.slice(0, -9) + "/__init__.py" : key + ".py")) return;
|
|
152
|
+
const id = `${spec}\u0000${key ?? ""}`;
|
|
153
|
+
if (seen.has(id)) return;
|
|
154
|
+
seen.add(id);
|
|
155
|
+
out.push({ spec, internal: true, candidates: key ? [key] : [] });
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** Resolve `base` (a root) + module segments + imported names for a `from` record; false if nothing is there. */
|
|
159
|
+
const fromAt = (spec, root, segs, names) => {
|
|
160
|
+
const base = modAt(ctx, root, segs);
|
|
161
|
+
if (!base) return false;
|
|
162
|
+
if (names.includes("*") || !names.length) names = [];
|
|
163
|
+
if (base.key && !base.key.endsWith("/__init__")) {
|
|
164
|
+
emit(spec, base.key); // module: names are attributes
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
if (!names.length) {
|
|
168
|
+
if (base.key) emit(spec, base.key);
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
for (const nm of names) {
|
|
172
|
+
const sub = modAt(ctx, root, [...segs, nm]);
|
|
173
|
+
if (sub && sub.key) emit(spec, sub.key);
|
|
174
|
+
else if (base.key) emit(spec, base.key);
|
|
175
|
+
else emit(spec, null);
|
|
176
|
+
}
|
|
177
|
+
return true;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
for (const r of records) {
|
|
181
|
+
if (r.tc || r.deferred) continue;
|
|
182
|
+
if (r.from && r.dots > 0) {
|
|
183
|
+
const spec = ".".repeat(r.dots) + r.module.join(".");
|
|
184
|
+
if (r.dots - 1 > dirSegs.length) {
|
|
185
|
+
emit(spec, null);
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const root = dirSegs.slice(0, dirSegs.length - (r.dots - 1)).join("/");
|
|
189
|
+
if (!fromAt(spec, root, r.module, r.names)) emit(spec, null);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const mods = r.from ? [r.module] : r.modules;
|
|
193
|
+
for (const segs of mods) {
|
|
194
|
+
const spec = segs.join(".");
|
|
195
|
+
const head = segs[0];
|
|
196
|
+
let root = null;
|
|
197
|
+
for (const cand of rootsFor(ctx, dirSegs)) {
|
|
198
|
+
if (modAt(ctx, cand, [head])) {
|
|
199
|
+
root = cand;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (root === null) {
|
|
204
|
+
if (STDLIB.has(head)) continue;
|
|
205
|
+
const places = ctx.heads.get(head);
|
|
206
|
+
if (!places) continue; // external
|
|
207
|
+
if (places.size > 1) {
|
|
208
|
+
emit(spec, null);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
root = [...places][0];
|
|
212
|
+
// The head must be a module/package AT that parent, not a deep directory of that name.
|
|
213
|
+
if (!modAt(ctx, root, [head])) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (r.from) {
|
|
218
|
+
if (!fromAt(spec, root, segs, r.names)) emit(spec, null);
|
|
219
|
+
} else {
|
|
220
|
+
const t = modAt(ctx, root, segs);
|
|
221
|
+
if (t && t.key) emit(spec, t.key);
|
|
222
|
+
else if (t && t.ns) continue; // a namespace directory: nothing to load
|
|
223
|
+
else emit(spec, null);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Habits: what the commit log alone says about how work lands. Git only, no
|
|
3
|
+
* language knowledge beyond the one thing the packs already decide — which
|
|
4
|
+
* paths are source and which are tests.
|
|
5
|
+
*
|
|
6
|
+
* ── The six readings, and the question each one answers ────────────────────
|
|
7
|
+
*
|
|
8
|
+
* fix Of the commits that touched source or tests, what share were a
|
|
9
|
+
* FIX or REVERT of files a different commit had changed in the
|
|
10
|
+
* seven days before. "Is the last thing I shipped holding?"
|
|
11
|
+
* Re-touch asks it per file; this asks it per commit and by what
|
|
12
|
+
* the author SAID, so the two disagree usefully.
|
|
13
|
+
* deletion Lines deleted per line added over the window, with the four
|
|
14
|
+
* weeks it is made of. The owner's grooming signal: an agent
|
|
15
|
+
* rarely deletes unless asked, so a ratio that stays near zero
|
|
16
|
+
* is a repo that only grows.
|
|
17
|
+
* netNegative The share of commits that delete more than they add.
|
|
18
|
+
* testsWithCode Of the commits that touched source, the share that also
|
|
19
|
+
* touched a test file.
|
|
20
|
+
* commitSize p95 (nearest rank) of changed lines (added + deleted) per
|
|
21
|
+
* commit, with the median beside it.
|
|
22
|
+
* hotspots The files where churn and size multiply — a LIST, like
|
|
23
|
+
* `untested`, because "src/a.ts, 4 changes, 2,100 lines" is
|
|
24
|
+
* something a person opens and "0.43" is not.
|
|
25
|
+
*
|
|
26
|
+
* ── The fix pattern ────────────────────────────────────────────────────────
|
|
27
|
+
*
|
|
28
|
+
* A commit is a fix when its SUBJECT, case-insensitively, starts with
|
|
29
|
+
* `revert`, `fix`, `fixes`, `fixed`, `bugfix` or `hotfix` (as a word), or is a
|
|
30
|
+
* Conventional-Commits subject whose type is `fix`/`revert`/`hotfix`
|
|
31
|
+
* (`fix(web): …`, `fix!: …`). It is pinned in `FIX_SUBJECT` below, is a
|
|
32
|
+
* message heuristic and nothing more: a repo that never writes "fix" reads 0
|
|
33
|
+
* fixes, which is why `fixes` travels beside the rate and a window with no
|
|
34
|
+
* fix-worded commit still reports the rate (0 of N) rather than an absence —
|
|
35
|
+
* "nothing was labelled a fix" is a true statement about the window.
|
|
36
|
+
*
|
|
37
|
+
* ── Which commits are the subject, and which are only evidence ─────────────
|
|
38
|
+
*
|
|
39
|
+
* The same rule `retouch` argues out. A BATCH commit (`history.batch`, the
|
|
40
|
+
* flag as recorded, never recomputed) is a day swept up by one `git add`, and
|
|
41
|
+
* a MERGE (subject `Merge …`; first-parent history gives it the whole branch
|
|
42
|
+
* as one diff) is a branch landing at once. Neither is a commit someone sized
|
|
43
|
+
* or worded, so neither is counted in a per-commit share (fix, test, net
|
|
44
|
+
* negative, size). Both still count as PRIOR touches for fix-after-change, and
|
|
45
|
+
* both still count in the line TOTALS of the deletion ratio: those lines
|
|
46
|
+
* really were added and deleted, and dropping them would make a repo that
|
|
47
|
+
* grooms in one big commit look like one that never does.
|
|
48
|
+
*
|
|
49
|
+
* ── Line counts: renames are not deletions ─────────────────────────────────
|
|
50
|
+
*
|
|
51
|
+
* Added and deleted lines come from `git.readChurn`, which runs numstat with
|
|
52
|
+
* `-M`. A pure move is `0 0`; a move with edits counts only the edit. The
|
|
53
|
+
* history `lines` map (rename detection OFF, pinned for path fidelity) would
|
|
54
|
+
* read a reorganisation as 100% deleted and 100% added. Paths inside the
|
|
55
|
+
* packs' excluded directories (build output, vendored code) are dropped from
|
|
56
|
+
* every count here: nobody grooms `node_modules`.
|
|
57
|
+
*
|
|
58
|
+
* ── Shallow clones and young repos ─────────────────────────────────────────
|
|
59
|
+
*
|
|
60
|
+
* In a shallow clone the boundary commit "adds" the whole tree, so any window
|
|
61
|
+
* that reaches it would read a repo-sized addition as a day's work. The whole
|
|
62
|
+
* family is absent when the history is shallow and the window (plus the
|
|
63
|
+
* fix look-back) reaches the first commit it has. A repo that is genuinely
|
|
64
|
+
* young reads normally: its root commit really did add everything.
|
|
65
|
+
*
|
|
66
|
+
* ── Cost ────────────────────────────────────────────────────────────────────
|
|
67
|
+
*
|
|
68
|
+
* Per row: one scan of the commits in the trailing window plus the look-back,
|
|
69
|
+
* found by walking back from `index` (not from 0, unlike `retouch`'s scan),
|
|
70
|
+
* with a `Map` of last-touch times. No git, no blobs; `history.churn` is read
|
|
71
|
+
* once per `update`.
|
|
72
|
+
*
|
|
73
|
+
* ── Purity ─────────────────────────────────────────────────────────────────
|
|
74
|
+
*
|
|
75
|
+
* The `History` and `Snapshot` handed in are the whole world, nothing past
|
|
76
|
+
* `index` is read, and every sub-reading is `{value, reason}`: a reading that
|
|
77
|
+
* cannot be taken is absent with the sentence that says why, never 0.
|
|
78
|
+
*/
|
|
79
|
+
import { isSource, isTestPath, inExcludedDir } from "../source.mjs";
|
|
80
|
+
import { nearestRankP95 } from "./size.mjs";
|
|
81
|
+
|
|
82
|
+
const DAY = 86400;
|
|
83
|
+
const WEEKS = 4;
|
|
84
|
+
|
|
85
|
+
/** See the header: the pinned meaning of "this commit is a fix". */
|
|
86
|
+
export const FIX_SUBJECT =
|
|
87
|
+
/^\s*(?:(?:revert|fix|fixes|fixed|bugfix|hotfix)\b|[a-z]+(?:\([^)]*\))?!?:\s*(?:revert|fix|hotfix)\b)/i;
|
|
88
|
+
|
|
89
|
+
/** A merge commit, by git's own default subject. */
|
|
90
|
+
const MERGE_SUBJECT = /^Merge\b/;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Per-path class, kept for the life of the process per `SRC` object: a path's
|
|
94
|
+
* class never changes within one configuration, and the scan below asks it of
|
|
95
|
+
* every path of every commit in the window for every row (measured: this was
|
|
96
|
+
* most of the per-row cost).
|
|
97
|
+
* @type {WeakMap<object, Map<string, 0|1|2>>} 0 other, 1 source, 2 test
|
|
98
|
+
*/
|
|
99
|
+
const CLASS = new WeakMap();
|
|
100
|
+
function classOf(path, prereg) {
|
|
101
|
+
let m = CLASS.get(prereg.SRC);
|
|
102
|
+
if (!m) CLASS.set(prereg.SRC, (m = new Map()));
|
|
103
|
+
let c = m.get(path);
|
|
104
|
+
if (c === undefined) {
|
|
105
|
+
c = isSource(path, prereg) ? 1 : isTestPath(path, prereg) && !inExcludedDir(path, prereg.SRC.excludeDirs) ? 2 : 0;
|
|
106
|
+
m.set(path, c);
|
|
107
|
+
}
|
|
108
|
+
return c;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const none = (reason) => ({ value: null, reason });
|
|
112
|
+
|
|
113
|
+
/** Nearest-rank median over an ascending list, same convention as the p95. */
|
|
114
|
+
function nearestRankMedian(ascending) {
|
|
115
|
+
return ascending[Math.max(0, Math.ceil(0.5 * ascending.length) - 1)];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Count desc, then path asc — a total order so the fixture can be compared. */
|
|
119
|
+
function byScoreThenPath(a, b) {
|
|
120
|
+
if (b.score !== a.score) return b.score - a.score;
|
|
121
|
+
return a.path < b.path ? -1 : a.path > b.path ? 1 : 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @param {import("../types.mjs").Snapshot} snapshot
|
|
126
|
+
* @param {import("../types.mjs").History & {churn?: Map<string, Map<string, {add: number, del: number}>>, shallow?: boolean}} history
|
|
127
|
+
* @param {number} index
|
|
128
|
+
* @param {import("../types.mjs").EffectivePrereg} prereg
|
|
129
|
+
* @returns {import("../types.mjs").Measured<object>}
|
|
130
|
+
*/
|
|
131
|
+
export function measureHabits(snapshot, history, index, prereg) {
|
|
132
|
+
const commits = history?.commits ?? [];
|
|
133
|
+
const here = commits[index];
|
|
134
|
+
if (!here) return none("no commit at index " + index);
|
|
135
|
+
if (!history.churn) return none("no rename-aware line counts were read");
|
|
136
|
+
|
|
137
|
+
const windowSecs = prereg.HABITS_WINDOW_DAYS * DAY;
|
|
138
|
+
const fixSecs = prereg.FIX_AFTER_DAYS * DAY;
|
|
139
|
+
const windowStart = here.ts - windowSecs;
|
|
140
|
+
|
|
141
|
+
if (history.shallow && commits[0] && commits[0].ts >= windowStart - fixSecs) {
|
|
142
|
+
return none(
|
|
143
|
+
"shallow clone: the history it holds starts at " + commits[0].day +
|
|
144
|
+
", inside the " + prereg.HABITS_WINDOW_DAYS + "-day window, and that first commit adds the whole tree",
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// First in-window commit, and the first commit of the fix look-back.
|
|
149
|
+
let lo = index;
|
|
150
|
+
while (lo > 0 && commits[lo - 1].ts >= windowStart) lo--;
|
|
151
|
+
let pre = lo;
|
|
152
|
+
while (pre > 0 && commits[pre - 1].ts >= windowStart - fixSecs) pre--;
|
|
153
|
+
|
|
154
|
+
const src = prereg.SRC;
|
|
155
|
+
const dirs = src.excludeDirs;
|
|
156
|
+
const pathsOf = (c) => history.touches?.get(c.sha) ?? c.filesTouched ?? [];
|
|
157
|
+
const isBatch = (c) => history.batch?.has(c.sha) ?? c.batch ?? false;
|
|
158
|
+
const isMerge = (c) => MERGE_SUBJECT.test(c.subject ?? "");
|
|
159
|
+
const hasSrc = src.exts.length > 0;
|
|
160
|
+
const hasTests = src.testGlobs.length > 0;
|
|
161
|
+
|
|
162
|
+
// ── fix-after-change, tests-with-code: path-level, per subject commit ────
|
|
163
|
+
const lastTouch = new Map();
|
|
164
|
+
let subjects = 0; // subject commits touching source or tests
|
|
165
|
+
let fixes = 0;
|
|
166
|
+
let fixesAfter = 0;
|
|
167
|
+
let srcCommits = 0;
|
|
168
|
+
let withTests = 0;
|
|
169
|
+
for (let i = pre; i <= index; i++) {
|
|
170
|
+
const c = commits[i];
|
|
171
|
+
const all = pathsOf(c);
|
|
172
|
+
const files = hasSrc ? all.filter((p) => classOf(p, prereg) !== 0) : [];
|
|
173
|
+
if (i >= lo && !isBatch(c) && !isMerge(c)) {
|
|
174
|
+
if (files.length) {
|
|
175
|
+
subjects++;
|
|
176
|
+
if (FIX_SUBJECT.test(c.subject ?? "")) {
|
|
177
|
+
fixes++;
|
|
178
|
+
if (files.some((p) => {
|
|
179
|
+
const t = lastTouch.get(p);
|
|
180
|
+
return t !== undefined && Math.abs(c.ts - t) <= fixSecs;
|
|
181
|
+
})) fixesAfter++;
|
|
182
|
+
}
|
|
183
|
+
if (all.some((p) => classOf(p, prereg) === 1)) {
|
|
184
|
+
srcCommits++;
|
|
185
|
+
if (all.some((p) => classOf(p, prereg) === 2)) withTests++;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Prior-touch bookkeeping runs for every commit, batch and merge included.
|
|
190
|
+
for (const p of files) lastTouch.set(p, c.ts);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ── line-level: totals over everything, per-commit stats over subjects ───
|
|
194
|
+
let added = 0;
|
|
195
|
+
let deleted = 0;
|
|
196
|
+
const weeks = Array.from({ length: WEEKS }, () => ({ added: 0, deleted: 0 }));
|
|
197
|
+
const sizes = [];
|
|
198
|
+
let negative = 0;
|
|
199
|
+
/** path -> churn (added + deleted) over subject commits. */
|
|
200
|
+
const churnOf = new Map();
|
|
201
|
+
for (let i = lo; i <= index; i++) {
|
|
202
|
+
const c = commits[i];
|
|
203
|
+
const files = history.churn.get(c.sha);
|
|
204
|
+
if (!files) continue;
|
|
205
|
+
let a = 0;
|
|
206
|
+
let d = 0;
|
|
207
|
+
for (const [p, v] of files) {
|
|
208
|
+
if (inExcludedDir(p, dirs)) continue;
|
|
209
|
+
a += v.add;
|
|
210
|
+
d += v.del;
|
|
211
|
+
}
|
|
212
|
+
const wk = Math.min(WEEKS - 1, Math.max(0, Math.floor((here.ts - c.ts) / (7 * DAY))));
|
|
213
|
+
weeks[WEEKS - 1 - wk].added += a;
|
|
214
|
+
weeks[WEEKS - 1 - wk].deleted += d;
|
|
215
|
+
added += a;
|
|
216
|
+
deleted += d;
|
|
217
|
+
if (isBatch(c) || isMerge(c) || a + d === 0) continue;
|
|
218
|
+
sizes.push(a + d);
|
|
219
|
+
if (d > a) negative++;
|
|
220
|
+
for (const [p, v] of files) {
|
|
221
|
+
if (inExcludedDir(p, dirs)) continue;
|
|
222
|
+
churnOf.set(p, (churnOf.get(p) ?? 0) + v.add + v.del);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
sizes.sort((x, y) => x - y);
|
|
226
|
+
|
|
227
|
+
const noSource = "no active language pack recognises source files in this tree";
|
|
228
|
+
|
|
229
|
+
const fix = !hasSrc
|
|
230
|
+
? none(noSource)
|
|
231
|
+
: subjects === 0
|
|
232
|
+
? none("no non-batch commit touched source or test files in the trailing " + prereg.HABITS_WINDOW_DAYS + "d")
|
|
233
|
+
: { value: { rate: fixesAfter / subjects, commits: subjects, fixes, fixesAfter } };
|
|
234
|
+
|
|
235
|
+
const deletion = added === 0
|
|
236
|
+
? none("no lines were added in the trailing " + prereg.HABITS_WINDOW_DAYS + "d, so there is nothing to compare deletions with")
|
|
237
|
+
: { value: { ratio: deleted / added, added, deleted, weeks } };
|
|
238
|
+
|
|
239
|
+
const netNegative = sizes.length === 0
|
|
240
|
+
? none("no non-batch, non-merge commit changed a line in the trailing " + prereg.HABITS_WINDOW_DAYS + "d")
|
|
241
|
+
: { value: { share: negative / sizes.length, commits: sizes.length, negative } };
|
|
242
|
+
|
|
243
|
+
const commitSize = sizes.length === 0
|
|
244
|
+
? none("no non-batch, non-merge commit changed a line in the trailing " + prereg.HABITS_WINDOW_DAYS + "d")
|
|
245
|
+
: { value: { p95: nearestRankP95(sizes), median: nearestRankMedian(sizes), commits: sizes.length } };
|
|
246
|
+
|
|
247
|
+
const testsWithCode = !hasSrc
|
|
248
|
+
? none(noSource)
|
|
249
|
+
: !hasTests
|
|
250
|
+
? none("no active language pack recognises test files in this tree")
|
|
251
|
+
: srcCommits === 0
|
|
252
|
+
? none("no non-batch commit touched source files in the trailing " + prereg.HABITS_WINDOW_DAYS + "d")
|
|
253
|
+
: { value: { rate: withTests / srcCommits, commits: srcCommits, withTests } };
|
|
254
|
+
|
|
255
|
+
// ── hotspots: churn x size, source files that still exist at this sha ────
|
|
256
|
+
let hotspots;
|
|
257
|
+
const files = snapshot?.files ?? [];
|
|
258
|
+
if (!files.length) {
|
|
259
|
+
hotspots = none(noSource);
|
|
260
|
+
} else {
|
|
261
|
+
const locOf = new Map(files.map((f) => [f.path, f.loc]));
|
|
262
|
+
const ranked = [];
|
|
263
|
+
for (const [path, churn] of churnOf) {
|
|
264
|
+
const loc = locOf.get(path);
|
|
265
|
+
if (loc === undefined) continue;
|
|
266
|
+
ranked.push({ path, churn, loc, score: churn * loc });
|
|
267
|
+
}
|
|
268
|
+
ranked.sort(byScoreThenPath);
|
|
269
|
+
hotspots = ranked.length === 0
|
|
270
|
+
? none("no source file that exists now changed in the trailing " + prereg.HABITS_WINDOW_DAYS + "d")
|
|
271
|
+
: { value: { items: ranked.slice(0, prereg.HABITS_LIST_N) } };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Key order is fixed and load-bearing: the row is compared to a fixture.
|
|
275
|
+
return {
|
|
276
|
+
value: {
|
|
277
|
+
windowDays: prereg.HABITS_WINDOW_DAYS,
|
|
278
|
+
fix,
|
|
279
|
+
deletion,
|
|
280
|
+
netNegative,
|
|
281
|
+
testsWithCode,
|
|
282
|
+
commitSize,
|
|
283
|
+
hotspots,
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|