theprogrammablemind_4wp 8.9.1 → 9.0.0

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/client.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const { Semantics, Semantic } = require('./src/semantics')
2
2
  const { Generators, Generator } = require('./src/generators')
3
3
  const { Config } = require('./src/config')
4
- const { loadInstance, ErrorReason, listable, setupArgs, gs, processContext, getObjects, setupProcessB, processContextsB } = require('./src/configHelpers')
4
+ const { loadInstance, ErrorReason, listable, setupArgs, gs, processContext, getObjects, setupProcessB, processContextsB } = require('./src/configHelpers')
5
5
  const DigraphInternal = require('./src/digraph_internal')
6
6
  const Digraph = require('./src/digraph')
7
7
  const { project } = require('./src/project')
@@ -12,7 +12,7 @@ const _ = require('lodash')
12
12
  const stringify = require('json-stable-stringify')
13
13
  const Lines = require('./lines')
14
14
  const flattens = require('./src/flatten')
15
- const { appendNoDups, InitCalls, updateQueries, safeNoDups, stableId, where } = require('./src/helpers')
15
+ const { appendNoDups, InitCalls, updateQueries, safeNoDups, stableId, where, suggestAssociationsFix, suggestAssociationsFixFromSummaries } = require('./src/helpers')
16
16
  const runtime = require('./runtime')
17
17
  const sortJson = runtime.sortJson
18
18
 
@@ -23,7 +23,7 @@ const getConfig_getObjectsCheck = (config, testConfig) => {
23
23
  }
24
24
  const checks = (testConfig.checks && testConfig.checks.objects) || []
25
25
  if (Array.isArray(checks)) {
26
- const kmToChecks = { [testConfigName]: checks.filter( (check) => !check.km ) }
26
+ const kmToChecks = { [testConfigName]: checks.filter((check) => !check.km) }
27
27
  for (const check of checks) {
28
28
  if (check.km) {
29
29
  kmToChecks[check.km] = config.km(check.km).testConfig.checks.objects
@@ -35,6 +35,16 @@ const getConfig_getObjectsCheck = (config, testConfig) => {
35
35
  }
36
36
  }
37
37
 
38
+ const getSuggestion = (diff) => {
39
+ return diff.map((element) => {
40
+ return element.marker
41
+ })
42
+ }
43
+
44
+ const getSuggestionMessage = (suggestion) => {
45
+ return `Try adding this to the associations: { context: ${JSON.stringify(getSuggestion(suggestion))}, choose: <indexOfMainElement> },\n If that does not work look at the logs and check when the operators become wrong during an interation. Deduce the change based on the previous iteration and what operator was applied.`
46
+ }
47
+
38
48
  const getConfig_getContextCheck = (testConfig) => {
39
49
  return (testConfig.checks && testConfig.checks.context) || []
40
50
  }
@@ -53,7 +63,7 @@ const pickObjects = (config, testConfig, getObjects) => {
53
63
  */
54
64
  const checks = getConfig_getObjectsCheck(config, testConfig)
55
65
  const projection = {}
56
- for (let km in checks) {
66
+ for (const km in checks) {
57
67
  const objects = getObjects(km)
58
68
  if (!objects) {
59
69
  throw new Error(`In the checks for ${config.name} the KM ${km} does not exist`)
@@ -72,9 +82,9 @@ const sameJSON = (json1, json2) => {
72
82
  const vimdiff = (actualJSON, expectedJSON, title) => {
73
83
  const path = '.'
74
84
  const actual = sortJson(actualJSON, { depth: 25 })
75
- runtime.fs.writeFileSync(`${path}/actual.json`, JSON.stringify({ title, actual}, 0, 2))
85
+ runtime.fs.writeFileSync(`${path}/actual.json`, JSON.stringify({ title, actual }, 0, 2))
76
86
  const expected = sortJson(expectedJSON, { depth: 25 })
77
- runtime.fs.writeFileSync(`${path}/expected.json`, JSON.stringify({ title, expected}, 0, 2))
87
+ runtime.fs.writeFileSync(`${path}/expected.json`, JSON.stringify({ title, expected }, 0, 2))
78
88
  // console.log(`vimdiff ${path}/actual.json ${path}/expected.json`)
79
89
  {
80
90
  const editor = runtime.process.env.EDITOR || 'vimdiff'
@@ -148,7 +158,7 @@ const writeTestFile = (fn, tests) => {
148
158
  runtime.fs.writeFileSync(fn, stringify(tests, { space: 2 }), { encoding: 'utf8', flag: 'w+' })
149
159
  }
150
160
 
151
- const writeTest = (fn, query, objects, generated, paraphrases, responses, contexts, associations, metadata, config, saveDeveloper, paraphrasesParenthesized, generatedParenthesized) => {
161
+ const writeTest = (fn, query, objects, generated, paraphrases, responses, contexts, associations, metadata, config, saveDeveloper, paraphrasesParenthesized, generatedParenthesized, summaries) => {
152
162
  let tests = []
153
163
  if (runtime.fs.existsSync(fn)) {
154
164
  tests = JSON.parse(runtime.fs.readFileSync(fn))
@@ -160,6 +170,7 @@ const writeTest = (fn, query, objects, generated, paraphrases, responses, contex
160
170
  // tests[query] = sortJson({ paraphrases, responses, contexts, objects: convertToStable(objects), associations, metadata, config, developerTest: saveDeveloper }, { depth: 25 })
161
171
  const results = sortJson({
162
172
  query,
173
+ summaries,
163
174
  paraphrases,
164
175
  responses,
165
176
  contexts,
@@ -276,7 +287,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
276
287
  data.errors_ignore_contextual_priorities_non_existant_ops = true
277
288
  }
278
289
  let queries = query.split('\\n')
279
-
290
+ const summaries = [] // for error
280
291
  try {
281
292
  const response = {
282
293
  hierarchy: [],
@@ -294,7 +305,8 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
294
305
  paraphrasesParenthesized: [],
295
306
  generatedParenthesized: [],
296
307
  responses: [],
297
- associations: []
308
+ associations: [],
309
+ summaries: []
298
310
  }
299
311
 
300
312
  let startCounter = 0
@@ -326,7 +338,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
326
338
  }
327
339
  }
328
340
  json.contexts = json.results
329
- startCounter= json.end_counter + 1
341
+ startCounter = json.end_counter + 1
330
342
  delete json.results
331
343
  if (json.status !== 200) {
332
344
  throw json
@@ -335,6 +347,8 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
335
347
  if (isTest) {
336
348
  start = runtime.performance.performance.now()
337
349
  }
350
+ const summary = { summaries: json.summaries, length: json.contexts.length }
351
+ summaries.push(summary)
338
352
  const { contextsPrime, generatedPrime, paraphrasesPrime, paraphrasesParenthesizedPrime, generatedParenthesizedPrime, responsesPrime } =
339
353
  await processContextsB({ isTest, rebuildingTemplate, config, hierarchy, json, commandLineArgs /*, generators, semantics */ })
340
354
  if (isTest) {
@@ -363,8 +377,8 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
363
377
  response.paraphrasesParenthesized = response.paraphrasesParenthesized.concat(paraphrasesParenthesizedPrime)
364
378
  response.generatedParenthesized = response.generatedParenthesized.concat(generatedParenthesizedPrime)
365
379
  response.responses = response.responses.concat(responsesPrime)
380
+ response.summaries.push(summary)
366
381
  queries = queries.slice(1)
367
-
368
382
  }
369
383
  }
370
384
 
@@ -375,11 +389,12 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
375
389
  for (const km of config.configs) {
376
390
  saveObjects.nameToUUID[km.name] = km.uuid
377
391
  }
378
- writeTest(testsFN, query, saveObjects, response.generated, response.paraphrases, response.responses, response.contexts, response.associations, response.metadata, actual_config, saveDeveloper, response.paraphrasesParenthesized, response.generatedParenthesized)
392
+ writeTest(testsFN, query, saveObjects, response.generated, response.paraphrases, response.responses, response.contexts, response.associations, response.metadata, actual_config, saveDeveloper, response.paraphrasesParenthesized, response.generatedParenthesized, response.summaries)
379
393
  }
380
394
 
381
395
  return response
382
396
  } catch (error) {
397
+ error.summaries = summaries
383
398
  error.query = query
384
399
  errorHandler(error)
385
400
  }
@@ -397,7 +412,7 @@ const getConfigForTest = (config, testConfig) => {
397
412
  configForTest.words = {
398
413
  literals: {},
399
414
  patterns: [],
400
- hierarchy: [],
415
+ hierarchy: []
401
416
  }
402
417
 
403
418
  const literals = config.config.words.literals
@@ -427,7 +442,7 @@ const getConfigForTest = (config, testConfig) => {
427
442
  if (Array.isArray(includes.operators)) {
428
443
  include = (operator) => includes.operators.includes(operator.pattern)
429
444
  }
430
- configForTest.operators = config.config.operators.filter( include ).map((operator) => Object.assign({}, operator, { uuid: undefined }))
445
+ configForTest.operators = config.config.operators.filter(include).map((operator) => Object.assign({}, operator, { uuid: undefined }))
431
446
  } else if (key === 'bridges') {
432
447
  let include = (operator) => true
433
448
  if (Array.isArray(includes.bridges)) {
@@ -441,7 +456,7 @@ const getConfigForTest = (config, testConfig) => {
441
456
  return configForTest
442
457
  }
443
458
 
444
- const runTest = async (config, expected, { args, verbose, testConfig, debug, timings={ server: 0, client: 0 } }) => {
459
+ const runTest = async (config, expected, { args, verbose, testConfig, debug, timings = { server: 0, client: 0 } }) => {
445
460
  const test = expected.query
446
461
  if (args.query && args.query != test) {
447
462
  // no run this
@@ -460,7 +475,7 @@ const runTest = async (config, expected, { args, verbose, testConfig, debug, tim
460
475
  defaultErrorHandler(error)
461
476
  }
462
477
 
463
- let objects = getObjects(config.config.objects)(config.uuid)
478
+ const objects = getObjects(config.config.objects)(config.uuid)
464
479
  try {
465
480
  const result = await _process(config, test, { errorHandler, isTest: true })
466
481
  result.query = test
@@ -539,7 +554,8 @@ const runTest = async (config, expected, { args, verbose, testConfig, debug, tim
539
554
  checked: expected_checked,
540
555
  checkedContexts: pickedExpectedContexts,
541
556
  objects: expected_objects,
542
- config: expected.config
557
+ config: expected.config,
558
+ summaries: expected.summaries
543
559
  },
544
560
  actual: {
545
561
  responses: result.responses,
@@ -550,7 +566,8 @@ const runTest = async (config, expected, { args, verbose, testConfig, debug, tim
550
566
  checked: actual_checked,
551
567
  checkedContexts: pickedResultContexts,
552
568
  objects: actual_objects,
553
- config: actual_config
569
+ config: actual_config,
570
+ summaries: result.summaries
554
571
  }
555
572
  }
556
573
  }
@@ -609,7 +626,7 @@ const saveTest = async (testFile, config, test, expected, testConfig, saveDevelo
609
626
  for (const km of config.configs) {
610
627
  saveObjects.nameToUUID[km.name] = km.uuid
611
628
  }
612
- writeTest(testFile, test, saveObjects, result.generated, result.paraphrases, result.responses, result.contexts, result.associations, result.metadata, actualConfig, saveDeveloper, result.paraphrasesParenthesized, result.generatedParenthesized)
629
+ writeTest(testFile, test, saveObjects, result.generated, result.paraphrases, result.responses, result.contexts, result.associations, result.metadata, actualConfig, saveDeveloper, result.paraphrasesParenthesized, result.generatedParenthesized, result.summaries)
613
630
  }
614
631
 
615
632
  const saveTestsHelper = async (testFile, config, tests, todo, testConfig, saveDeveloper) => {
@@ -768,13 +785,13 @@ const printContextualPrioritiesAmbiguities = (cpa) => {
768
785
  console.log(` Counter ${counter}`)
769
786
  for (const choices of cpa[counter]) {
770
787
  console.log(' [')
771
- for (const choice of choices) {
772
- console.log(' [')
773
- for (const element of choice) {
774
- console.log(` ${JSON.stringify(element)},`)
775
- }
776
- console.log(' ],')
788
+ for (const choice of choices) {
789
+ console.log(' [')
790
+ for (const element of choice) {
791
+ console.log(` ${JSON.stringify(element)},`)
777
792
  }
793
+ console.log(' ],')
794
+ }
778
795
  console.log(' ],')
779
796
  }
780
797
  }
@@ -873,7 +890,7 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
873
890
  console.log('')
874
891
  const screen_width = process.stdout.columns
875
892
  // || 0 for when running without a console
876
- const widths = [70, 10, Math.max(80, screen_width-71 || 0)]
893
+ const widths = [70, 10, Math.max(80, screen_width - 71 || 0)]
877
894
  const lines = new Lines(widths)
878
895
  lines.setElement(0, 0, '--- The paraphrases are ----------')
879
896
  lines.setElement(0, 2, '--- The response strings are ----------')
@@ -904,12 +921,13 @@ const defaultProcess = ({ config, errorHandler }) => async (promise) => {
904
921
  }
905
922
 
906
923
  // builtTemplate saveInstance
907
- const rebuildTemplate = async ({ config, target, previousResultss, startOfChanges, template, errorHandler = defaultErrorHandler }) => {
924
+ const rebuildTemplate = async ({ config, instance, target, previousResultss, rebuild, startOfChanges, template, errorHandler = defaultErrorHandler }) => {
908
925
  const accumulators = {
909
926
  resultss: [],
910
927
  fragments: [],
911
928
  semantics: [],
912
929
  associations: [],
930
+ summaries: [],
913
931
  learned_contextual_priorities: []
914
932
  }
915
933
  config.fragmentsBeingBuilt = []
@@ -922,7 +940,7 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
922
940
  // queries are strings or { query: "blah", development: true/false }
923
941
  if (typeof queryOrExtraConfig === 'string' || queryOrExtraConfig.query || queryOrExtraConfig.isFragment) {
924
942
  let query = queryOrExtraConfig
925
- let isFragment = queryOrExtraConfig.isFragment
943
+ const isFragment = queryOrExtraConfig.isFragment
926
944
  if (typeof queryOrExtraConfig === 'string') {
927
945
  query = { query }
928
946
  }
@@ -943,12 +961,28 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
943
961
  try {
944
962
  let results
945
963
  let prMessage = ''
946
- if (previousResults && previousResults.query == query.query) {
964
+ const suggestFix = (newSummaries) => {
965
+ if (!previousResults) {
966
+ return
967
+ }
968
+ const suggestion = suggestAssociationsFixFromSummaries(previousResults.summaries, newSummaries)
969
+ if (suggestion.length > 0) {
970
+ console.log(getSuggestionMessage(suggestion))
971
+ }
972
+ }
973
+ if (!rebuild && previousResults && previousResults.query == query.query) {
947
974
  results = previousResults
948
975
  prMessage = ' Using previous results. use -rtf for a hard rebuild of everything on the server side.'
949
976
  await loadInstance(config, { resultss: [results] })
950
977
  } else {
951
- results = await _process(config, query.query, { initializer, rebuildingTemplate: true })
978
+ try {
979
+ results = await _process(config, query.query, { initializer, rebuildingTemplate: true })
980
+ } catch (e) {
981
+ if (e.summaries && e.summaries.length > 0) {
982
+ suggestFix(e.summaries)
983
+ }
984
+ throw e
985
+ }
952
986
  }
953
987
  if (config.config.debug) {
954
988
  // TODO pass in the error handler like the other ones
@@ -956,9 +990,11 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
956
990
  }
957
991
  if (results.contexts.length > 1) {
958
992
  console.log(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
993
+ suggestFix(results.summaries)
959
994
  throw new Error(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
960
995
  } else if (results.paraphrases[0].toLowerCase() !== query.query.toLowerCase()) {
961
996
  console.log(`query "${query.query}". The paraphrase is different from the query "${results.paraphrases[0]}".${prMessage}`)
997
+ // suggestFix(results.summaries)
962
998
  } else {
963
999
  console.log(`query ${isFragment ? 'fragment' : ''}"${query.query}".${prMessage}`)
964
1000
  }
@@ -973,6 +1009,7 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
973
1009
  if (isFragment) {
974
1010
  config.fragmentsBeingBuilt.push({ query: query.query, contexts: results.contexts })
975
1011
  }
1012
+ accumulators.summaries = accumulators.summaries.concat(results.summaries)
976
1013
  accumulators.associations = accumulators.associations.concat(results.associations)
977
1014
  accumulators.learned_contextual_priorities = accumulators.learned_contextual_priorities.concat(results.learned_contextual_priorities)
978
1015
  await looper(configs)
@@ -1065,16 +1102,31 @@ const rebuildTemplate = async ({ config, target, previousResultss, startOfChange
1065
1102
  }
1066
1103
  let todo = []
1067
1104
  todo = todo.concat((template.initializers || []).map((query) => { return { initializer: true, property: 'resultss', query, skipSemantics: false || query.skipSemantics } }))
1105
+ /*
1068
1106
  todo = todo.concat((template.configs || []).map((query, index) => {
1069
1107
  let pr
1070
- if (index < startOfChanges) {
1108
+ if (index < startOfChanges || (!startOfChanges && index < previousResultss.length)) {
1071
1109
  pr = previousResultss[index]
1072
1110
  }
1073
1111
  return { property: 'resultss', query, previousResults: pr, skipSemantics: false || query.skipSemantics }
1074
1112
  }))
1075
- todo = todo.concat((template.fragments || []).map((query) => { return Object.assign({}, toProperties(query), { property: 'fragments', skipSemantics: false }) }))
1076
- todo = todo.concat((template.semantics || []).map((definition) => { return { property: 'semantics', query: `${definition.from}\n${definition.to}`, skipSemantics: true } }))
1077
- await looper(Object.assign([], todo))
1113
+ */
1114
+ if (template.configs) {
1115
+ for (let configsIndex = 0; configsIndex < template.configs.length; ++configsIndex) {
1116
+ const query = template.configs[configsIndex]
1117
+ // account for things for example associations being added to the config while debugginer
1118
+ const pr = previousResultss.find((pr) => pr.query == query)
1119
+ todo.push({ property: 'resultss', query, previousResults: pr, skipSemantics: false || query.skipSemantics })
1120
+ }
1121
+ }
1122
+ todo = todo.concat((template.fragments || []).map((query, index) => {
1123
+ const pr = instance.fragments[index]
1124
+ return Object.assign({}, toProperties(query), { property: 'fragments', previousResults: pr, skipSemantics: false })
1125
+ }))
1126
+ todo = todo.concat((template.semantics || []).map((definition) => {
1127
+ return { property: 'semantics', query: `${definition.from}\n${definition.to}`, skipSemantics: true }
1128
+ }))
1129
+ await looper([...todo])
1078
1130
  }
1079
1131
 
1080
1132
  const checkTemplate = (template) => {
@@ -1096,14 +1148,14 @@ const checkTest = (testConfig) => {
1096
1148
  if (!testConfig.contents) {
1097
1149
  throw new Error("The 'test' property is missing the 'contents' property that contains contents of the '<km>.test.json' file")
1098
1150
  }
1099
- if (testConfig.checks?.context && typeof testConfig.checks.context == 'function') {
1151
+ if (testConfig.checks?.context && typeof testConfig.checks.context === 'function') {
1100
1152
  throw new Error(`The 'test.check.context' property should not be a function for ${testConfig.name}. If you are using defaultContextCheck then do this defaultContextCheck().`)
1101
1153
  }
1102
1154
  }
1103
1155
 
1104
1156
  const knowledgeModuleImpl = async ({
1105
1157
  includes,
1106
- config : configStruct,
1158
+ config: configStruct,
1107
1159
  api,
1108
1160
  initializer,
1109
1161
  terminator,
@@ -1248,7 +1300,7 @@ const knowledgeModuleImpl = async ({
1248
1300
  }
1249
1301
 
1250
1302
  config = await createConfig()
1251
-
1303
+
1252
1304
  // dont debug the load of the KM's if rebuild template is on since we want to debug the template rebuild not the load
1253
1305
  if (args.rebuildTemplate) {
1254
1306
  global.pauseDebugging = true
@@ -1398,7 +1450,7 @@ const knowledgeModuleImpl = async ({
1398
1450
  // { literals: Object, patterns: Array(2), hierarchy: Array(97) }
1399
1451
  console.log('literals')
1400
1452
  for (const word in config.config.words.literals) {
1401
- console.log(' ' + word.concat(...config.config.words.literals[word].map((def, i) => ((i > 0) ? ' '.repeat(4+word.length) : ' ') + JSON.stringify(def) + '\n')))
1453
+ console.log(' ' + word.concat(...config.config.words.literals[word].map((def, i) => ((i > 0) ? ' '.repeat(4 + word.length) : ' ') + JSON.stringify(def) + '\n')))
1402
1454
  }
1403
1455
  console.log('patterns')
1404
1456
  for (const pattern of config.config.words.patterns) {
@@ -1567,19 +1619,23 @@ const knowledgeModuleImpl = async ({
1567
1619
  }
1568
1620
  }
1569
1621
 
1570
-
1571
1622
  console.log(`Total Server Time: ${timings.server.toFixed(2)}. Total Client Time: ${timings.client.toFixed(2)}`)
1572
1623
  if (hasError) {
1573
1624
  console.log('**************************** ERRORS ************************')
1574
1625
  for (const result of results) {
1575
1626
  console.log('Utterance: ', result.utterance)
1576
- const show = (label, expected, actual) => {
1627
+ if (!result.hasError) {
1628
+ continue
1629
+ }
1630
+ const show = (label, expected, actual, { console_log = true } = {}) => {
1577
1631
  if (JSON.stringify(expected) !== JSON.stringify(actual)) {
1578
- if (!headerShown) {
1579
- console.log(' Failure')
1632
+ if (console_log) {
1633
+ if (!headerShown) {
1634
+ console.log(' Failure')
1635
+ }
1636
+ console.log(` expected ${label}`, expected)
1637
+ console.log(` actual ${label} `, actual)
1580
1638
  }
1581
- console.log(` expected ${label}`, expected)
1582
- console.log(` actual ${label} `, actual)
1583
1639
  newError = true
1584
1640
  headerShown = true
1585
1641
  if (args.vimdiff) {
@@ -1588,6 +1644,44 @@ const knowledgeModuleImpl = async ({
1588
1644
  result.hasError = true
1589
1645
  }
1590
1646
  }
1647
+ if (!deepEqual(result.expected.summaries, result.actual.summaries)) {
1648
+ /*
1649
+ const suggestion = suggestAssociationsFix(result.expected.summaries, result.actual.summaries)
1650
+ let suggestedFix
1651
+ if (suggestion) {
1652
+ suggestedFix = suggestion
1653
+ console.log(`Try adding this to the associations: { context: ${JSON.stringify(getSuggestion(suggestedFix))}, choose: <indexOfMainElement> }`)
1654
+ }
1655
+ */
1656
+
1657
+ const checkForFix = () => {
1658
+ for (let iDiff = 0; iDiff < result.expected.paraphrases.length; ++iDiff) {
1659
+ if (result.expected.paraphrases[iDiff] !== result.actual.paraphrases[iDiff]) {
1660
+ // const context = result.expected.contexts[iDiff]
1661
+ let lengths = 0
1662
+ // just check where the results differ since earlier summaries can be different but dont matter if the result is the same
1663
+ for (let iSummaries = 0; iSummaries < result.expected.summaries.length; ++iSummaries) {
1664
+ const summary = result.expected.summaries[iSummaries]
1665
+ lengths += summary.length
1666
+ if (lengths > iDiff) {
1667
+ const suggestion = suggestAssociationsFix(result.expected.summaries[iSummaries].summaries, result.actual.summaries[iSummaries].summaries)
1668
+ if (suggestion) {
1669
+ suggestedFix = suggestion
1670
+ // console.log(`Try adding this to the associations: { context: ${JSON.stringify(getSuggestion(suggestedFix))}, choose: <indexOfMainElement> },`)
1671
+ console.log(getSuggestionMessage(suggestedFix))
1672
+ return
1673
+ }
1674
+ }
1675
+ }
1676
+ }
1677
+ }
1678
+ }
1679
+ checkForFix()
1680
+
1681
+ // find the context where the different is
1682
+ // select the first diff that has a different operator in the range
1683
+ // show that
1684
+ }
1591
1685
  show('paraphrases', result.expected.paraphrases, result.actual.paraphrases)
1592
1686
  if (!args.testNoParenthesized) {
1593
1687
  show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
@@ -1723,7 +1817,7 @@ const knowledgeModuleImpl = async ({
1723
1817
  })
1724
1818
  f()
1725
1819
  } else if (args.query) {
1726
- let useTestConfig = testConfig
1820
+ const useTestConfig = testConfig
1727
1821
  if (args.testModuleName) {
1728
1822
  config.testConfig.testModuleName = args.testModuleName
1729
1823
  config.testConfig.checks = config.getConfigs()[args.testModuleName].getTestConfig().checks
@@ -1751,7 +1845,6 @@ const knowledgeModuleImpl = async ({
1751
1845
  const initConfig = async (config) => {
1752
1846
  if (template) {
1753
1847
  if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess }).needsRebuild) {
1754
- debugger
1755
1848
  config.needsRebuild(template.template, template.instance, { isModule: !isProcess })
1756
1849
  const error = `This module "${config.name}" cannot be used because the instance file needs rebuilding. Run on the command line with no arguments or the -rt argument to rebuild.`
1757
1850
  throw new Error(error)
@@ -1855,5 +1948,5 @@ module.exports = {
1855
1948
  gs,
1856
1949
  flattens,
1857
1950
  writeTest,
1858
- getConfigForTest,
1951
+ getConfigForTest
1859
1952
  }
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "devDependencies": {
3
+ "@eslint/js": "^9.21.0",
3
4
  "@typescript-eslint/eslint-plugin": "^4.28.4",
4
5
  "@typescript-eslint/parser": "^4.28.4",
5
- "eslint": "^7.31.0",
6
+ "eslint": "^7.32.0",
6
7
  "eslint-config-standard": "^16.0.3",
7
8
  "eslint-plugin-import": "^2.23.4",
8
9
  "eslint-plugin-node": "^11.1.0",
9
10
  "eslint-plugin-promise": "^5.1.0",
11
+ "globals": "^16.0.0",
10
12
  "jest": "^29.7.0"
11
13
  },
12
14
  "scripts": {
@@ -65,6 +67,6 @@
65
67
  "sort-json": "^2.0.0",
66
68
  "uuid": "^8.3.2"
67
69
  },
68
- "version": "8.9.1",
70
+ "version": "9.0.0",
69
71
  "license": "UNLICENSED"
70
72
  }
package/src/config.js CHANGED
@@ -50,7 +50,8 @@ const debugPriority = (priority) => {
50
50
  }
51
51
  if (global.entodictonDebugPriority) {
52
52
  if (helpers.subPriority(entodictonDebugPriority, priority)) {
53
- debugger // debug hierarchy hit
53
+ // debug hierarchy hit
54
+ debugger // eslint-disable-line no-debugger
54
55
  }
55
56
  }
56
57
  }
@@ -61,7 +62,8 @@ const debugAssociation = (association) => {
61
62
  }
62
63
  if (global.entodictonDebugAssociation) {
63
64
  if (helpers.safeEquals(global.entodictonDebugAssociation, association)) {
64
- debugger // debug association hit
65
+ // debug association hit
66
+ debugger // eslint-disable-line no-debugger
65
67
  }
66
68
  }
67
69
  }
@@ -72,7 +74,8 @@ const debugWord = (word) => {
72
74
  }
73
75
  if (global.entodictonDebugWord) {
74
76
  if (helpers.safeEquals(global.entodictonDebugWord, word)) {
75
- debugger // debug word hit
77
+ // debug word hit
78
+ debugger // eslint-disable-line no-debugger
76
79
  }
77
80
  }
78
81
  }
@@ -83,7 +86,8 @@ const debugHierarchy = (pair) => {
83
86
  }
84
87
  if (global.entodictonDebugHierarchy) {
85
88
  if (helpers.safeEquals(global.entodictonDebugHierarchy, pair)) {
86
- debugger // debug hierarchy hit
89
+ // debug hierarchy hit
90
+ debugger // eslint-disable-line no-debugger
87
91
  }
88
92
  }
89
93
  }
@@ -94,7 +98,8 @@ const debugBridge = (bridge) => {
94
98
  }
95
99
  if (global.entodictonDebugBridge) {
96
100
  if (global.entodictonDebugBridge == bridge.id) {
97
- debugger // debug hierarchy hit
101
+ // debug hierarchy hit
102
+ debugger // eslint-disable-line no-debugger
98
103
  }
99
104
  }
100
105
  }
@@ -105,7 +110,8 @@ const debugOperator = (operator) => {
105
110
  }
106
111
  if (global.entodictonDebugOperator) {
107
112
  if ((operator.pattern || operator) === global.entodictonDebugOperator) {
108
- debugger // debug operator hit
113
+ // debug operator hit
114
+ debugger // eslint-disable-line no-debugger
109
115
  }
110
116
  }
111
117
  }
@@ -119,21 +125,36 @@ const debugConfigProps = (config) => {
119
125
  }
120
126
  const checkProps = [
121
127
  { property: 'priorities', check: (v) => debugPriority(v) },
122
- { property: 'association', check: (v) => debugAssociation(v) },
123
- { property: 'words', check: (v) => debugAssociation(v) },
128
+ { property: 'associations', check: (v) => debugAssociation(v) },
129
+ // TODO implement debugWords
130
+ { property: 'words', check: (v) => debugWords(v) },
124
131
  { property: 'hierarchy', check: (v) => debugHierarchy(v) },
125
132
  { property: 'operators', check: (v) => debugOperator(v) },
126
133
  { property: 'bridges', check: (v) => debugBridge(v) }
127
134
  ]
128
135
  for (const { property, check } of checkProps) {
129
- if (property == 'words') {
136
+ if (property == 'associations') {
137
+ if (config[property]) {
138
+ if (config[property].negative) {
139
+ for (const value of config[property].negative) {
140
+ check(value)
141
+ }
142
+ }
143
+ if (config[property].positive) {
144
+ for (const value of config[property].positive) {
145
+ check(value)
146
+ }
147
+ }
148
+ }
149
+ } else if (property == 'words') {
150
+ /*
130
151
  if (config[property]) {
131
- for (const value in config[property].literals) {
152
+ for (const value of config[property].literals) {
132
153
  check(value)
133
154
  }
134
155
  }
135
- }
136
- else if (config[property]) {
156
+ */
157
+ } else if (config[property]) {
137
158
  for (const value of config[property]) {
138
159
  check(value)
139
160
  }
@@ -174,6 +195,13 @@ const validConfigProps = (config) => {
174
195
  'eqClasses'
175
196
  ]
176
197
  helpers.validProps(valid, config, 'config')
198
+
199
+ // TODO add more type checks
200
+ if (config.associations) {
201
+ if (!config.associations.positive && !config.associations.negative) {
202
+ throw new Error('Expected the \'associations\' property to be a hash with \'positive\' and or \'negative\' properties')
203
+ }
204
+ }
177
205
  }
178
206
 
179
207
  const setupInitializerFNArgs = (config, args) => {
@@ -262,7 +290,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
262
290
  if (bridge.development && config.isModule) {
263
291
  return
264
292
  }
265
- if (!bridge.bridge) {
293
+ if (false && !bridge.bridge) {
266
294
  bridge.bridge = '{ ...next(operator) }'
267
295
  }
268
296
  if (!bridge.level) {
@@ -400,7 +428,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
400
428
  match: (args) => bridge.id == args.context.marker && !!args.context.evaluate == evaluate && match(args),
401
429
  apply: (args) => apply(args),
402
430
  applyWrapped: semantic,
403
- property: evaluate ? 'evaluator':'semantic',
431
+ property: evaluate ? 'evaluator' : 'semantic'
404
432
  }
405
433
  if (addFirst) {
406
434
  config.config.semantics.unshift(addUUID(semanticDef))
@@ -444,7 +472,7 @@ const handleCalculatedProps = (baseConfig, moreConfig, { addFirst, uuid } = {})
444
472
  if (moreConfig.bridges) {
445
473
  moreConfig.bridges = moreConfig.bridges.map((bridge) => {
446
474
  bridge = { ...bridge }
447
- const valid = ['after', 'before', 'bridge', 'development', 'evaluator', 'evaluators', 'generatorp', 'generatorr', 'generatorpr', 'generators', 'operator', 'id', 'convolution', 'inverted', 'isA', 'children', 'parents',
475
+ const valid = ['after', 'before', 'bridge', 'development', 'return_type_selector', 'evaluator', 'evaluators', 'generatorp', 'generatorr', 'generatorpr', 'generators', 'operator', 'id', 'convolution', 'inverted', 'isA', 'children', 'parents',
448
476
  'level', 'optional', 'selector', 'semantic', 'semantics', 'words', /Bridge$/, 'localHierarchy', 'levelSpecificHierarchy', 'where', 'uuid']
449
477
  helpers.validProps(valid, bridge, 'bridge')
450
478
  handleBridgeProps(baseConfig, bridge, { addFirst, uuid })
@@ -531,7 +559,7 @@ const addWord = (config, uuid) => ({ word, id, initial }) => {
531
559
  config.words = {
532
560
  literals: {},
533
561
  patterns: [],
534
- hierarchy: [],
562
+ hierarchy: []
535
563
  }
536
564
  }
537
565
  const literals = config.words.literals
@@ -562,7 +590,7 @@ const normalizeConfig = (config) => {
562
590
  if (!bridge.level) {
563
591
  bridge.level = 0
564
592
  }
565
- if (!bridge.bridge) {
593
+ if (false && !bridge.bridge) {
566
594
  bridge.bridge = '{ ...next(operator) }'
567
595
  }
568
596
  }
@@ -610,7 +638,7 @@ function setWordsUUIDs (words, uuid) {
610
638
  }
611
639
  const hierarchy = words.hierarchy
612
640
  for (const pair of hierarchy) {
613
- pair.uuid = uuid
641
+ pair.uuid = uuid
614
642
  }
615
643
  }
616
644
 
@@ -938,7 +966,7 @@ class Config {
938
966
  words: {
939
967
  literals: {},
940
968
  patterns: [],
941
- hierarchy: [],
969
+ hierarchy: []
942
970
  }, // Done
943
971
  floaters: [],
944
972
  implicits: [],
@@ -998,7 +1026,7 @@ class Config {
998
1026
  }
999
1027
  }
1000
1028
 
1001
- get semantics() {
1029
+ get semantics () {
1002
1030
  return [...this.config.semantics]
1003
1031
  }
1004
1032
 
@@ -1044,7 +1072,7 @@ class Config {
1044
1072
  // const todo = [...instantiated]
1045
1073
  // const todo = [...instantiated]
1046
1074
  const todo = _.clone(instantiated)
1047
- args = {...args}
1075
+ args = { ...args }
1048
1076
  while (todo.length > 0) {
1049
1077
  const context = todo.pop()
1050
1078
  args.context = context
@@ -1125,18 +1153,18 @@ class Config {
1125
1153
  delete config.where
1126
1154
 
1127
1155
  if (config.words && config.words.hierarchy) {
1128
- config.words.hierarchy = config.words.hierarchy.map( (value) => {
1129
- value = {...value}
1156
+ config.words.hierarchy = config.words.hierarchy.map((value) => {
1157
+ value = { ...value }
1130
1158
  delete value.uuid
1131
1159
  return value
1132
1160
  })
1133
1161
  }
1134
1162
 
1135
1163
  if (config.words && config.words.patterns) {
1136
- config.words.patterns = config.words.patterns.map( (value) => {
1137
- value = {...value}
1138
- value.defs = value.defs.map( (value) => {
1139
- value = {...value}
1164
+ config.words.patterns = config.words.patterns.map((value) => {
1165
+ value = { ...value }
1166
+ value.defs = value.defs.map((value) => {
1167
+ value = { ...value }
1140
1168
  delete value.uuid
1141
1169
  return value
1142
1170
  })
@@ -1173,8 +1201,8 @@ class Config {
1173
1201
  delete bridge.evaluators
1174
1202
  delete bridge.semantic
1175
1203
  delete bridge.semantics
1176
- if (!bridge.bridge) {
1177
- bridge.bridge = "{ ...next(operator) }"
1204
+ if (false && !bridge.bridge) {
1205
+ bridge.bridge = '{ ...next(operator) }'
1178
1206
  }
1179
1207
  return bridge
1180
1208
  })
@@ -1237,7 +1265,7 @@ class Config {
1237
1265
  let hasQueryOrFragment = false
1238
1266
  for (let rest = iq; rest < templateQueries.length; ++rest) {
1239
1267
  const value = templateQueries[rest]
1240
- if (typeof value == 'string' || (value.query && value.isFragment)) {
1268
+ if (typeof value === 'string' || (value.query && value.isFragment)) {
1241
1269
  hasQueryOrFragment = true
1242
1270
  break
1243
1271
  }
@@ -1247,7 +1275,7 @@ class Config {
1247
1275
  startOfChanges = iq
1248
1276
  }
1249
1277
  }
1250
- break;
1278
+ break
1251
1279
  }
1252
1280
  }
1253
1281
 
@@ -1306,7 +1334,7 @@ class Config {
1306
1334
  // TODO fix beforeQuery
1307
1335
  template = { fragments: [], configs: [], ...template }
1308
1336
  template.fragments = template.fragments.concat(this.dynamicFragments)
1309
- await rebuildTemplate({ config: this, target: this.name, previousResultss: options.previousResultss, startOfChanges: options.startOfChanges, beforeQuery: () => {}, template, ...options })
1337
+ await rebuildTemplate({ config: this, instance, target: this.name, startOfChanges: options.startOfChanges, beforeQuery: () => {}, template, ...options, previousResultss: options.previousResultss || instance.resultss })
1310
1338
  } else {
1311
1339
  // no change
1312
1340
  // this.initInstances.push({ ...instance, name: config.name })
@@ -1396,7 +1424,7 @@ class Config {
1396
1424
 
1397
1425
  addHierarchyInternal (edge) {
1398
1426
  debugHierarchy([edge[0], edge[1]])
1399
- // because this is called from the semantics and internally. in the semantics the config can be a pseudo config
1427
+ // because this is called from the semantics and internally. in the semantics the config can be a pseudo config
1400
1428
  // where hierarchy and config.hierarchy do not match
1401
1429
  if (this.hierarchy) {
1402
1430
  this.hierarchy.addEdge(edge)
@@ -1588,7 +1616,7 @@ class Config {
1588
1616
  this.config.words = {
1589
1617
  literals: {},
1590
1618
  patterns: [],
1591
- hierarchy: [],
1619
+ hierarchy: []
1592
1620
  }
1593
1621
  }
1594
1622
  debugWord(word)
@@ -1611,7 +1639,7 @@ class Config {
1611
1639
  this.config.words = {
1612
1640
  literals: {},
1613
1641
  patterns: [],
1614
- hierarchy: [],
1642
+ hierarchy: []
1615
1643
  }
1616
1644
  }
1617
1645
 
@@ -1834,7 +1862,7 @@ class Config {
1834
1862
  let defs = pattern.defs || []
1835
1863
  defs = defs.filter((def) => !def.development)
1836
1864
  if (defs.length !== 0) {
1837
- patternsPrime.push({...pattern, defs})
1865
+ patternsPrime.push({ ...pattern, defs })
1838
1866
  }
1839
1867
  }
1840
1868
  config.words.patterns = patternsPrime
@@ -1849,7 +1877,7 @@ class Config {
1849
1877
  config.words.hierarchy = hierarchyPrime
1850
1878
  }
1851
1879
 
1852
- terminate() {
1880
+ terminate () {
1853
1881
  this.configs.forEach((km) => {
1854
1882
  const config = km.config
1855
1883
  if (!config.terminatorFn) {
@@ -1860,7 +1888,7 @@ class Config {
1860
1888
  })
1861
1889
  }
1862
1890
 
1863
- setTerminator(terminatorFn) {
1891
+ setTerminator (terminatorFn) {
1864
1892
  if (terminatorFn) {
1865
1893
  this.terminatorFn = terminatorFn
1866
1894
  }
@@ -1968,11 +1996,11 @@ class Config {
1968
1996
  this.addedArgss.push(moreArgs)
1969
1997
  }
1970
1998
 
1971
- stop_auto_rebuild() {
1999
+ stop_auto_rebuild () {
1972
2000
  this._stop_auto_rebuild = true
1973
2001
  }
1974
2002
 
1975
- async restart_auto_rebuild() {
2003
+ async restart_auto_rebuild () {
1976
2004
  this._stop_auto_rebuild = false
1977
2005
  await this.rebuild()
1978
2006
  }
@@ -1985,9 +2013,6 @@ class Config {
1985
2013
  Object.assign(args, addedArgs)
1986
2014
  if (getUUIDScoped) {
1987
2015
  const currentGetUUIDScoped = args.getUUIDScoped
1988
- if (!currentGetUUIDScoped) {
1989
- debugger
1990
- }
1991
2016
  args.getUUIDScoped = (uuid) => Object.assign(currentGetUUIDScoped(uuid), getUUIDScoped(uuid))
1992
2017
  }
1993
2018
  }
@@ -2115,7 +2140,6 @@ class Config {
2115
2140
  // TODO add more details
2116
2141
  equal (config) {
2117
2142
  if (JSON.stringify(this.config) != JSON.stringify(config.config)) {
2118
- debugger
2119
2143
  return false
2120
2144
  }
2121
2145
  return true
@@ -2172,9 +2196,6 @@ class Config {
2172
2196
  }
2173
2197
  cp.mapUUIDs(map)
2174
2198
 
2175
- if (cp._uuid == 'concept2') {
2176
- // debugger
2177
- }
2178
2199
  if (options.callInitializers) {
2179
2200
  await cp.rebuild(options) // in copy
2180
2201
  } else {
@@ -2580,8 +2601,6 @@ class Config {
2580
2601
  args.currentConfig.wasInitialized = true
2581
2602
  }
2582
2603
  */
2583
- // debugger
2584
- // greg55
2585
2604
  config.initializerFn(args, { dontCallFn: true })
2586
2605
  initAfterApis.unshift({ config, args })
2587
2606
  if (config._api) {
@@ -2802,6 +2821,7 @@ class Config {
2802
2821
  config.name = toNS(config.name)
2803
2822
  }
2804
2823
  */
2824
+ /*
2805
2825
  if (config.associations) {
2806
2826
  const map = (associations) => {
2807
2827
  return associations.map((association) => {
@@ -2816,6 +2836,7 @@ class Config {
2816
2836
  associations.negative = map(associations.negative)
2817
2837
  }
2818
2838
  }
2839
+ */
2819
2840
 
2820
2841
  if (config.words) {
2821
2842
  const literals = {}
@@ -2975,7 +2996,7 @@ class Config {
2975
2996
  async add (...createConfigs) {
2976
2997
  createConfigs.forEach((createConfig, index) => {
2977
2998
  if (typeof createConfig !== 'function') {
2978
- throw new Error(`Expected add argument number ${index+1} to be a function that constructs the config.`)
2999
+ throw new Error(`Expected add argument number ${index + 1} to be a function that constructs the config. This can happen if you have a loop in your includes. Sorry I am too tired to add a good error message. Good luck! I know you can figure it out. I have confidence in you.`)
2979
3000
  }
2980
3001
  })
2981
3002
 
@@ -3330,5 +3351,5 @@ module.exports = {
3330
3351
  Config,
3331
3352
  config_toServer,
3332
3353
  operatorKey_valid,
3333
- handleBridgeProps,
3354
+ handleBridgeProps
3334
3355
  }
@@ -29,7 +29,7 @@ const gs = (g) => async (contexts, separator, lastSeparator) => {
29
29
  return s
30
30
  }
31
31
 
32
- const isA = (hierarchy) => (child, parent, { strict=false } = {}) => {
32
+ const isA = (hierarchy) => (child, parent, { strict = false } = {}) => {
33
33
  if (!child || !parent) {
34
34
  return false
35
35
  }
@@ -81,7 +81,6 @@ const cleanAssign = (dest, ...srcs) => {
81
81
  }
82
82
 
83
83
  const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
84
-
85
84
  // callId
86
85
  args.calls = new InitCalls(args.isInstance ? `${args.isInstance}#${config.name}` : config.name)
87
86
  if (global.theprogrammablemind && global.theprogrammablemind.loadForTesting) {
@@ -251,6 +250,13 @@ const setupContexts = (rawContexts) => {
251
250
  contexts.push(context)
252
251
  }
253
252
  contexts.push({ marker: 'controlEnd', controlRemove: true })
253
+
254
+ let _index = 0
255
+ const id = (context) => {
256
+ context.context_index = _index
257
+ ++_index
258
+ }
259
+ contexts.forEach(id)
254
260
  return contexts
255
261
  }
256
262
 
@@ -440,5 +446,5 @@ module.exports = {
440
446
  gs,
441
447
  processContextsB,
442
448
  loadInstance,
443
- isA,
449
+ isA
444
450
  }
package/src/digraph.js CHANGED
@@ -17,7 +17,6 @@ class Digraph {
17
17
 
18
18
  // BFS
19
19
  path (from, to) {
20
- debugger
21
20
  const frontier = { [from]: [[]] }
22
21
  const done = new Set()
23
22
  while (Object.keys(frontier).length > 0) {
@@ -132,7 +131,7 @@ class Digraph {
132
131
  for (const node of nodes) {
133
132
  nodeToDescendants[node] = this.descendants(node)
134
133
  }
135
- let minima = new Set()
134
+ const minima = new Set()
136
135
  for (const node of nodes) {
137
136
  let okay = true
138
137
  for (const key of nodeToDescendants[node]) {
@@ -155,18 +154,17 @@ class Digraph {
155
154
  if (nodes.length === 0) {
156
155
  return new Set([])
157
156
  }
158
- debugger
159
- nodes = Array.from(nodes);
157
+ nodes = Array.from(nodes)
160
158
  let common = this.ancestors(nodes[0], { includeSelf: true })
161
159
 
162
160
  for (let i = 1; i < nodes.length; i++) {
163
161
  const ancestors = this.ancestors(nodes[i], { includeSelf: true })
164
162
  common = new Set([...common].filter(x => ancestors.has(x)))
165
163
  if (common.size === 0) {
166
- break;
164
+ break
167
165
  }
168
166
  }
169
- return this.minima(common);
167
+ return this.minima(common)
170
168
  }
171
169
 
172
170
  /*
@@ -185,13 +183,13 @@ class Digraph {
185
183
  this._edges.push([child, parent])
186
184
  }
187
185
 
188
- exists(child, parent) {
186
+ exists (child, parent) {
189
187
  return this._edges.find((edge) => edge[0] == child && edge[1] == parent)
190
188
  }
191
189
 
192
190
  addList (l) {
193
191
  for (let i = 1; i < l.length; ++i) {
194
- if (!this.exists(l[i-1], l[i])) {
192
+ if (!this.exists(l[i - 1], l[i])) {
195
193
  this._edges.push([l[i - 1], l[i]])
196
194
  }
197
195
  }
@@ -1,4 +1,4 @@
1
- const _ = require('lodash')
1
+ const _ = require('lodash')
2
2
 
3
3
  const toA = (edge) => {
4
4
  if (Array.isArray(edge)) {
@@ -92,7 +92,6 @@ class DigraphInternal {
92
92
  ancestors.add(s)
93
93
  }
94
94
  return ancestors
95
-
96
95
  }
97
96
 
98
97
  minima (nodes) {
@@ -101,7 +100,7 @@ class DigraphInternal {
101
100
  for (const node of nodes) {
102
101
  nodeToDescendants[node] = this.descendants(node)
103
102
  }
104
- let minima = new Set()
103
+ const minima = new Set()
105
104
  for (const node of nodes) {
106
105
  let okay = true
107
106
  for (const key of nodeToDescendants[node]) {
@@ -124,17 +123,17 @@ class DigraphInternal {
124
123
  if (nodes.length === 0) {
125
124
  return new Set([])
126
125
  }
127
- nodes = Array.from(nodes);
126
+ nodes = Array.from(nodes)
128
127
  let common = this.ancestors(nodes[0], { includeSelf: true })
129
128
 
130
129
  for (let i = 1; i < nodes.length; i++) {
131
130
  const ancestors = this.ancestors(nodes[i], { includeSelf: true })
132
131
  common = new Set([...common].filter(x => ancestors.has(x)))
133
132
  if (common.size === 0) {
134
- break;
133
+ break
135
134
  }
136
135
  }
137
- return this.minima(common);
136
+ return this.minima(common)
138
137
  }
139
138
 
140
139
  /*
@@ -153,13 +152,13 @@ class DigraphInternal {
153
152
  this._edges.push([child, parent])
154
153
  }
155
154
 
156
- exists(child, parent) {
155
+ exists (child, parent) {
157
156
  return this._edges.findIndex((edge) => edge[0] == child && edge[1] == parent) != -1
158
157
  }
159
158
 
160
159
  addList (l) {
161
160
  for (let i = 1; i < l.length; ++i) {
162
- if (!this.exists(l[i-1], l[i])) {
161
+ if (!this.exists(l[i - 1], l[i])) {
163
162
  this._edges.push([l[i - 1], l[i]])
164
163
  }
165
164
  }
package/src/generators.js CHANGED
@@ -66,7 +66,8 @@ class Generator {
66
66
  const matches = await this.match(args)
67
67
  if ((matches && (options.debug || {}).match) ||
68
68
  callId == this.callId) {
69
- debugger // next line is the matcher
69
+ // next line is the matcher
70
+ debugger // eslint-disable-line no-debugger
70
71
  await this.match(args)
71
72
  }
72
73
  return matches
@@ -118,16 +119,9 @@ class Generator {
118
119
  if (this.property == 'generatorp') {
119
120
  args.g = args.gp
120
121
  }
121
- // if (this.callId) {
122
- // greg
123
- /*
124
- if (callId == 'call11' && this.callId) {
125
- debugger;
126
- }
127
- */
128
122
  if ((options.debug || {}).apply ||
129
123
  callId == this.callId) {
130
- debugger
124
+ debugger // eslint-disable-line no-debugger
131
125
  }
132
126
  return await this._apply(args)
133
127
  }
package/src/helpers.js CHANGED
@@ -27,6 +27,28 @@ function where (goUp = 2) {
27
27
  }
28
28
  }
29
29
 
30
+ function suggestAssociationsFix (esummary, asummary) {
31
+ for (let isummary = 0; isummary < esummary.length; ++isummary) {
32
+ if (!deepEqual(esummary[isummary], asummary[isummary])) {
33
+ return esummary[isummary].operators
34
+ }
35
+ }
36
+ return []
37
+ }
38
+
39
+ function suggestAssociationsFixFromSummaries (esummaries, asummaries) {
40
+ for (let isummaries = 0; isummaries < esummaries.length; ++isummaries) {
41
+ const esummary = esummaries[isummaries].summaries
42
+ const asummary = asummaries[isummaries].summaries
43
+ for (let isummary = 0; isummary < esummary.length; ++isummary) {
44
+ if (!deepEqual(esummary[isummary], asummary[isummary])) {
45
+ return esummary[isummary].operators
46
+ }
47
+ }
48
+ }
49
+ return []
50
+ }
51
+
30
52
  function w (func) {
31
53
  func.where = where(3)
32
54
  return func
@@ -438,4 +460,6 @@ module.exports = {
438
460
  subPriority,
439
461
  where,
440
462
  w,
463
+ suggestAssociationsFix,
464
+ suggestAssociationsFixFromSummaries
441
465
  }
package/src/semantics.js CHANGED
@@ -73,7 +73,8 @@ class Semantic {
73
73
  this.fixUpArgs(args, context)
74
74
  const matches = await this.matcher(args)
75
75
  if (matches && (options.debug || {}).match || args.callId == this.callId) {
76
- debugger // next line is the matcher
76
+ // next line is the matcher
77
+ debugger // eslint-disable-line no-debugger
77
78
  await this.matcher(args)
78
79
  }
79
80
  return matches
@@ -92,10 +93,10 @@ class Semantic {
92
93
  this.fixUpArgs(args, contextPrime)
93
94
 
94
95
  if ((options.debug || {}).apply || args.callId == this.callId) {
95
- debugger
96
+ debugger // eslint-disable-line no-debugger
96
97
  }
97
98
  if (args.breakOnSemantics) {
98
- debugger
99
+ debugger // eslint-disable-line no-debugger
99
100
  }
100
101
  await this._apply(args)
101
102
  return contextPrime
@@ -166,9 +167,6 @@ class Semantics {
166
167
  args.log = (message) => { this.logs.push(message) }
167
168
  for (const isemantic in this.semantics) {
168
169
  const semantic = this.semantics[isemantic]
169
- if (!semantic) {
170
- debugger
171
- }
172
170
  // only one question at a time
173
171
  if (semantic.isQuestion && seenQuestion) {
174
172
  continue
@@ -182,7 +180,7 @@ class Semantics {
182
180
  let deferWasCalled = false
183
181
  const defer = (listener) => {
184
182
  deferred.push({ semantic, listener })
185
- deferWasCalled = true
183
+ deferWasCalled = true
186
184
  }
187
185
  args.defer = defer
188
186
  contextPrime = await semantic.apply(args, context, s, options)