From 04c80e3f126b99a401e7ed61cac9adfdc138e2c7 Mon Sep 17 00:00:00 2001 From: Graham Nelson Date: Thu, 26 May 2022 11:34:26 +0100 Subject: [PATCH] Documented recent semver change for N/YYMMDD extension version numbers --- README.md | 2 +- build.txt | 4 +- docs/inbuild/M-ui.html | 19 +++-- inbuild/Manual/Using Inbuild.w | 18 +++-- inform7/Figures/memory-diagnostics.txt | 64 ++++++++--------- inform7/Figures/timings-diagnostics.txt | 53 +++++++------- .../Documentation/Writing with Inform.txt | 71 ++++++++++++------- 7 files changed, 129 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index 1c161fac9..f1742f1d7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Inform 7 -v10.1.0-beta+6V13 'Krypton' (24 May 2022) +v10.1.0-beta+6V14 'Krypton' (26 May 2022) ## About Inform 7 diff --git a/build.txt b/build.txt index 88c5891d4..3888cc4d9 100644 --- a/build.txt +++ b/build.txt @@ -1,3 +1,3 @@ Prerelease: beta -Build Date: 24 May 2022 -Build Number: 6V13 +Build Date: 26 May 2022 +Build Number: 6V14 diff --git a/docs/inbuild/M-ui.html b/docs/inbuild/M-ui.html index 5d26649a0..66238e5b0 100644 --- a/docs/inbuild/M-ui.html +++ b/docs/inbuild/M-ui.html @@ -93,7 +93,7 @@ what is called an "edition", which in turn is a version of a "work".

For example, perhaps the user has two copies of version 3 of the extension Locksmith by Emily Short, in different places in the file system, and also a further copy of version 4. These are three different "copies", but only two -different "editions", and all are of the same "work". A work — in this case. +different "editions", and all are of the same "work". A work — in this case, Locksmith by Emily Short — is identified by its title, author name and genre — in this case, an Inform extension.

@@ -137,7 +137,7 @@ the software, but it's still helpful. $ inbuild/Tangled/inbuild -graph 'Basic Help Menu.i7x' [c0] Basic Help Menu by Emily Short --use---> [c26] Menus by Emily Short v3 - --use---> [c34] Basic Screen Effects by Emily Short v7.140425 + --use---> [c34] Basic Screen Effects by Emily Short v8

The graph begins at the copy we asked for, and then continues through arrows to other copies. It gives a systematic answer to the question "how do I @@ -176,7 +176,7 @@ resources. --build-> [c0] Menu Time.inform --build-> [c53] Basic Help Menu by Emily Short --use---> [c47] Menus by Emily Short v3 - --use---> [c55] Basic Screen Effects by Emily Short v7.140425 + --use---> [c55] Basic Screen Effects by Emily Short v8 --build-> [f1] Menu Time.inform/Source/story.ni --build-> [c12] BasicInformKit @@ -220,7 +220,7 @@ want to know is: what do I need to use, or to build, something?

     extension: Basic Help Menu by Emily Short
       extension: Menus by Emily Short v3
-        extension: Basic Screen Effects by Emily Short v7.140425
+        extension: Basic Screen Effects by Emily Short v8
 

and applied to our example story gives just:

@@ -244,7 +244,7 @@ to build them. But projectbundle: Menu Time.inform extension: Basic Help Menu by Emily Short extension: Menus by Emily Short v3 - extension: Basic Screen Effects by Emily Short v7.140425 + extension: Basic Screen Effects by Emily Short v8 kit: BasicInformKit extension: Basic Inform by Graham Nelson v1 extension: English Language by Graham Nelson v1 @@ -438,8 +438,13 @@ Inbuild will act on every copy it can find which matches that. For example,

lists all extensions by Eric Eve which Inbuild can see. The legal clauses to specify are title, author, genre and version. Note that version=5.1.1 would match version numbers 5.1.1, 5.1.2, 5.2.0, etc., but not 6 or above: -again, this is following semver conventions. To specify an explicit maximum -and minimum version number, use max and min. For example: +again, this is following semver conventions. (Extensions giving their version +numbers in the old-fashioned format "N/YYMMDD" are read as if N.0.YYMMDD, with +the release date being treated as a patch number: see the Inform language +documentation for examples.) +

+ +

To specify an explicit maximum and minimum version number, use max and min. For example:

diff --git a/inbuild/Manual/Using Inbuild.w b/inbuild/Manual/Using Inbuild.w
index 005ef717f..278015fc7 100644
--- a/inbuild/Manual/Using Inbuild.w	
+++ b/inbuild/Manual/Using Inbuild.w	
@@ -40,7 +40,7 @@ what is called an "edition", which in turn is a version of a "work".
 For example, perhaps the user has two copies of version 3 of the extension
 Locksmith by Emily Short, in different places in the file system, and also
 a further copy of version 4. These are three different "copies", but only two
-different "editions", and all are of the same "work". A work -- in this case.
+different "editions", and all are of the same "work". A work -- in this case,
 Locksmith by Emily Short -- is identified by its title, author name and
 genre -- in this case, an Inform extension.
 
@@ -75,7 +75,7 @@ More ambitiously, we can look at the "graph" of a copy.
 	$ inbuild/Tangled/inbuild -graph 'Basic Help Menu.i7x'
 	[c0] Basic Help Menu by Emily Short
 	  --use---> [c26] Menus by Emily Short v3
-	    --use---> [c34] Basic Screen Effects by Emily Short v7.140425
+	    --use---> [c34] Basic Screen Effects by Emily Short v8
 =
 The graph begins at the copy we asked for, and then continues through arrows
 to other copies. It gives a systematic answer to the question "how do I
@@ -107,7 +107,7 @@ resources.
 	      --build-> [c0] Menu Time.inform
 	        --build-> [c53] Basic Help Menu by Emily Short
 	          --use---> [c47] Menus by Emily Short v3
-	            --use---> [c55] Basic Screen Effects by Emily Short v7.140425
+	            --use---> [c55] Basic Screen Effects by Emily Short v8
 	        --build-> [f1] Menu Time.inform/Source/story.ni
 	        --build-> [c12] BasicInformKit
 =
@@ -145,7 +145,7 @@ The command |-use-needs| applied to our example extension gives:
 = (text as ConsoleText)
 	extension: Basic Help Menu by Emily Short
 	  extension: Menus by Emily Short v3
-	    extension: Basic Screen Effects by Emily Short v7.140425
+	    extension: Basic Screen Effects by Emily Short v8
 =
 and applied to our example story gives just:
 = (text as ConsoleText)
@@ -163,7 +163,7 @@ to build them. But |-build-needs| on our story produces:
 	projectbundle: Menu Time.inform
 	  extension: Basic Help Menu by Emily Short
 	    extension: Menus by Emily Short v3
-	      extension: Basic Screen Effects by Emily Short v7.140425
+	      extension: Basic Screen Effects by Emily Short v8
 	  kit: BasicInformKit
 	    extension: Basic Inform by Graham Nelson v1
 	    extension: English Language by Graham Nelson v1
@@ -320,8 +320,12 @@ lists all the kits which Inbuild can see; and
 lists all extensions by Eric Eve which Inbuild can see. The legal clauses to
 specify are |title|, |author|, |genre| and |version|. Note that |version=5.1.1|
 would match version numbers 5.1.1, 5.1.2, 5.2.0, etc., but not 6 or above:
-again, this is following semver conventions. To specify an explicit maximum
-and minimum version number, use |max| and |min|. For example:
+again, this is following semver conventions. (Extensions giving their version
+numbers in the old-fashioned format "N/YYMMDD" are read as if N.0.YYMMDD, with
+the release date being treated as a patch number: see the Inform language
+documentation for examples.)
+
+To specify an explicit maximum and minimum version number, use |max| and |min|. For example:
 = (text as ConsoleText)
 	-matching 'genre=extension,author=Emily Short,title=Locksmith,min=6.1-alpha.2,max=17.2'
 =
diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt
index 2b241403a..dc76515a8 100644
--- a/inform7/Figures/memory-diagnostics.txt
+++ b/inform7/Figures/memory-diagnostics.txt
@@ -1,47 +1,47 @@
-Total memory consumption was 123375K = 120 MB
+Total memory consumption was 129432K = 126 MB
 
  ---- was used for 2044964 objects, in 362887 frames in 0 x 800K = 0K = 0 MB:
 
-    33.0%  inter_tree_node_array                    58 x 8192 = 475136 objects, 41813824 bytes
-    20.5%  text_stream_array                        4605 x 100 = 460500 objects, 25935360 bytes
-    19.2%  linked_list                              43461 objects, 24338160 bytes
-    11.1%  inter_symbol_array                       132 x 1024 = 135168 objects, 14061696 bytes
-    10.4%  inter_error_stash_array                  101 x 1024 = 103424 objects, 13241504 bytes
-     8.2%  parse_node                               129722 objects, 10377760 bytes
-     5.8%  verb_conjugation                         160 objects, 7425280 bytes
-     4.3%  parse_node_annotation_array              346 x 500 = 173000 objects, 5547072 bytes
-     2.6%  pcalc_prop_array                         25 x 1000 = 25000 objects, 3400800 bytes
-     2.5%  inter_name_array                         67 x 1000 = 67000 objects, 3218144 bytes
-     2.0%  kind_array                               66 x 1000 = 66000 objects, 2642112 bytes
-     1.6%  inter_name_generator_array               51 x 1000 = 51000 objects, 2041632 bytes
+    31.5%  inter_tree_node_array                    58 x 8192 = 475136 objects, 41813824 bytes
+    19.5%  text_stream_array                        4605 x 100 = 460500 objects, 25935360 bytes
+    18.3%  linked_list                              43461 objects, 24338160 bytes
+    10.6%  inter_symbol_array                       132 x 1024 = 135168 objects, 14061696 bytes
+     9.9%  inter_error_stash_array                  101 x 1024 = 103424 objects, 13241504 bytes
+     7.8%  parse_node                               129722 objects, 10377760 bytes
+     5.6%  verb_conjugation                         160 objects, 7425280 bytes
+     4.1%  parse_node_annotation_array              346 x 500 = 173000 objects, 5547072 bytes
+     2.5%  pcalc_prop_array                         25 x 1000 = 25000 objects, 3400800 bytes
+     2.4%  inter_name_array                         67 x 1000 = 67000 objects, 3218144 bytes
+     1.9%  kind_array                               66 x 1000 = 66000 objects, 2642112 bytes
+     1.5%  inter_name_generator_array               51 x 1000 = 51000 objects, 2041632 bytes
      1.5%  inter_schema_token                       13969 objects, 2011536 bytes
      1.4%  package_request                          21153 objects, 1861464 bytes
-     1.4%  vocabulary_entry_array                   161 x 100 = 16100 objects, 1808352 bytes
-     1.2%  dict_entry_array                         470 x 100 = 47000 objects, 1519040 bytes
+     1.3%  vocabulary_entry_array                   161 x 100 = 16100 objects, 1808352 bytes
+     1.1%  dict_entry_array                         470 x 100 = 47000 objects, 1519040 bytes
      1.1%  match_trie_array                         11 x 1000 = 11000 objects, 1496352 bytes
      1.1%  inter_symbols_table                      26592 objects, 1489152 bytes
      1.0%  i6_schema_array                          23 x 100 = 2300 objects, 1380736 bytes
-     1.0%  scan_directory                           314 objects, 1296192 bytes
-     1.0%  inter_package                            26592 objects, 1276416 bytes
+     0.9%  scan_directory                           314 objects, 1296192 bytes
+     0.9%  inter_package                            26592 objects, 1276416 bytes
      0.8%  map_data                                 671 objects, 1127280 bytes
      0.8%  id_body                                  942 objects, 1077648 bytes
      0.7%  adjective_meaning                        202 objects, 1000304 bytes
      0.7%  excerpt_meaning                          3102 objects, 967824 bytes
-     0.7%  production                               3878 objects, 899696 bytes
+     0.6%  production                               3878 objects, 899696 bytes
      0.6%  ptoken                                   8397 objects, 873288 bytes
      0.6%  grammatical_usage                        3613 objects, 867120 bytes
      0.6%  individual_form                          2563 objects, 861168 bytes
      0.6%  inter_schema_node                        8920 objects, 856320 bytes
-     0.5%  unary_predicate_array                    16 x 1000 = 16000 objects, 640512 bytes
+     0.4%  unary_predicate_array                    16 x 1000 = 16000 objects, 640512 bytes
      0.3%  local_variable_array                     47 x 100 = 4700 objects, 452704 bytes
-     0.3%  verb_usage                               1128 objects, 388032 bytes
+     0.2%  verb_usage                               1128 objects, 388032 bytes
      0.2%  rule                                     470 objects, 368480 bytes
      0.2%  dictionary                               7520 objects, 360960 bytes
      0.2%  verb_form                                386 objects, 348944 bytes
      0.2%  noun                                     2382 objects, 285840 bytes
      0.2%  compilation_subtask                      3355 objects, 268400 bytes
-     0.2%  inter_annotation_array                   2 x 8192 = 16384 objects, 262208 bytes
-     0.2%  inference_subject                        666 objects, 261072 bytes
+     0.1%  inter_annotation_array                   2 x 8192 = 16384 objects, 262208 bytes
+     0.1%  inference_subject                        666 objects, 261072 bytes
      0.1%  vanilla_function                         3683 objects, 235712 bytes
      0.1%  binary_predicate                         322 objects, 170016 bytes
      0.1%  hierarchy_location                       1122 objects, 161568 bytes
@@ -237,23 +237,23 @@ Total memory consumption was 123375K = 120 MB
 
 100.0% was used for memory not allocated for objects:
 
-    57.7%  text stream storage                      72934504 bytes in 478023 claims
-     4.1%  dictionary storage                       5228544 bytes in 7520 claims
+    59.7%  text stream storage                      79137048 bytes in 478471 claims
+     3.9%  dictionary storage                       5228544 bytes in 7520 claims
      ----  sorting                                  1448 bytes in 149 claims
-     5.6%  source text                              7200000 bytes in 3 claims
-     8.5%  source text details                      10800000 bytes in 2 claims
-     0.2%  documentation fragments                  262144 bytes in 1 claim
+     5.4%  source text                              7200000 bytes in 3 claims
+     8.1%  source text details                      10800000 bytes in 2 claims
+     0.1%  documentation fragments                  262144 bytes in 1 claim
      ----  linguistic stock array                   81920 bytes in 2 claims
      ----  small word set array                     105600 bytes in 22 claims
-     3.5%  inter symbols storage                    4520272 bytes in 27949 claims
-    13.2%  inter bytecode storage                   16767680 bytes in 14 claims
-     4.9%  inter links storage                      6222976 bytes in 11 claims
+     3.4%  inter symbols storage                    4520272 bytes in 27949 claims
+    12.6%  inter bytecode storage                   16767680 bytes in 14 claims
+     4.6%  inter links storage                      6222976 bytes in 11 claims
      0.1%  inter tree location list storage         191232 bytes in 32 claims
-     1.3%  instance-of-kind counting                1700416 bytes in 1 claim
+     1.2%  instance-of-kind counting                1700416 bytes in 1 claim
      ----  compilation workspace for objects        21896 bytes in 25 claims
      ----  lists for type-checking invocations      16000 bytes in 1 claim
      ----  code generation workspace for objects    1336 bytes in 4 claims
      0.2%  emitter array storage                    280288 bytes in 1999 claims
 
--146.-1% was overhead - -184656920 bytes = -180329K = -176 MB
+-139.-3% was overhead - -184656920 bytes = -180329K = -176 MB
 
diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt
index 000d9171a..684a1a5c8 100644
--- a/inform7/Figures/timings-diagnostics.txt
+++ b/inform7/Figures/timings-diagnostics.txt
@@ -1,32 +1,33 @@
 100.0% in inform7 run
-     71.4% in compilation to Inter
-         50.6% in //Sequence::undertake_queued_tasks//
-          4.6% in //MajorNodes::pre_pass//
+     71.3% in compilation to Inter
+         50.0% in //Sequence::undertake_queued_tasks//
+          4.7% in //MajorNodes::pre_pass//
           3.4% in //MajorNodes::pass_1//
+          2.3% in //RTPhrasebook::compile_entries//
           1.8% in //ImperativeDefinitions::assess_all//
-          1.8% in //RTPhrasebook::compile_entries//
           1.4% in //RTKindConstructors::compile//
-          1.0% in //Sequence::lint_inter//
-          0.6% in //MajorNodes::pass_2//
-          0.6% in //World::stage_V//
-          0.4% in //ImperativeDefinitions::compile_first_block//
-          0.4% in //Sequence::undertake_queued_tasks//
-          0.4% in //Sequence::undertake_queued_tasks//
-          0.2% in //CompletionModule::compile//
-          0.2% in //InferenceSubjects::emit_all//
-          0.2% in //RTKindConstructors::compile_permissions//
-          0.2% in //Task::make_built_in_kind_constructors//
-          3.3% not specifically accounted for
-     25.7% in running Inter pipeline
-         10.0% in step 14/15: generate inform6 -> auto.inf
-          5.7% in step 5/15: load-binary-kits
+          1.1% in //Sequence::lint_inter//
+          0.5% in //ImperativeDefinitions::compile_first_block//
+          0.5% in //MajorNodes::pass_2//
+          0.5% in //Sequence::undertake_queued_tasks//
+          0.5% in //World::stage_V//
+          0.3% in //Sequence::undertake_queued_tasks//
+          0.1% in //CompletionModule::compile//
+          0.1% in //InferenceSubjects::emit_all//
+          0.1% in //RTKindConstructors::compile_permissions//
+          0.1% in //Task::make_built_in_kind_constructors//
+          0.1% in //World::stages_II_and_III//
+          2.7% not specifically accounted for
+     25.8% in running Inter pipeline
+         10.6% in step 14/15: generate inform6 -> auto.inf
+          5.5% in step 5/15: load-binary-kits
           5.3% in step 6/15: make-synoptic-module
           1.4% in step 9/15: make-identifiers-unique
-          0.4% in step 12/15: eliminate-redundant-operations
-          0.4% in step 4/15: compile-splats
-          0.4% in step 7/15: shorten-wiring
-          0.4% in step 8/15: detect-indirect-calls
-          0.2% in step 11/15: eliminate-redundant-labels
-          1.5% not specifically accounted for
-      2.4% in supervisor
-      0.5% not specifically accounted for
+          0.3% in step 12/15: eliminate-redundant-operations
+          0.3% in step 4/15: compile-splats
+          0.3% in step 7/15: shorten-wiring
+          0.3% in step 8/15: detect-indirect-calls
+          0.1% in step 11/15: eliminate-redundant-labels
+          1.3% not specifically accounted for
+      2.3% in supervisor
+      0.4% not specifically accounted for
diff --git a/resources/Documentation/Writing with Inform.txt b/resources/Documentation/Writing with Inform.txt
index b8bae1247..54addfe90 100644
--- a/resources/Documentation/Writing with Inform.txt	
+++ b/resources/Documentation/Writing with Inform.txt	
@@ -17444,7 +17444,7 @@ Extensions are plain text files, and can be created with any text editor. (It is
 
 Extensions look very much like passages of Inform source, because except for a special introductory and concluding sentence, and one convention, that is all they are:
 
-	{*}The Ducking Action by Graham Nelson begins here.
+	{*}The Ducking Action by Beatrix Potter begins here.
 
 	"An action for ducking one's head."
 
@@ -17464,7 +17464,7 @@ Providing a rubric is helpful, because it enables Inform to give a meaningful li
 
 A second double-quoted text can also, optionally, be added in yet a third special starting paragraph. This is to provide additional credits to people who have contributed to this or earlier versions. For instance:
 
-	The Ducking Action by Graham Nelson begins here.
+	The Ducking Action by Beatrix Potter begins here.
 
 	"An action for ducking one's head."
 
@@ -17483,30 +17483,48 @@ Note the typical style here: it's a phrase rather than a sentence, and neither s
 
 As we have seen, extensions are referred to by name and author, but they can also (optionally) be referred to by version. For instance:
 
-	Include version 2 of the Ducking Action by Graham Nelson.
+	Include version 2 of the Ducking Action by Beatrix Potter.
 
-	Version 1/040426 of the Ducking Action by Graham Nelson begins here.
+	Version 1.2.4 of the Ducking Action by Beatrix Potter begins here.
 
-A version number must be a whole number 1, 2, ..., 999 (version 0 is not allowed, and nor are decimal points), optionally followed by a slash '/' and then a six-figure date, in the form YYMMDD: so 040426 means 26 April 2004.
+Version numbers should consist of one to three whole numbers divided by dots, with no negative numbers allowed. Thus "5", "3.3" and "2.1.71652" are all valid as version numbers, but "-4" and "3.1.2.5" are not. Any numbers not specified are taken to be 0: thus "3.3" means the same as "3.3.0", and "5" means the same as "5.0.0".
 
-A request to include version 2 of something implicitly means "version 2 or later", and similarly "version 2/040426" means version 2 with a date of 26 April 2004 or later, or else any version higher than 2. If Inform loads the extension but finds that its version is not good enough, an error is issued.
+In versions of Inform before 2022, versions of extensions were also allowed to be written in the form "N/YYMMDD", as in this example:
 
-Where no version number is quoted, the rule is that an unspecified version predates any numbered version. This means that the line
+	Version 6/040426 of the Ducking Action by Beatrix Potter begins here.
 
-	Include the Ducking Action by Graham Nelson.
+The material after the slash '/' was expected to be a date, so that 040426 would mean 26 April 2004. In order to preserve compatibility with old extensions, Inform continues to allow this notation, but treats it as equivalent to writing "N.0.YYMMDD", though with any leading 0s trimmed. So the above sentence is equivalent to writing:
+
+	Version 6.0.40426 of the Ducking Action by Beatrix Potter begins here.
+
+Extensions are usually intended to be shared and passed around between Inform users, and good use of version numbering can be a huge help to those users; and it's helpful if we can agree as a community on what good version-numbering is. Because of that, the Inform project tries to use a widely-recognised Internet standard called "semantic version numbering".
+
+For full details see semver.org, but for Inform purposes the following fairly simple rules should be enough. "Semantic" just means that version number changes should communicate something meaningful. So, whenever an extension author puts out a new version of an extension, the extension number should change in a way that signals how drastic the change will be.
+
+In this system, the three possible numbers X.Y.Z are called the "major", "minor" and "patch" numbers. Every time an extension is changed and re-released, even just informally among friends but certainly if posted somewhere on the Internet, X, Y or Z should change. The rules are:
+
+(X) If the extension has changed so much that Inform projects using it will need to be changed in order to keep on working - for example, if a "To..." phrase has been taken out, or the name of a kind changed - then X should be increased. Y and Z then usually go back to 0. This is a "major version".
+
+(Y) If the extension provides new features but doesn't do anything to change the way its existing features are used, then X can stay the same but Y should increase, and Z then usually rolls around to 0. This is a "minor version".
+
+(Z) If the extension has changed only to fix bugs, or make its existing features work more efficiently, or provide better documentation or examples, then X and Y can stay the same but Z should increase. This is a "patch version".
+
+So, for example, a user who currently has version 3.2.7 can update to 3.2.8 without really investigating. That same user can update to 3.3, 3.4, ... without any trouble, choosing either to use or ignore whatever new features they are presenting. But the user knows that moving up to version 4 might well require some work - a project using version 3.Y.Z will likely need writing to adopt version 4.
+
+Now let's turn to "Include" sentences. A request like:
+
+	Include the Ducking Action by Beatrix Potter.
 
 will be happy with any version of the extension at all, whether numbered or not; but
 
-	Include version 2 of the Ducking Action by Graham Nelson.
+	Include version 2.4 of the Ducking Action by Beatrix Potter.
 
-will only accept the extension if it has a version number attached (and with that number being 2 or higher).
+will only accept the extension if its version number is "compatible" with 2.4, which means, if it is 2.4 or later, but still belongs to the same major version, "2". So if we write this inclusion sentence, but the version we have installed is version 3.1, Inform will give a problem message. The fix may well be as simple as changing the inclusion sentence to match - but it may not, because a change in major version number is a signal that things have changed a lot inside the extension (see above).
 
 During play of any story compiled by Inform 7, typing VERSION lists various serial numbers of the pieces of software used to make it. The list concludes with names, authors and version numbers of any extensions used. So every author whose work contributes to a story automatically gets a modest credit within it. The same list can be printed, at the discretion of the designer, using the textual substitution:
 
 {defn phs_extcredits}say "[the/-- list of extension credits]"
-This text substitution expands to one or more lines of text crediting each of the extensions used by the current source text, along with their version numbers and authors. Extensions whose authors have chosen the "use authorial modesty" option are missed out. Example:
-
-	Standard Rules version 2/090402 by Graham Nelson
+This text substitution expands to one or more lines of text crediting each of the extensions used by the current source text, along with their version numbers and authors. Extensions whose authors have chosen the "use authorial modesty" option are missed out.
 {end}
 
 If we want our extension to go uncredited - perhaps if it is a low-level enabling sort of thing, for instance - we can place the following sentence inside the definition of the extension:
@@ -17518,10 +17536,7 @@ The same sentence placed in the body of a source text causes all extensions by t
 A complete list, undiluted by modesty, can always be obtained using:
 
 {defn phs_compextcredits}say "[the/-- complete list of extension credits]"
-This text substitution expands to one or more lines of text crediting each of the extensions used by the current source text, along with their version numbers and authors. Every extension is included, even those whose authors have opted for "use authorial modesty". Example:
-
-	Standard Rules version 2/090402 by Graham Nelson
-	Locksmith version 9 by Emily Short
+This text substitution expands to one or more lines of text crediting each of the extensions used by the current source text, along with their version numbers and authors. Every extension is included, even those whose authors have opted for "use authorial modesty".
 {end}
 
 [x] Extensions and story file formats
@@ -17558,15 +17573,21 @@ would ensure that "reveal the explosion" works nicely whichever story file forma
 
 ^^{extensions: writing: including other extensions}
 
-As was mentioned earlier, the same extension is sometimes requested several times. For instance, suppose the main source text asks to include version 2 of extension X, and also to include extension Y. Suppose further that Y contains a request to include version 4 of X. We now have two different requests for X. Inform works out the minimum version number needed to satisfy these requests (in this case 4) and gives an error if the extension it actually loads turns out to be earlier.
+Extensions can themselves contain "Include..." sentences asking for other extensions to be included. An extension might, for example, start like this:
 
-This is true even of the Standard Rules. Suppose that the Standard Rules had recently been republished in version 37, making the previously existing version 36 out of date, and that an extension is written which capitalizes on a new feature in v37. It will therefore not work if people try to use it with v36. All the extension needs to do is to say:
+	Version 1 of Basic Help Menu by Emily Short begins here.
 
-	Include version 37 of the Standard Rules by Graham Nelson.
+	Include Menus by Emily Short.
+	
+	...
 
-to guarantee that v37 or later will be used.
+A project which asks to include "Basic Help Menu" will then also include "Menus", even though the author might never even realise that. Indeed, the author could also have asked to include "Menus", not realising that "Basic Help Menu" was going to ask for the same thing.
 
-If an extension does include other extensions, it should do so in a paragraph immediately following the introductory sentence, so that anyone looking at the file can see these mutual dependencies at a glance.
+So the same extension is often requested multiple times. This is fine if the version numbers in the requests are compatible, but they might not be. For instance, suppose the main source text asks to include version 2 of extension X, and also to include extension Y. Suppose further that Y contains a request to include version 4 of X. We now have two different requests for X, and they contradict each other - the major version of X cannot be both 2 and 4 at the same time. So Inform will produce a problem message in this case.
+
+But in cases where it is possible for everyone to be satisfied, Inform will try to find a solution. If one extension asks for version 2.3 of X, and another asks just for X, and a third asks for version 2.7.2 of X, then Inform will work out that any version number in the range 2.7.2 up to (but not including) 3 will be fine. If it can in fact find such an extension, it will then use it. So if the user has version 2.8.17 installed, everything is fine.
+
+If an extension does include other extensions, it is good style to place the "Include..." sentence(s) as early as possible after the introductory sentence, just so that human readers looking at the text of the extension can see these dependencies easily.
 
 [x] Extensions can interact with other extensions {PM_HeadingInPlaceOfUnincluded} {PM_HeadingInPlaceOfUnknown} {PM_UnequalHeadingInPlaceOf}
 
@@ -17610,11 +17631,7 @@ If the name of the heading to replace contains the word "in", it's a good idea t
 ^^{headings: in extensions}
 ^^{(unindexed), headings in extensions+sourcepart+}
 
-As soon as a project has successfully been translated, its Index is brought up to date: pages of the index record all the kinds and what they are for, all the phrases which can be used, and so on. Any kind or phrase created in an extension is automatically included. The extension's presence in the project is itself recorded - the Contents index for any project contains a brief list of all extensions used in that project, along with their authors and version numbers. For instance:
-
-	Standard Rules version 1/040731
-	Locksmith by Emily Short
-	Tupperware by Emily Short
+As soon as a project has successfully been translated, its Index is brought up to date: pages of the index record all the kinds and what they are for, all the phrases which can be used, and so on. Any kind or phrase created in an extension is automatically included. The extension's presence in the project is itself recorded - the Contents index for any project contains a brief list of all extensions used in that project, along with their authors and version numbers.
 
 The Kinds index aims to give the reader a brief note of what each kind is intended for. We can provide for this by writing a sentence like so: